PHP 8.3 不修复 SQL 注入,漏洞源于应用层用户输入拼接 SQL;应结合 Burp/ZAP 自动探测、SQLMap(禁用于生产)、Postman 手动测试及静态扫描定位高危模式,并严控 ORDER BY、LIMIT、表名列名、LIKE 等动态位置。

PHP 8.3 本身不引入也不修复 SQL 注入漏洞,这类漏洞始终属于应用层问题。扫描目标不是 PHP 版本,而是你代码中是否将用户输入直接拼进 SQL 查询——无论用的是 MySQLi、PDO 还是 ORM 封装。
用工具做自动化探测
先覆盖高频入口,再人工验证可疑点:
- Burp Suite 或 OWASP ZAP:拦截所有带参数的请求(尤其是 GET/POST 中含 id、name、sort、search 等字段),对每个参数依次注入 ' OR 1=1 --、1' UNION SELECT 1,2,3--、1; WAITFOR DELAY '0:0:5'--(适用于 MSSQL)等典型 payload,观察响应变化(状态码、响应体长度、延时)
- SQLMap(谨慎使用):对目标接口执行
sqlmap -u "https://site.com/api/user?id=1" --batch --level=3,它能自动识别可注入点并尝试提取数据;但生产环境禁用,避免触发风控或写入日志爆炸 - Postman 手动构造边界值:传空字符串、超长字符串(如 1000 个 a)、特殊字符(
'"、;、--、/*),看是否报错泄露数据库信息(如 “MySQL syntax error”)
静态代码扫描抓高危模式
在开发或 CI 阶段运行脚本,定位硬编码拼接点:
修复 Core bailout 状态损坏安全问题,以及 BZ2、DOM、PDO、Opcache/JIT 内存与执行错误,改进 Unicode 字素处理、URL 解析、TLS 流状态、信号分发及会话错误处理。
- 搜索所有
mysql_query(、mysqli_query(、pg_query(调用,确认是否含$_GET、$_POST、$_COOKIE变量 - 检查
PDO::prepare()后是否缺失bindValue()或execute(),比如只写$pdo->prepare("SELECT * FROM t WHERE id = :id")却没绑定就执行 - 排查字符串拼接中混用占位符和变量,例如:
"WHERE status = '" . $_GET['s'] . "' AND id = :id"—— :id 安全,但 status 部分已失守 - 用 Psalm 或 PHPStan 配置规则检测
exec、system、eval,它们常与注入链式利用有关
重点盯防“看似安全”的动态位置
这些地方最容易被忽略,却常成突破口:
立即学习“PHP免费学习笔记(深入)”;
-
ORDER BY / GROUP BY 字段:不能参数化,必须白名单校验。例如
$sort = in_array($_GET['sort'], ['created_at', 'title']) ? $_GET['sort'] : 'id'; $sql = "SELECT * FROM posts ORDER BY $sort"; -
LIMIT/OFFSET 偏移量:数字型也要过滤,
$offset = (int)$_GET['offset'];或filter_var($_GET['offset'], FILTER_VALIDATE_INT),防止0; DROP TABLE users--类攻击 - 表名、列名、数据库名:绝对不可由用户输入决定,必须硬编码或查配置表映射
-
LIKE 模糊查询:用户输入需转义通配符,
$keyword = str_replace(['%', '_'], ['\%', '\_'], $_GET['q']); $stmt->bindValue(':q', "%{$keyword}%", PDO::PARAM_STR);
验证修复是否真正生效
改完代码后别只看“不报错”,要验证逻辑是否闭环:
- 重放原攻击请求,确认返回 400 或空结果,而非数据泄露或 200 成功响应
- 开启 PDO 的
PDO::ATTR_EMULATE_PREPARES = false,防止驱动层模拟拼接绕过防护 - 检查错误日志,确保 SQL 异常不再暴露表结构、字段名或完整查询语句
- 对关键接口(登录、支付、后台操作)做回归测试,确认业务逻辑未因过滤逻辑被破坏


















