ThinkPHP 5.1.25 存在SQL注入漏洞,核心是用户可控数组键名被直接拼入SQL字段位(如insert/update等方法),未校验导致注入;官方已在5.1.26+修复,推荐升级至5.1.31或更高版,暂无法升级则需手动加固parseKey()与parseData()并实施字段白名单校验。

ThinkPHP 5.1.25 存在多个SQL注入漏洞,核心问题在于用户可控的数组键名被直接用于SQL字段名拼接(如 insert、insertAll、update、max、min、order、where 等方法),且未做严格校验。官方已在 5.1.26 版本中修复该系列问题,因此最直接有效的修复方式是升级框架。
升级到安全版本(推荐首选)
5.1.25 的 SQL 注入漏洞已在 5.1.26 及后续版本中修复(如 5.1.31、5.1.40 等)。升级操作简单且彻底:
- 修改
composer.json中的框架依赖:"topthink/framework": "^5.1.31"或更高稳定版 - 执行
composer update topthink/framework - 升级后务必测试关键数据库操作(增删改查、聚合函数、排序等),确认业务逻辑无异常
- 注意:5.1.x 系列已停止官方维护,生产环境建议规划迁移到 ThinkPHP 6.3+ 或 8.0+(LTS 版本)
临时补丁(适用于无法立即升级的场景)
若因兼容性等原因暂不能升级,可对关键类进行手动加固:
- 定位文件:
thinkphp/library/think/db/Builder.php中的parseData()方法,以及thinkphp/library/think/db/builder/Mysql.php中的parseKey() - 在
parseKey()中增加字段名校验逻辑:仅允许字母、数字、下划线,且长度限制在 64 字符内;拒绝含点号(.)、反引号、括号、SQL 关键字等危险字符 - 对
parseData()中循环处理的$data键名,强制调用parseKey()校验,禁止绕过(如二维数组触发INC/DEC表达式时) - 禁用调试模式:
app_debug => false,避免错误信息泄露数据库结构
代码层防御(开发规范必须落实)
框架补丁只是兜底,开发者需主动规避风险写法:
立即学习“PHP免费学习笔记(深入)”;
- 所有数据库操作一律使用参数绑定,避免手拼 SQL;
where()不要用exp表达式接收用户输入 - 用户输入的字段名(如排序字段、分组字段)必须白名单校验:
$allowFields = ['id', 'name', 'create_time'];<br>if (!in_array($orderField, $allowFields)) { throw new Exception('非法字段'); } - 聚合函数(
max、count等)的参数不接受用户直传,应映射为内部字段别名 - 关闭不必要的调试与追踪功能:
app_trace => false,防止报错暴露敏感路径和配置
验证修复是否生效
修复完成后,需主动验证常见攻击链是否失效:
- 尝试复现原始 PoC:
?data[id%60)values(updatexml(1,concat(0x7e,user(),0x7e),1))%23][0]=inc&data[id%60)values(updatexml(1,concat(0x7e,user(),0x7e),1))%23][1]=1 - 访问带恶意
order参数的接口:?order=id%60)%20or%201=1%23 - 检查响应是否返回 SQL 语法错误或数据库报错信息——正常应返回 400 或空结果,绝不暴露 MySQL 错误详情



















