php框架中sql注入风险极高,必须禁用字符串拼接、改用数组式where条件、闭包封装逻辑查询、like拆解为三参数形式、原生sql显式绑定参数、关闭pdo模拟预处理、禁用raw()/exp()、动态排序字段白名单校验。

在PHP框架中直接拼接SQL语句极易引发SQL注入,攻击者只需输入admin' OR '1'='1就能绕过登录验证、读取全表数据。这不是小概率风险,而是只要拼接发生就必然存在的漏洞。
ThinkPHP中禁止字符串拼接where条件
ThinkPHP默认对数组格式的where条件自动启用PDO参数绑定,但一旦使用双引号字符串拼接,框架将完全跳过安全机制,直接执行原始SQL。
第一步:把所有where("username = '" . input('user') . "'")改成键值数组:where(['username' => input('user')])。
第二步:含逻辑运算的条件必须用闭包封装,例如查询启用且非测试账号:where(function ($query) { $query->where('status', 1)->whereNotIn('type', ['test']); })。
第三步:LIKE模糊搜索不能写成"name LIKE '%{input('kw')}%'",必须拆解为where('name', 'like', '%' . input('kw') . '%')——【否则通配符会被当SQL指令执行】。
原生SQL必须显式绑定参数
框架中的Db::query()和Db::execute()不会自动过滤,必须人工传入参数数组,否则等于裸奔。
方法一(位置占位符):Db::query("SELECT * FROM user WHERE id = ? AND level > ?", [$id, $minLevel])。
方法二(命名占位符):Db::query("UPDATE log SET ip = :ip WHERE action = :act", [':ip' => $_SERVER['REMOTE_ADDR'], ':act' => 'login'])。
方法三(IN语句特殊处理):若要查多个ID,先生成对应数量的问号:$ids = [101, 102, 105]; $placeholders = str_repeat('?,', count($ids) - 1) . '?'; Db::query("SELECT * FROM user WHERE id IN ($placeholders)", $ids)。
关闭模拟预处理与危险接口
PDO默认开启PDO::ATTR_EMULATE_PREPARES,此时预处理退化为字符串拼接,在MySQL低版本或Docker环境中极易被宽字节绕过。
在数据库配置文件中添加:'PDO::ATTR_EMULATE_PREPARES' => false。
全局禁用raw()和exp()调用——这两个接口等同于手动拼接SQL,【一旦启用,所有参数绑定形同虚设】。
动态排序字段必须走白名单校验:$sort = in_array(input('sort'), ['create_time', 'score', 'id']) ? input('sort') : 'id'; Db::order($sort, 'desc');。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











