5.0.24不能修复SQL注入漏洞,因其未增强parseData()的字段名校验逻辑,仍存在数组型exp注入缺陷;必须升级至5.0.16或更高(推荐5.0.25+)才能覆盖官方修复。

直接升级到 5.0.24 不能修复 SQL 注入漏洞——该版本仍存在 parseData() 中的数组型 exp 注入缺陷,必须升至 5.0.16 或更高(推荐 5.0.25+)才能覆盖官方修复。
为什么 5.0.24 不安全?
5.0.24 仅修复了 RCE(远程代码执行)漏洞(如 Request::method() 的 _method 绕过),但未修复 SQL 注入的核心路径:library/think/db/Builder.php 中的 parseData() 方法对 ['exp', 'UPPER(1)'] 类结构仍无字段名校验。漏洞在 5.0.13–5.0.15 引入,5.0.16 首次加入 $key 白名单比对逻辑,而 5.0.24 并未回溯增强该逻辑。
- 实测:在
5.0.24中发送POST /user/add username[0]=exp&username[1]=UPPER(1)仍可触发注入 - 官方补丁记录明确标注“SQL 注入修复起始于 v5.0.16”(见 GitHub commit 0a7c9d8)
-
5.0.23及更早版本甚至存在多条注入链(如parseOrder()调用未同步加固)
升级到哪个版本才算真正修复?
必须满足两个条件之一:
- 升至
5.0.16~5.0.23之间的任一版本 + 手动打补丁(见下节) - 直接升至
5.0.25或更高(5.0.25合并了多轮加固,包括parseField()和parseArrayData()的联动校验)
注意:5.0.x 系列已于 2019 年停止维护,5.0.24 是最后一个带 RCE 修复的“伪安全”版本,但 SQL 注入风险仍在。生产环境应跳过 5.0.24,直上 5.0.25 或迁移到 6.x。
如果卡在 5.0.20 且无法跳版,怎么临时堵住 parseData()?
在 library/think/db/Builder.php 的 parseData() 函数开头插入校验逻辑(适用于 5.0.20):
foreach ($data as $key => $val) {
if (is_array($val) && !empty($val) && $val[0] === 'exp') {
// 拦截非法字段名
if (!in_array($key, ['username', 'email', 'status'], true)) { // 替换为你的实际白名单字段
throw new Exception('Invalid field for exp expression');
}
// 拦截危险表达式内容
if (preg_match('/\b(select|union|updatexml|extractvalue|sleep)\b/i', (string)$val[1])) {
throw new Exception('Suspicious SQL expression');
}
}
}
- 必须同步检查调用
parseData()的方法,如parseOrder()——攻击者常通过order=id|updatexml(0,1,1)绕过 - 该补丁不防
inc/dec类操作,需额外禁用:if ($val[0] === 'inc' || $val[0] === 'dec') { throw new Exception(...); } - 补丁后务必关闭
app_debug = false,否则错误信息可能泄露数据库结构
升级后仍要检查的三个盲点
很多人升级完就以为万事大吉,但以下三点常被忽略:
-
Db::query()或Db::execute()手动拼接语句的地方,不受框架自动修复保护,必须全部改用参数占位符(?) - 自定义查询闭包中用了
whereRaw()或havingRaw(),且参数未绑定(如whereRaw("id = {$id}")) - 前端传参仍保留
a修饰符(如input('data/a')),若后端没做二次白名单过滤,数组绕过风险仍在
最稳妥的做法:升级后全局 grep exp、inc、dec、Raw(、query(,逐个确认上下文是否可控。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











