原生sql必须显式传参,db::query("select * from user where id = ?", [$id])才安全;in语句需动态生成占位符;where条件禁用字符串拼接,须用数组或闭包;order/group字段名须白名单校验;关闭pdo模拟预处理并禁用exp/raw接口。

原生SQL必须显式传参,不能只写占位符
Db::query("SELECT * FROM user WHERE id = ?") 这种写法看似用了问号,但没传参数数组,PDO 不会触发绑定,实际执行时问号会被当成字面量,或直接报错回退为字符串拼接。框架日志里可能显示 WHERE id = ?,但 MySQL 服务端收到的可能是 WHERE id = 1 OR 1=1。
- 正确写法是
Db::query("SELECT * FROM user WHERE id = ?", [$id]),必须带第二个参数且为数组 - 命名占位符要严格匹配键名:
Db::query("WHERE name = :name", [':name' => $name]),漏掉冒号或大小写不一致都会失效 -
IN语句不能直接传数组变量,得先生成对应数量的?:$placeholders = implode(',', array_fill(0, count($ids), '?')),再调用Db::query("WHERE id IN ($placeholders)", $ids)
where 条件禁用字符串拼接,改用数组或闭包
像 where("id = " . input('id')) 或 where("name LIKE '%" . input('kw') . "%') 这类写法,框架完全跳过 PDO 绑定流程,用户输入原样进 SQL。哪怕加了 intval() 或 htmlspecialchars(),也防不住报错注入、联合查询等绕过方式。
- 简单条件统一用键值数组:
where(['id' => input('id', 0, 'intval'), 'status' => 1]) - LIKE 必须手动拼通配符:
where(['name' => ['like', '%' . input('kw') . '%']]),不能写成['like', input('kw')] - 多逻辑分支用闭包:
where(function($q) use($name, $status) { $q->where('name', 'like', "%{$name}%")->where('status', $status); })
动态字段名(order/group)必须白名单校验
order(input('sort')) 看似无害,但传入 ?sort=id; SELECT password FROM admin 或 ?sort=updatexml(1,concat(0x7e,user()),0) 就能触发报错注入。框架对 order()、group() 的键名不做任何过滤,原样拼入 SQL。
- 字段名必须走白名单:
$sort = in_array(input('sort'), ['id', 'name', 'create_time'], true) ? input('sort') : 'id' - 拼接前用
parseKey()处理:order($builder->parseKey($sort) . ' DESC'),防止字段名含点号、反引号等绕过 - 绝对禁止把
input()结果直接丢进order(),htmlspecialchars()对 SQL 关键字完全无效
关闭模拟预处理并禁用 exp/raw 接口
PDO 默认开启 PDO::ATTR_EMULATE_PREPARES 时,预处理会被退化为字符串替换,尤其在 MySQL 5.6 或 Docker 环境中极易被绕过。而 exp 和 raw 是明确告诉框架“别管我,直接拼”,等于主动开后门。
- 数据库配置中强制关闭:
'PDO::ATTR_EMULATE_PREPARES' => false - 全局搜索并删除所有
where('field', 'exp', ...)、whereRaw()、field('COUNT(*) + 1')类调用 - 升级到 ThinkPHP 6.3+ 后,
exp模式默认被废弃,但老项目仍需人工清理
最隐蔽的坑是:你以为写了 where(['id' => $id]) 就安全了,但如果 $id 是用户传来的数组(比如 id[]=1&id[]=2),且没做 is_numeric() 校验,就可能触发 parseData() 漏洞,让恶意结构进入 SQL。类型检查和白名单,一个都不能少。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











