HTTP Header注入是指攻击者通过操纵HTTP请求头中的字段内容,将恶意数据注入到应用的处理流程中,进而造成安全风险的一类漏洞。相比SQL注入、XSS这些耳熟能详的攻击方式,Header注入往往被开发者和运维人员忽视,因为大家普遍认为请求头是由浏览器或客户端自动生成的,普通用户无法控制。但实际上,借助curl、Burp Suite等工具,请求头中的任何一个字段都可以被随意篡改。一旦应用直接信任并使用这些头部数据,就等于把攻击入口拱手让给了对方。

HTTP Header注入的攻击原理
要理解Header注入,首先要明白HTTP请求的工作机制。客户端每次向服务器发起请求时,都会携带一组键值对形式的头部字段,例如Host、Referer、User-Agent、Cookie、X-Forwarded-For等。这些字段的本意是向服务器传递上下文信息,但在很多业务场景中,开发者会直接读取这些值并用于业务逻辑,比如记录访问日志、生成密码重置链接、判断用户来源等。
问题就出在这里。头部数据完全由客户端控制,服务端如果没有任何校验就将其拼接到响应、SQL语句、日志文件或跳转地址中,恶意内容就会随之流转。以PHP为例,下面这段代码就存在典型的注入风险:
<?php // 危险示例:直接将请求头拼接到SQL语句中 $ua = $_SERVER['HTTP_USER_AGENT']; $sql = "SELECT * FROM visit_log WHERE ua = '" . $ua . "'"; mysqli_query($conn, $sql); ?>
攻击者只需将User-Agent设置为' OR 1=1 --,就能改变SQL语句的语义,这本质上就是SQL注入,只是注入点换成了请求头。除了直接注入代码,头部还可能被用来注入换行符(CRLF,即\r\n),从而拆分或伪造HTTP响应头,这种变体被称为CRLF注入,可以用来设置恶意Cookie、伪造响应内容或实施缓存投毒。
几种常见的Header注入场景
第一种是Host头注入。有些应用在生成链接时直接使用请求中的Host值,例如密码重置邮件里包含http://$_SERVER['HTTP_HOST']/reset.php?token=xxx这样的地址。攻击者将Host头改成自己控制的域名,受害者点击邮件链接后,密码重置令牌就会被发送到攻击者的服务器上,从而实现账号接管。这种攻击在共享服务器或配置不当的Nginx、Apache环境中尤其常见。
第二种是Referer和User-Agent注入。不少系统会把这两个字段写入访问统计或日志系统。如果日志查看页面直接输出这些数据且没有做HTML转义,攻击者可以在User-Agent中嵌入<script>alert(1)</script>这样的载荷,当管理员查看日志时就触发了存储型XSS,最终可能窃取管理员会话。
第三种是X-Forwarded-For相关注入。这个头部常被用来获取客户端真实IP,很多应用信任它做访问控制或限流判断。但如果服务器没有部署在反向代理后面,或者没有校验代理链的真实性,攻击者可以随意伪造该头部绕过IP封禁,甚至将其注入到日志分析系统或防火墙规则中。下面是一个利用curl伪造头部的简单演示:
# 伪造User-Agent和X-Forwarded-For进行注入测试 curl -v "http://target.ippipp.com/profile" \ -H "User-Agent: Mozilla/5.0 <script>alert(document.cookie)</script>" \ -H "X-Forwarded-For: 127.0.0.1" \ -H "Referer: http://evil.ipipp.com/steal"
如何有效防御Header注入
防御的核心原则是:永远不要信任客户端提交的任何数据,请求头也不例外。具体可以从以下几个层面入手。
第一层是输入校验。对所有从请求头读取的数据做白名单校验,例如Host字段可以用正则^[a-zA-Z0-9.-]+$限制合法字符,User-Agent限制长度和字符集,Referer校验是否属于可信域名列表。第二层是输出编码。数据最终落到哪里,就按对应上下文编码:写入HTML要转义为HTML实体,写入SQL要使用参数化查询,写入日志要过滤换行符防止日志注入。下面是一段相对安全的PHP处理示例:
<?php
// 安全示例:白名单校验 + 参数化查询
$host = $_SERVER['HTTP_HOST'] ?? '';
if (!preg_match('/^[a-zA-Z0-9.-]+$/', $host)) {
// Host不合法,拒绝处理或回退到配置中的默认域名
$host = 'www.ipipp.com';
}
$ua = substr($_SERVER['HTTP_USER_AGENT'] ?? '', 0, 256);
$ua = str_replace(["\r", "\n"], '', $ua); // 移除换行符,防止CRLF注入
$stmt = $conn->prepare("SELECT * FROM visit_log WHERE ua = ?");
$stmt->bind_param('s', $ua);
$stmt->execute();
?>第三层是服务器与框架层面的加固。在Nginx中应配置默认的server块来拒绝不匹配的Host请求,避免Host头被任意指定;框架层面可以启用自带的请求校验组件,例如Laravel的Validator对头部字段做规则校验。对于反向代理场景,要确保只有可信代理设置的X-Forwarded-For才会被采信,可以通过TrustedProxy配置指定可信代理IP段。此外,响应头中涉及动态拼接的部分要统一走框架的安全API,避免手动拼接Location、Set-Cookie等头部值。
最后,建议将头部校验纳入自动化安全测试流程,在CI阶段使用包含头部篡改用例的扫描脚本,同时定期审查代码中所有读取$_SERVER、request.getHeader()等头部数据的位置,形成清单化管理。安全从来不是单点防护,只有输入校验、输出编码、配置加固三者结合,才能真正堵住Header注入这类隐蔽漏洞。
HTTP Header注入HTTP请求头安全Web安全防护修改时间:2026-09-07 08:02:32