必须对order/group参数强制白名单校验,仅允许预设字段如['id','name','create_time'],不匹配时fallback默认值;禁用where('field','exp',$value)所有用法,全部替换为参数绑定或闭包方式。

order/group 传参必须走白名单校验
框架对 order() 和 group() 的参数不做任何过滤,尤其当传入数组时,键名会被原样拼进 SQL。比如 $order = input('orderby') + db('user')->order($order)->select(),攻击者传 ?orderby[id]=updatexml(1,concat(0x7e,user()),0) 就能触发报错注入。
修复不是加个 htmlspecialchars() 或正则替换,而是强制字段白名单:
- 只允许预设字段参与排序:
in_array($order, ['id', 'name', 'create_time'], true) - 不匹配时 fallback 到默认值(如
'id desc'),不能直接抛异常或留空 - 若需手动拼接字符串(如带
asc/desc),必须用$builder->parseKey($field)处理字段名,防止id`--这类绕过
where 中彻底删除所有 'exp' 模式调用
where('field', 'exp', $value) 是明确告诉框架“把 $value 当原生 SQL 执行”,完全绕过参数绑定。哪怕只在某处写了一次,就等于给攻击者开了后门。
不要试图“过滤 $value”,直接删掉所有含 'exp' 的 where() 调用:
- 全局搜索项目中所有
where(+'exp'组合,逐行替换 - 改用参数绑定写法:
where('status', '>', input('min_status', 0, 'intval')) - 复杂逻辑用闭包:
where(function ($query) { $query->where('a', '>', 1)->whereOr('b', '
update/insert 接收数组参数前必须强类型校验
TP5.1.0–5.1.7 存在 parseData() 漏洞:当 update(['name' => $input]) 的 $input 是用户可控数组(如表单提交 name="username[a]"),框架会解析类似 ['inc', 'updatexml()', 1] 的结构并直接拼入 SQL。
input('data/a', '', 'htmlspecialchars') 对数组无效,必须显式遍历检查:
- 先
is_array($input),再对每个值执行is_string($val) || is_numeric($val) - 拒绝多维数组、含函数名的字符串(如
'updatexml()')、特殊结构(['inc', ...]) - 老版本别依赖升级——5.1.38+ 仅缓解,不能替代代码层校验
Db::query() 原生查询必须显式绑定参数
Db::query() 不自动启用参数绑定,它只执行你写的 SQL 字符串。哪怕用了 PDO,只要存在拼接,就是裸奔。
危险写法:Db::query("SELECT * FROM user WHERE name = '" . input('name') . "'")
安全写法只有两种:
- 问号占位符:
Db::query('SELECT * FROM user WHERE name = ?', [input('name')]) - 命名占位符:
Db::query('SELECT * FROM user WHERE name = :name', ['name' => input('name')])
注意:字符串拼接 + addslashes() 或 mysql_real_escape_string() 都不可靠,MySQL 报错注入(如 updatexml())在 prepare 阶段就能回显数据,必须用真正的参数化语法。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











