首页/安全/漏洞与攻击面速查/HTTP 响应头注入(CRLF 注入)
Web 漏洞原理与防护55 条

HTTP 响应头注入(CRLF 注入)

把用户输入放入响应头(如 Location、Set-Cookie)时,回车换行字符可拆分出额外头部甚至响应体,形成会话固定或缓存投毒;现代框架通常已默认拦截,拼接型代码仍要警惕。

漏洞与攻击面速查安全更新于 2026-10-13

CRLF 注入的原理

HTTP 响应头以回车换行(CRLF)分隔,把用户输入直接放进响应头值(如 Location、Set-Cookie 或自定义头)时,输入中的换行符可以提前结束当前头部并注入新头部甚至响应体。后果包括响应拆分、缓存投毒与会话固定。现代框架与运行时多数会直接拒绝含 CR/LF 的头值,但拼接型代码和老旧运行时仍需自行加固。

基本信息

涉及字符CR(\r,%0d)与 LF(\n,%0a)
触发位置响应头赋值处,如 Location、Set-Cookie、自定义头
可能后果响应拆分、缓存投毒、会话固定
缓解方向剔除换行、改用白名单、升级运行时
自检方式检索代码中拼接响应头的位置并逐处复核

典型使用场景

  • 重定向:Location 头由用户参数拼出(与开放重定向常同时出现)
  • 设置 Cookie:名称或值来自用户输入时
  • 自定义头回显:把请求信息回写到响应头用于调试
  • 下载文件名:Content-Disposition 中拼入用户提供的文件名
  • 网关与中间件:自研的反向代理头部处理逻辑

风险与修复示例

风险与修复示例
风险:response['Location'] = user_input
修复:剔除 \r 与 \n,或改为仅允许站内路径白名单
框架层:主流现代框架直接抛错拒绝含 CR/LF 的头值
自研网关:对头部值做字符白名单校验,而不是只做长度限制
下载文件名:去除换行并按规范做编码,避免头部被截断

自检要点

自检要点
检索代码中拼接响应头的位置(Location、Set-Cookie、Content-Disposition)
覆盖自定义头与错误页头信息
检查框架与运行时版本:老版本可能不默认拦截
结合缓存层评估:共享缓存被污染的影响面远大于单次响应
复核网关与中间件:自研头部处理逻辑最容易漏检

常见入口与检查点

入口检查点加固方式
重定向跳转参数是否进入 Location相对路径校验 + 剔除换行
Cookie名称与值是否来自输入固定名称,值做白名单
下载文件名是否拼入 Content-Disposition文件名净化并按规范编码
调试头是否回写请求信息改为记录日志,不回写头部
只处理 %0d%0a 这类字面量不足以保证安全:二次编码或字符归一化后仍可能还原为 CR/LF,校验应在解码与规范化之后,并以字符白名单为准。
老版本语言运行时可能不默认拦截换行符,升级运行时本身也是缓解手段之一;但升级不能替代代码层的输入校验,两者要一起做。

易错点

  • 只处理 %0d%0a 字面量:二次编码或字符归一化后仍可能还原为 CR/LF
  • 只在应用层加固:自研网关与中间件同样拼接头部,容易被整体漏掉
  • 忽略缓存层:响应拆分一旦污染共享缓存,影响范围会从单个用户扩大到所有人
  • 把长度限制当作防护:短小的换行载荷就能完成注入,长度限制拦不住

数据来源与参考

  • OWASP HTTP Response Splitting 说明
  • RFC 7230(头部字段语法)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌