原文来自—>here
什么是无参数
顾名思义,就是只使用函数,且函数不能带有参数,这里有种种限制:比如我们选择的函数必须能接受其括号内函数的返回值,使用的函数规定必须参数为空或者为一个参数等。
例题讲解
例题:
<?php
highlight_file(__FILE__);
if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])) {
eval($_GET['code']);
}
?>
代码解析:
preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])
这里使用preg_replace
替换匹配到的字符为空,\w
匹配字母、数字和下划线,等价于[^A-Za-z0-9]
,然后(?R)?
这个意思为递归整个匹配模式。
举个例子:
a(b(c()));可以使用,但是a(‘b’)或a(‘b’, ‘c’)的这种含有参数的都不能使用。
所以我们要使用无参数的函数进行文件读取或者命令执行。
无参数任意文件读取
查看当前目录文件名
正常的,print_r(scandir('.'));
可以用来查看当前目录所有文件名。
但是要怎么构造参数里这个点呢,这里介绍几个方法:
-
localeconv()
localeconv()返回一包含本地数字及货币格式信息的数组。而数组第一项就是
.
。
要怎么取到这个点呢,这里就要用到另一个函数:
current()返回数组中的单元,默认取第一个值:
print_r(scandir(current(localeconv())));
成功打印出当前目录下的文件。也可以使用 print_r(scandir(pos(localeconv())));
,poc是current的别名。
如果都被过滤了还可以使用reset(),该函数返回数组第一个单元的值,如果数组为空则返回FALSE。
-
chr(64)
chr(64)就是字符
.
。要构造46,有几个方法:
chr(rand()) #不切实际,看运气 chr(time()) chr(current(localtime(time())))
chr(time()):
chr()函数以256为一个周期,所以chr(46), chr(302), chr(558)都等于
.
,所以使用chr(time()),一个周期必定会出现一次.
。chr(current(localtime(time()))):
数组第一个值每秒+1,所以最多60秒就一定能得到46,用current(pos)就能获得
.
。
……