github编辑

[ISITDTU 2019]EasyPHP

[ISITDTU 2019]EasyPHP

考点

  • 无字符代码执行

wp

<?php
highlight_file(__FILE__);

$_ = @$_GET['_'];
if ( preg_match('/[\x00- 0-9\'"`$&.,|[{_defgops\x7F]+/i', $_) )
    die('rosé will not do it');

if ( strlen(count_chars(strtolower($_), 0x3)) > 0xd )
    die('you are so close, omg');

eval($_);
?>

代码执行,最后一个if不允许使用的字符超过12个

然后输入黑名单如下

到这里想到的绕过方式是异或和取反,然后在返回头看一下PHP版本是7.3,那就可以用函数执行的特性结合取反

phpinfo取反为%8F%97%8F%96%91%99%90,PHP7函数执行(~%8F%97%8F%96%91%99%90)();,长度为10

看到disable_functions

但是有字符使用的限制,所以还是要考虑其他方式。以前p牛说过无字符getshell可以用自增、位运算和取反,再偷一波陆队的思路。

现在可以考虑一下自增。PHP在获取HTTP参数时默认是字符串,然后可以用!进行布尔类型转换,再用@忽略notice输出,就可以把!!@a转化为数字1,然后再用chr()转换拼接就可以构造任意函数,但是需要用.拼接

使用异或,如果用爆破的方法就会很慢,偷一波陆队的思路。先确定自己想执行的语句,比如phpinfo,然后定一个参考字符串,让phpinfo和它异或,就可以得到想要的输入,如果得到的结果不符合要求,再微调参考字符串

结果是%8f%97%8f%96%91%99%90^%ff%ff%ff%ff%ff%ff%ff,脚本如下:

但是这里有个疑问,%21^%4f的结果是n,但是在测试的时候却不对

加上引号就可以了

用数字也是同样的道理,一开始一直报错,但是把数字用trim转换一下就可以了。然后用自增找到数字

结果是AYAXZWZ^1111415

这里如果要求字符种类最少,可以考虑使用%ff的方式,先生成语句,再去尝试找可以替换的字符。如下,共用了16个字符

所以要找到可以替换的,即在内部可以互相异或出来的,目标代码用到的字符为['n', 'p', 'c', 's', 'i', 'a', 't', 'd', 'r', '_', '.'],写个脚本找一下

得到的结果对应如下

找一下就可以找到,原则先找必须存在的字符,比如._,那么a,d,0也必须存在,那么r就必须存在,同样的,对于字符c和d,在生成的URL编码中也有,所以c和d也必须存在,如果换掉,相当于没有做异或,对于n和i而言,哪个都可以,后续不牵扯到6和1,然后看t和s,他们也是哪个都可以,他们URL编码中的b和c都已经存在,最后是a和p,明显a含有的字符更多,要保留p

最后结果

print_r(scandir('.'))

readfile(end(scandir('.')))

小结

最后更新于