CRLF漏洞

CRLF(Carriage Return + Line Feed,回车 + 换行),是 \r\n 的组合,表示文本换行

\r\n进行URL编码变成%0D%0A

CRLF注入

在输入中插入 \r\n,改变 HTTP 头部或 HTML 页面结构,进而实现 XSS、HTTP 响应拆分(HTTP Response Splitting)、Web 伪造攻击

HTTP响应拆分

原理

服务器在响应 HTTP 头时,通常会使用 \r\n 作为分隔符

如果攻击者可以在 URL 或请求头中注入 \r\n,就可能 伪造 HTTP 头部或插入恶意内容

示例

1
2
3
4
5
HTTP/1.1 200 OK
Content-Type: text/html
Set-Cookie: user=admin

<html><body>Welcome</body></html>

攻击者构造请求:

1
https://example.com/page?param=%0D%0ASet-Cookie:%20admin=true

服务器返回:

1
2
3
4
5
6
HTTP/1.1 200 OK
Content-Type: text/html
Set-Cookie: user=admin
Set-Cookie: admin=true <-- 攻击者成功伪造 Cookie

<html><body>Welcome</body></html>

攻击者成功伪造cookie,可能绕过身份验证,可以用于会话劫持、钓鱼攻击等

其可与location头结合进行重定向

1
https://example.com/page?username=%0D%0ALocation:%20https://evil.com%0D%0A

可能导致服务器返回:

1
2
3
4
5
6
HTTP/1.1 200 OK
Content-Type: text/html
Set-Cookie: user=
Location: https://evil.com <-- 伪造重定向

<html><body>Welcome!</body></html>

用户被恶意跳转到evil.com

CRLF与XSS结合

攻击者构造请求:

1
https://example.com/page?param=%0D%0AContent-Length:%200%0D%0A%0D%0A<script>alert('XSS')</script>

服务器返回:

1
2
3
4
5
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 0 <-- 伪造的 Content-Length

<script>alert('XSS')</script> <-- XSS 代码被执行

CRLF 造成日志伪造

很多 Web 服务器会将请求参数写入日志,例如:

1
[INFO] 2025-02-07 12:00:00 - User input: test

如果攻击者输入 \r\n,可能伪造日志内容:

1
https://example.com/page?param=%0D%0A%5BWARNING%5D%20Security%20Breach!

服务器日志可能变成:

1
2
[INFO] 2025-02-07 12:00:00 - User input: 
[WARNING] Security Breach!

攻击者可以伪造系统日志,可能隐藏攻击痕迹、制造假警报等

防御 CRLF 注入

过滤用户输入,移除 \r\n

1
userInput = userInput.replace(/[\r\n]/g, "");  // 删除 CRLF

对 URL 参数进行编码

1
encodeURIComponent(userInput);

设置 HTTP 头安全策略

启用 CSP只允许同源(self)资源加载(内嵌 HTML(非 JS 或 CSS)),阻止外部资源加载

1
Content-Security-Policy: default-src 'self'

HTTP 头中使用安全 API

setHeader() 时避免拼接用户输入:

1
res.setHeader("Set-Cookie", `user=${encodeURIComponent(username)}`);

确保日志安全

使用 JSON.stringify() 记录日志,防止换行

避免直接写入用户输入