只做代码审计或渗透测试均易漏SQL注入,必须双线并行:审计查“能不能拼接”,测试查“拼接后能不能执行”。因审计难发现框架封装、ORM混用原始SQL等隐性拼接,测试则受限于WAF、非标准注入点及错误屏蔽,二者交叉验证才能覆盖全路径。
直接结论:只做代码审计或只做渗透测试,都大概率漏掉SQL注入隐患;必须双线并行,且明确分工——审计查“能不能拼接”,测试查“拼接后能不能执行”。
为什么单靠代码审计会失效
代码审计能发现
、
这类直连函数的硬编码调用,但对以下情况基本无感:
框架封装层(如 Laravel 的
传入未绑定的字符串变量)
ORM 链式调用中混入原始 SQL 片段(例如 Django 的
)
日志埋点、缓存键生成等非显性数据库交互路径里拼接了用户输入
第三方 SDK 或内部中间件自动构造 SQL(常见于统一鉴权、审计日志模块)
这类问题在静态扫描中常被标记为“低风险”或直接忽略,但运行时一旦触发,就是高危漏洞。
为什么单靠渗透测试不可信
渗透测试依赖 HTTP 请求响应判断,但很多真实场景下它根本“看不见”注入点:
防SQL注入的php类库
防SQL注入的php类库
下载
应用启用了 WAF 并拦截了典型 payload(如
),但实际后端仍存在拼接逻辑
注入点在 Cookie 或自定义 Header 中(如
),而测试范围未覆盖这些字段
业务逻辑强制校验输入长度/字符集(如手机号字段只允许 11 位数字),导致手工 payload 无法送达数据库
错误信息被全局捕获并返回通用提示(如“系统繁忙”),无法通过报错反推闭合方式
换句话说:没测出 ≠ 没漏洞,只是当前测试条件没触达执行路径。
怎么让两者真正互补落地
关键不是“做没做”,而是“怎么做才能交叉验证”:
代码审计输出必须带具体行号和上下文片段,例如标出
所在文件及第 42 行,并注明该变量未经过
强转或参数化处理
渗透测试前,把审计发现的所有疑似拼接点整理成清单,针对性构造绕过 WAF 的 payload(如 URL 编码
替代
,或用
绕过空格过滤)
对审计认为“已修复”的点,渗透测试必须复测——常见问题是开发者改成了
,但 MySQL 开启
模式时仍可绕过
所有测试结果必须回填进代码仓库的 issue 系统,关联到对应 commit,避免“修了又犯”
最易被忽略的一点:审计和测试团队之间不能共享原始凭证(如测试账号、数据库连接串)。否则测试人员可能下意识避开已知高危路径,导致验证失真。
mysql_query()mysqli::query()DB::select().extra(where=["name = '{}'".format(user_input)])' OR '1'='1X-Trace-ID$sql = "SELECT * FROM orders WHERE uid = " . $_GET['uid'];(int)%27'/**/addslashes()NO_BACKSLASH_ESCAPES