HTTP头部SQL注入高危字段包括User-Agent、Cookie、X-Forwarded-For、Referer等,只要后端将其未过滤拼入SQL语句即可能被利用;检测可用报错、时间盲注或布尔盲注,防御必须采用参数化查询而非依赖WAF或简单过滤。

User-Agent、Cookie、X-Forwarded-For 这些头部字段一旦被拼接到 SQL 查询中且未做参数化处理,就可能成为真实可利用的注入入口——不是“理论上存在”,而是已在多个 SRC 漏洞报告和渗透实战中反复验证。
哪些 HTTP 头最常触发 SQL 注入?
关键不在头本身,而在后端是否把它当「用户可控输入」直接拼进 SQL 语句。常见高危组合:
-
User-Agent:记录设备信息时写入INSERT INTO logs (ua) VALUES ('...') -
X-Forwarded-For或X-Real-IP:用于限流、封禁或日志归档,例如WHERE ip = '127.0.0.1' -
Cookie中的自定义字段(如user_id=123):若直接用于SELECT * FROM users WHERE id = user_id且未转义 -
Referer:某些统计系统会把来源页 URL 存进数据库,VALUES ('https://evil.com?x=' + referer)就很危险
注意:Host 头虽少被写库,但若用于多租户路由逻辑(如 WHERE tenant = 'xxx.com'),也存在风险。
手工检测时怎么快速确认头部是否参与 SQL 查询?
不依赖 WAF 日志或源码,用 Burp Suite 抓包后逐个修改头部值,观察响应差异。重点看三类信号:
- 返回
MySQL error、SQL syntax error、ORA-等数据库报错信息(显式错误) - 页面空白 / 500 / 响应时间突增 2s+(盲注迹象,尤其配合
SLEEP(2)测试) - 正常请求 vs
' OR '1'='1请求,返回内容有无逻辑翻转(布尔盲注,比如登录态异常维持或列表项数量变化)
推荐 payload 组合:' AND SLEEP(2)#(时间盲注)、' OR 1=1-- -(布尔)、' UNION SELECT database(),user()-- -(联合查询,需回显)。
为什么参数化查询对头部字段同样有效?
因为问题根源是字符串拼接,不是输入位置。只要后端用类似以下方式构造 SQL,就一定出事:
sql = "INSERT INTO logs (ua) VALUES ('" + request.headers.get('User-Agent') + "')正确做法是把头部值当作参数传入,交由数据库驱动处理:
- Python/Flask + SQLAlchemy:
db.session.execute(text("INSERT INTO logs (ua) VALUES (:ua)"), {"ua": request.headers.get("User-Agent")}) - Java/JDBC:
PreparedStatement ps = conn.prepareStatement("INSERT INTO logs (ua) VALUES (?)"); ps.setString(1, request.getHeader("User-Agent")); - PHP/PDO:
$stmt = $pdo->prepare("INSERT INTO logs (ua) VALUES (?)"); $stmt->execute([$_SERVER['HTTP_USER_AGENT']]);
绕过过滤器(如简单 replace("'", "''"))不如直接杜绝拼接——这是防御成本最低、效果最稳的方式。
WAF 和日志监控能替代代码修复吗?
不能。WAF 规则易被绕过(比如用大小写混写 UnIoN、编码 %27、注释符变形 /**/),而日志只记录已发生的攻击,无法阻止首次利用。更麻烦的是:X-Forwarded-For 这类头在 Nginx/Apache 层可能已被覆盖或截断,应用层拿到的值未必是原始请求值,导致 WAF 规则匹配失效。
真正容易被忽略的一点:很多团队只给 GET/POST 参数加了防护,却没把 request.headers、request.cookies 加入统一的参数校验中间件——这相当于给门装了锁,却忘了关窗。

















