资料库 · HTTP 协议与请求走私
第 ② 卷,条目 21–40。来源为 PortSwigger Research,主要是 James Kettle 的研究线。
这一卷有一条贯穿的主线:几乎所有问题都出在"两个组件对同一段字节的理解不一致"上。前端代理认为这是一个请求,后端认为是两个;CDN 认为这个响应可缓存,源站认为不可;负载均衡认为连接干净,实际上里面残留着半个请求。
这也决定了这一卷的防御思路和第一卷完全不同:第一卷改代码,这一卷改架构和配置。
请求走私与去同步
21. HTTP/1.1 must die: the desync endgame
来源:PortSwigger Research,James Kettle。
读它解决什么:想理解为什么请求走私这类问题在 HTTP/1.1 上无法根治。
要点:
- 标题主张 HTTP/1.1 应当被淘汰,称之为去同步问题的"终局"
- 是这条研究线的总结性文章
我的补充:根本原因在协议设计:HTTP/1.1 在一条 TCP 连接上用文本分隔符来划分请求边界,于是"这个请求到哪结束"是靠解析 Content-Length 和 Transfer-Encoding 推断出来的,任何两个组件推断不一致就出现走私。HTTP/2 用二进制帧和显式长度字段,从设计上消除了这个歧义。所以最有效的防御不是加规则,而是让整条链路端到端都用 HTTP/2——注意关键在"端到端":很多架构是浏览器到 CDN 用 HTTP/2、CDN 到源站降级成 HTTP/1.1,那后半段的走私风险完全没消除,而且更隐蔽(前端的 HTTP/2 请求被翻译成 HTTP/1.1 时可能产生新的歧义,这就是 H2 降级走私)。查一下你的 CDN 到源站是什么协议,很多人没查过。
22. CRLF-Powered Desync Attacks: Beheading HTTP Streams
来源:PortSwigger Research,2026 年,本卷最新。
读它解决什么:CRLF 处理差异如何造成去同步。
要点:
- 基于 CRLF 的去同步攻击
- 2026 年发表,是这条线的最新进展
我的补充:CRLF(\r\n)是 HTTP/1.1 里的行分隔符,所以任何允许它进入请求头的地方都是潜在的请求边界注入点。规范要求严格按 \r\n 处理,但实现的容错各不相同——有的接受裸 \n,有的接受 \r,有的把某些 Unicode 字符规范化成 CRLF。防御上:任何进入 HTTP 头的用户输入都要拒绝而不是过滤 CR/LF(过滤会遇到第一卷第 6 条那种规范化绕过),并且优先用框架提供的 header 设置 API 而不是手工拼接头字符串。这一条也解释了为什么"重定向 URL 来自用户参数"是个高危模式——那个值最终会进 Location 头。
23. Browser-Powered Desync Attacks: A New Frontier in HTTP Request Smuggling
来源:PortSwigger Research,2022 年。
读它解决什么:请求走私原来需要特制的客户端,这条说明浏览器就能触发。
要点:
- 用浏览器发起去同步攻击
- 标题称之为请求走私的"新边界"
我的补充:这是个严重性等级的跃升。走私攻击此前需要攻击者直连目标(用特制客户端发畸形请求),这限定了攻击场景。浏览器能触发意味着可以变成客户端侧攻击——诱导受害者访问一个页面,由受害者的浏览器去污染他们自己与目标站点之间的连接。防御含义:不能再假设"只有能直连我们的人才构成威胁"。同时它把 CSRF 类防护的地位又提高了一层,因为攻击入口变成了"用户点了一个链接"。
24. Making desync attacks easy with TRACE
来源:PortSwigger Research。
读它解决什么:TRACE 方法如何帮助发现和利用去同步。
要点:
- 用 HTTP
TRACE方法简化去同步攻击 TRACE的语义是回显收到的请求
我的补充:TRACE 的设计目的是调试——它把服务器收到的原始请求回显给你。这个能力对攻击者极其有用:它直接告诉你中间层是怎么改写你的请求的,省掉大量盲猜。防御非常简单直接:在边缘禁用 TRACE(和 TRACK),这个方法在生产环境没有任何正当用途。这属于那种"一行配置消除一整类侦察能力"的加固项,成本低到没有理由不做。顺手也检查一下 OPTIONS 的响应里有没有泄露过多信息。
25. Making HTTP header injection critical via response queue poisoning
来源:PortSwigger Research,2022 年。
读它解决什么:头注入通常被评为中危,这条说明它能升级到"响应发给了错误的用户"。
要点:
- 通过响应队列投毒把 HTTP 头注入提升为严重漏洞
- 涉及响应与请求的配对关系被打乱
我的补充:响应队列投毒的后果是响应错配——用户 A 的响应(含 A 的 session cookie、A 的个人数据)被发给了用户 B。这不需要攻击者做任何针对性的事,错配是持续发生的,等于连接上所有后续用户的数据都可能泄露给攻击者。这条是给漏洞定级时的一个重要参考:看到"HTTP 头注入"别按 CVSS 的默认中危处理,要看它能不能升级。检测手段上,观察响应与请求的错配(返回的内容明显不属于这个请求)是最直接的信号,值得在监控里加这类异常检测。
26. Beware the false false-positive: how to distinguish HTTP pipelining from request smuggling
来源:PortSwigger Research。
读它解决什么:扫描器报了走私但可能只是流水线(pipelining),怎么区分。
要点:
- 区分 HTTP 流水线与请求走私
- 标题的 "false false-positive" 指"被误判为误报的真问题"
我的补充:这条对做安全评审和处理扫描结果的人特别有用。走私的测试信号和正常的 HTTP 流水线行为长得很像,于是两种错误都会发生:把真问题当误报关掉(这就是标题说的 "false false-positive",更危险),或者把正常行为当漏洞上报(浪费所有人时间)。实践建议:这类结论必须人工复核,别让扫描器自动开工单也别自动关闭;复核时看的是响应的时序和配对关系,不只看单个响应内容。
27. Introducing HTTP Anomaly Rank
来源:PortSwigger Research,2026 年。
读它解决什么:想量化"某个 HTTP 实现有多不规范",这是一套排名方法。
要点:
- 提出 HTTP Anomaly Rank 这一指标
- 2026 年发表
我的补充:这类量化指标对技术选型有直接价值。"这个反向代理的 HTTP 解析有多符合规范"以前只能靠传闻和个案,有了可比较的指标,选型时就能把它当一个维度。判断原则不变:你链路上任意两个组件的解析行为差异越大,走私风险越高。所以同构(全链路同一款代理)通常比异构安全,混用 nginx + 某个云 LB + 某个应用服务器时,风险来自它们两两之间的差异。
28. Can AI do novel security research? Meet the HTTP Terminator
来源:PortSwigger Research,2026 年。
读它解决什么:AI 能不能做出原创的安全研究,这是一次带具体产出的尝试。
要点:
- 探讨 AI 做原创安全研究的能力,产出被称为 "HTTP Terminator"
- 2026 年发表
我的补充:这个问题值得认真跟。我的判断是 AI 在安全研究里的强项是大规模差异测试——生成海量畸形输入、比对多个实现的行为差异、把不一致的地方标出来。这恰好是 HTTP 解析差异研究最费人力的部分(人工枚举组合是不可能的)。它的弱项是提出新的攻击模型,也就是"想到应该往哪个方向找"这一步。所以现实的形态是人定方向、AI 做覆盖。对防御方的启示更直接:如果这类自动化差异测试变得廉价,新的解析差异会被更快地发现,所以"用了很多年没出事"的老组件不再是安全的理由。
29. How to turn security research into profit: a CL.0 case study
来源:PortSwigger Research,2022 年。
读它解决什么:以 CL.0 这一类去同步为例,讲研究如何落到赏金上。
要点:
- 以 CL.0 攻击为案例,讲安全研究到收益的路径
- CL.0 指
Content-Length: 0相关的去同步变体
我的补充:CL.0 这个变体的原理值得单独知道:请求带 Content-Length: 0 但实际有 body,前端认为请求在头结束、后端认为 body 属于这个请求(或反之),边界就错位了。特别值得注意的是它常出现在特定端点上——某些路径由不同的后端处理(比如静态资源走一个服务、API 走另一个),而那个后端对 CL 的处理不同。防御含义:走私测试不能只测网站根路径,得覆盖不同类型的端点,因为路由差异会导致同一个站点上有的路径安全有的不安全。
30. HTTP/3 connection contamination: an upcoming threat?
来源:PortSwigger Research,2022 年。
读它解决什么:HTTP/3 会不会带来新的连接层问题。
要点:
- 讨论 HTTP/3 的连接污染问题
- 标题带问号,写作时属于前瞻性讨论
我的补充:这条提醒了一件重要的事:升级到 HTTP/2 或 HTTP/3 消除了旧的歧义,但引入了新的问题面。连接污染的场景是——HTTP/2 和 HTTP/3 都会把多个(可能属于不同主机名的)请求复用到同一条连接上,如果后端根据连接而不是根据请求头来判断"这些请求属于谁",就会出错。所以第 21 条那个"迁到 HTTP/2"的建议要加个限定:迁移的同时要检查后端是否有基于连接的假设(连接级别的认证、连接级别的限流、按连接绑定 session 之类的设计),这些在多路复用下都会失效。
Web 缓存与竞态
31. Gotta cache 'em all: bending the rules of web cache exploitation
来源:PortSwigger Research。
读它解决什么:Web 缓存投毒与欺骗的系统性方法。
要点:
- Web 缓存利用的规则突破,覆盖面较广
- 属于系统化梳理而非单个技巧
我的补充:缓存类漏洞的根源是缓存键(cache key)和实际影响响应的输入不一致。缓存按 URL 加少数几个头做键,但响应内容可能受到未纳入键的头(X-Forwarded-Host、X-Original-URL 等)影响——于是攻击者用这些头污染一份响应,之后所有请求同一 URL 的用户都拿到被污染的版本。防御要点:把所有影响响应的输入都纳入缓存键(或者反过来,禁止那些头影响响应);给用户特定的响应显式设 Cache-Control: private;Vary 头要设对。这个博客部署在 Cloudflare Pages 上,静态站点风险低得多,但只要有 Pages Functions 返回随请求变化的内容,就需要确认它的缓存配置。
32. Smashing the state machine: the true potential of web race conditions
来源:PortSwigger Research,2023 年。
读它解决什么:Web 竞态条件的危害远超"重复提交",这条讲它的真实潜力。
要点:
- 系统阐述 Web 竞态条件,标题指向应用的状态机
- 2023 年发表,是这个方向的代表性研究
我的补充:竞态在业务系统里的典型形态:限领一次的优惠券被并发领了十份、余额校验和扣款之间被插入另一次扣款、一次性验证码被并发使用多次。这类问题在功能测试里几乎不可能发现,因为顺序执行时逻辑完全正确。防御是明确的:校验和变更必须在同一个原子操作里——数据库层面用 SELECT ... FOR UPDATE、乐观锁(版本号)、或唯一索引约束(让数据库来拒绝第二次),而不是"先查再改"这种应用层两步操作。我的经验是:任何"检查配额然后消耗配额"的代码,如果这两步不在一个事务里,就一定有竞态。
33. The single-packet attack: making remote race-conditions 'local'
来源:PortSwigger Research,2023 年。
读它解决什么:网络抖动让远程竞态难以命中,这条讲怎么消除这个障碍。
要点:
- 单包攻击技术,把远程竞态的时序精度提升到接近本地
- 利用 HTTP/2 的多路复用把多个请求放进一个 TCP 包
我的补充:这条改变了竞态漏洞的可利用性判断。过去评估竞态时的常见减分理由是"需要精确的时序,网络抖动使其难以实现"——单包攻击把这个理由消除了:多个请求装进同一个 TCP 数据包,几乎同时到达服务器,网络抖动不再影响相对时序。所以现在给竞态漏洞定级时,不能再用"时序窗口太窄"来降级。防御侧的结论和上一条相同:靠数据库原子性,不要靠"窗口太小打不中"。
34. Listen to the whispers: web timing attacks that actually work
来源:PortSwigger Research。
读它解决什么:时序攻击通常被认为不实用,这条讲哪些是真能用的。
要点:
- 讨论实际可行的 Web 时序攻击
- 标题的 "actually work" 与"理论上可行"形成对比
我的补充:时序攻击在 Web 上的实际形态往往不是密码学教材里那种纳秒级测量,而是粗粒度的行为差异:用户存在时查数据库(慢)、不存在时直接返回(快),这个差异大到能被网络噪声之外测出来,于是成了用户名枚举通道。同类还有:缓存命中与否、内部服务是否被调用、错误路径长短。防御上:认证相关的路径要统一处理时间(不管用户存不存在都执行同样的密码哈希计算——很多框架已经这么做了,但自己写的登录逻辑经常没有),并且对认证端点做速率限制,让统计所需的样本量无法采集。
解析差异与协议边界
35. Splitting the email atom: exploiting parsers to bypass access controls
来源:PortSwigger Research。
读它解决什么:邮箱地址的解析差异如何绕过访问控制。
要点:
- 利用邮箱地址解析器的差异绕过访问控制
- 前提是不同组件对同一个地址的解析结果不同
我的补充:这是我最常提醒人注意的一类问题,因为**"只允许 @company.com 的邮箱注册"这个逻辑到处都有**。邮箱地址的语法比大多数人以为的复杂得多(引号、注释、编码字符、多个 @),于是校验器认为域名是 company.com、而实际投递到了别处的情况是真实存在的。防御原则:不要自己解析邮箱地址来做授权判断。正确做法是发一封带一次性令牌的验证邮件,凭"能收到令牌"来证明控制权——这样不管地址怎么解析,最终投递到哪里就是哪里,绕过解析差异这整类问题。
36. Introducing the URL validation bypass cheat sheet
来源:PortSwigger Research。
读它解决什么:URL 校验为什么这么容易被绕过,有哪些已知模式。
要点:
- 发布 URL 校验绕过的速查表
- 汇总性资源,覆盖多种绕过模式
我的补充:URL 校验绕过最要紧的场景是 SSRF 防护和开放重定向。"只允许跳到本站"和"只允许请求内网白名单"这两类判断都依赖 URL 解析,而 URL 解析的歧义空间极大(@ 分隔的凭据部分、# 的位置、反斜杠、点号变体、IPv6 括号写法、十进制 IP、DNS rebinding)。防御原则:用平台的 URL 解析器解析后取结构化字段判断,不要用正则匹配字符串;重定向目标用白名单或索引映射(用户传 ?next=2,服务端查表得到 URL),不要直接接受完整 URL;SSRF 防护要在连接建立时校验解析后的 IP,而不是只校验域名(否则 DNS rebinding 直接绕过)。
37. New crazy payloads in the URL Validation Bypass Cheat Sheet
来源:PortSwigger Research。
读它解决什么:URL 校验绕过速查表的更新条目。
要点:
- 速查表新增的绕过 payload
- 说明这份清单在持续增长
我的补充:和第一卷第 1 条同样的道理——清单在增长,说明基于清单的防御必输。这份速查表对防御方的正确用法不是"把这些都过滤掉",而是当测试用例:拿它跑一遍自己的 URL 校验逻辑,如果任何一条能通过,说明你的校验方式(大概是正则)从根本上就不对,该换成结构化解析。这个区别很重要:用它补规则是徒劳,用它证伪自己的方案是有效的。
38. Concealing payloads in URL credentials
来源:PortSwigger Research。
读它解决什么:URL 里的凭据部分(user:pass@host)如何被用来隐藏内容。
要点:
- 在 URL 的凭据部分隐藏 payload
- 涉及
userinfo@host这一 URL 组成部分
我的补充:https://looks-legit.com@evil.com/ 这个形式是钓鱼的经典手法——人眼从左往右读会停在第一个域名上,而浏览器按规范取 @ 之后的部分作为主机。它同时也是 URL 校验绕过的常用模式:字符串匹配 "包含 looks-legit.com" 会通过。防御上:解析后取 host 字段判断(第 36 条那个原则);如果你的产品展示用户提交的 URL,显示解析后的真实主机名而不是原始字符串。这条也值得作为安全意识培训的内容,因为它对普通用户特别有效。
39. Fickle PDFs: exploiting browser rendering discrepancies
来源:PortSwigger Research。
读它解决什么:不同浏览器渲染 PDF 的差异造成的攻击面。
要点:
- 利用浏览器 PDF 渲染的差异
- 与本卷主线一致:同一份内容被不同组件不同解读
我的补充:PDF 是个容易被忽略的攻击面,因为大家把它当"文档"而不是"可执行内容"。但 PDF 支持 JavaScript、支持嵌入资源,浏览器内置的渲染器(PDF.js、PDFium)实现差异明显。防御要点:用户上传的 PDF 不要在同源下直接提供——放在独立的域名或对象存储上,或者强制 Content-Disposition: attachment 下载而不是内联渲染。同源渲染的话,PDF 里的脚本就拿到了你的源的权限。这个原则对所有用户上传的内容都适用(HTML、SVG 尤其危险,SVG 里可以直接写 <script>)。
40. Top 10 web hacking techniques of 2024
来源:PortSwigger Research,2025 年初。
读它解决什么:2024 年 Web 攻击面进展的年度综述。
要点:
- 2024 年度十大 Web 黑客技术评选结果
- 与第一卷第 20 条(2025 年度)同一系列
我的补充:这个系列按年读能看出攻击面的迁移轨迹——早年榜单里 XSS 和注入占主导,近几年越来越多是协议层、缓存层、以及组件间不一致的问题。这个迁移是有原因的:框架把代码层面的注入问题基本解决了(自动转义成了默认行为),于是研究重心转向了框架管不到的地方——架构和基础设施。对防御方的含义是:安全投入的重心也该跟着迁移。如果你的安全评审还只覆盖应用代码,不看反向代理配置、CDN 缓存规则、以及各层之间的协议一致性,那就是在防上一个时代的攻击。
本卷小结
三个带走的结论:
- 走私的根源是组件间的解析不一致。 所以防御手段是架构层面的:全链路端到端 HTTP/2(包括 CDN 到源站那一段)、减少异构组件、禁用
TRACE。加 WAF 规则治不了根。 - "时序窗口太窄"不再是降级理由。 单包攻击(第 33 条)把远程竞态的精度提到接近本地。竞态防御只能靠数据库层的原子性,不能靠概率。
- 别自己写解析器做安全判断。 邮箱地址(第 35 条)、URL(第 36–38 条)的语法歧义空间都远超直觉。用平台解析器取结构化字段,或者干脆换成不依赖解析的验证方式(发令牌、查表映射)。
上一卷: ← ① 注入与浏览器攻击面 · 下一卷: ③ 认证、会话与令牌 →
