http报头追踪漏洞
作者:综合 来源:休闲 浏览: 【大 中 小】 发布时间:2026-10-17 06:08:50 评论数:
去年秋天,追踪一个做跨境电商的漏洞朋友给我发来一张截图。他在自己的追踪服务器日志里发现,某个IP地址在短短两小时内,漏洞用完全相同的追踪请求头访问了后台登录接口四千多次。奇怪的漏洞是,这个请求头里携带的追踪User-Agent、Accept-Language、漏洞Referer全部正常,追踪看起来就像普通用户。漏洞但频率不对。追踪他顺着这个IP查下去,漏洞发现对方只是追踪把浏览器发来的原始报头原封不动地重放。没有伪装,漏洞没有篡改。追踪这其实就是最朴素的http报头追踪漏洞——服务器过度信任了报头里的信息,而攻击者只需要照抄。
很多人以为http报头追踪漏洞是某种高深的技术。不是。它更像一种逻辑上的偷懒。比如,你的应用通过X-Forwarded-For来判断用户真实IP,然后基于这个IP做限流或封禁。攻击者只要在请求里手动加一行X-Forwarded-For: 1.2.3.4,你的限流就形同虚设。更糟的是,有些系统会把X-Forwarded-For的值直接写进数据库,当成用户操作日志。攻击者填个127.0.0.1,日志里就全是本地访问,追查时你连对方影子都摸不着。
我见过一个真实的案例。某在线投票网站用X-Forwarded-For来防止刷票,每个IP只能投一票。结果有人写了个脚本,每次请求随机生成一个X-Forwarded-For值。五分钟投了八千票。网站方一开始还纳闷:怎么有这么多来自不同地区的IP?后来才发现,那些IP全是伪造的。服务器根本没验证报头来源,直接采信了。
问题出在哪?http报头是客户端完全可控的。除了少数由代理或负载均衡器添加的报头(比如Via、X-Forwarded-For的某些变体),绝大多数报头都可以被任意修改。User-Agent可以改成任何字符串,Referer可以伪造,Cookie可以伪造,X-Forwarded-For当然也可以。服务器如果不加区分地信任这些值,就等于把大门钥匙交给了访客。
那怎么防?不是把所有报头都禁掉——那不现实。关键是分清哪些报头是可信的,哪些是不可信的。如果你的服务器前面有反向代理(Nginx、HAProxy、Cloudflare等),那么代理添加的报头(比如X-Real-IP)通常可信,但前提是代理会覆盖客户端传来的同名报头。很多代理默认不覆盖,只是追加。这时候客户端传一个X-Real-IP: 1.1.1.1,代理再追加一个X-Real-IP: 真实IP,后端取第一个值就中招了。正确做法是:代理必须强制覆盖,或者后端只取最后一个值。
另一个坑是日志记录。有些WAF或日志系统会把所有报头原样存下来,包括X-Forwarded-For、X-Client-IP、X-Remote-IP等等。攻击者可以塞入超长报头,或者塞入换行符,造成日志注入。我见过一个日志分析平台,因为没过滤报头里的\r\n,攻击者伪造了一条假的日志条目,把管理员引向了钓鱼链接。这已经超出追踪漏洞的范畴,但根子是一样的:把不可信数据当成了可信数据。
说到底,http报头追踪漏洞的本质是信任边界模糊。客户端发来的东西,默认都是不可信的。你可以用报头做辅助判断,但不能用它做唯一判断。限流要看连接层信息(TCP源IP、TLS指纹),日志要区分“客户端声称的”和“代理确认的”,鉴权要走独立的令牌机制。报头只是提示,不是证据。
我那个朋友后来改了架构。他把限流逻辑从应用层挪到了Nginx的limit_req模块,基于TCP源IP做限制。X-Forwarded-For只用来做地理统计,不再参与任何安全决策。攻击流量瞬间掉下去了。他跟我说了一句话:“以前总觉得报头是元数据,现在才知道,元数据也能杀人。”
