thinkphp 3.2 的 where() 方法易致 sql 注入,因默认不强制预处理,字符串拼接(如 where('id='.$_get['id']))直接引入用户输入;即使使用数组方式,若 value 为未过滤表达式或动态字段名/表名未白名单校验,仍存在风险。

ThinkPHP 3.2 的 where() 方法为什么容易出 SQL 注入
因为老版本默认不强制预处理,拼接字符串时若直接用用户输入当条件值,where('id='.$_GET['id']) 这种写法一跑就中招。框架虽提供 where(array('id'=>$_GET['id'])) 自动转占位符,但开发者常误以为“写了数组就安全”,忽略了 key 是字段名、value 才进绑定——如果 value 是个未过滤的表达式(比如 '1 OR 1=1'),而字段本身又参与了拼接(如动态表名、字段名),照样崩。
常见错误现象:SQL syntax error 看似报错,实则是注入试探成功;或者返回异常多条记录,但日志里查不到明显攻击痕迹。
- 动态字段名/表名绝不能来自用户输入,必须白名单校验,例如
$field = in_array($_GET['sort'], ['name', 'create_time']) ? $_GET['sort'] : 'id'; - 所有用户可控的查询值,必须走数组式
where()或显式bind(),禁止字符串拼接 - 慎用
exp查询类型,它绕过绑定,where(array('status'=>'exp','exp'=>"= 1 AND admin=1"))就是高危写法
ThinkPHP 5.x+ 的 where() 和 param() 绑定差异
5.x 开始默认启用 PDO 预处理,但绑定行为和写法强相关:用数组传参(where(['name'=>$name]))会自动转 ? 占位符;用字符串 + 参数数组(where('name=:name', [':name'=>$name]))则走命名绑定;而 where('name='.$name) 仍直连 SQL,不触发任何绑定。
性能影响不大,但兼容性要注意:PDO 默认关闭 emulate_prepareds 时,某些复杂子查询或变量类型(如 NULL)可能触发 fallback 到模拟预处理,导致绑定失效。线上环境建议显式开启 emulate_prepareds=false 并测一遍边界 case。
- 优先用数组式
where(),最简且最稳 - 需要命名绑定时,确保参数键名带冒号,如
[':user_id'=>$id],否则框架可能忽略 -
param()是 URL 参数映射方法,不是 SQL 绑定接口,别把它和bind()混用
审计时怎么快速定位未绑定的 where 调用
直接搜项目里 where( 后紧跟单引号或双引号的行,尤其注意 $_GET、$_POST、I()、input() 出现在字符串内的情况。正则可配:where\([\'"]([^\'"]*?$_[A-Z]+|I\(|input\()|where\(".*\.$_ —— 这类基本都是雷。
容易踩的坑:IDE 全局搜索可能漏掉模板里的 {:M('user')->where(...)},或者闭包里动态拼的 $map['id'] = $_GET['id']; $m->where($map),看似数组实则 value 未过滤。
- 检查所有
where()调用前是否有对变量的类型/范围校验,比如intval()或in_array() - 留意
order()、group()、having(),它们也接受字符串参数,同样能注入 - TP 5.1+ 的
buildSql()可用于调试,打印生成的 SQL 看是否含原始用户输入
修复后如何验证绑定真正生效
光看代码没用,得看最终执行的 SQL。在数据库配置加 'debug'=>true,或用 getLastSql() 输出语句,确认用户输入是否变成 ? 或 :name,而不是原样出现在 SQL 字符串里。例如输入 id=1' OR '1'='1,安全结果应是 WHERE id = ?,而非 WHERE id = 1' OR '1'='1。
真实环境中,PDO 日志或 MySQL 的 general_log 也能抓到原始语句,但要注意开启后性能损耗大,仅临时开。
- 测试时务必覆盖 NULL、空字符串、特殊符号(如 %、_、反斜杠)等边界值
- 注意 ORM 模式下
find()、select()都共享同一套绑定逻辑,不用单独测每个方法 - 如果用了自定义查询构造器或原生
query(),那绑定规则完全失效,必须手动处理
最麻烦的是那些藏在模型基类、公共函数、甚至 vendor 扩展里的 where 调用——它们往往被当成“可信代码”跳过审计,但只要参数来源不可控,就是隐患。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











