cURL MQTT组件双重释放漏洞分析

本文详细分析了cURL库MQTT组件中存在的双重释放漏洞。该漏洞在特定条件下会导致mqtt_doing()函数重复释放内存指针,可能引发内存损坏、拒绝服务甚至代码执行等安全风险。文章包含漏洞代码分析、复现步骤和安全影响评估。

漏洞概述

在cURL库的MQTT组件中发现一个双重释放漏洞,该漏洞存在于mqtt_doing()函数中。当满足以下两个条件时触发:

  1. mqtt_send()无法一次性发送完整缓冲区
  2. 后续的mqtt_send()调用失败

漏洞代码分析

问题代码位置

lib/mqtt.c第755行:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
static CURLcode mqtt_doing(struct Curl_easy *data, bool *done)
{
    // ...
    if(mq->nsend) {
        /* send the remainder of an outgoing packet */
        char *ptr = mq->sendleftovers;
        result = mqtt_send(data, mq->sendleftovers, mq->nsend);
        free(ptr);  // 漏洞点:释放指针后未置空
        if(result)
            return result;
    }
    // ...
}

相关函数代码

mqtt_send函数

1
2
3
4
5
6
7
8
static CURLcode mqtt_send(struct Curl_easy *data, char *buf, size_t len)
{
    CURLcode result = CURLE_OK;
    struct MQTT *mq = data->req.p.mqtt;
    size_t n;
    result = Curl_xfer_send(data, buf, len, FALSE, &n);
    if(result)
        return result;

mqtt_done函数

1
2
3
4
5
6
7
8
9
static CURLcode mqtt_done(struct Curl_easy *data, CURLcode status, bool premature)
{
    struct MQTT *mq = data->req.p.mqtt;
    (void)status;
    (void)premature;
    Curl_safefree(mq->sendleftovers);  // 第二次释放相同指针
    Curl_dyn_free(&mq->recvbuf);
    return CURLE_OK;
}

漏洞复现步骤

  1. 在VS2022中构建cURL
  2. 在以下位置设置断点:
    • mqtt_send()第125行
    • mqtt_doing()第754行
    • mqtt_done()第735行
  3. 设置curl命令行参数:-v mqtt://test.mosquitto.org:1883/test
  4. 运行curl(F5)
  5. mqtt_send()断点触发时,步入Curl_xfer_send()
  6. 在调试器中修改blen值为2(模拟部分传输)
  7. 观察mq->sendleftovers指针分配并记录其值
  8. 继续执行,在mqtt_doing()中模拟发送错误
  9. 观察第755行释放指针但未置空
  10. 继续执行,在mqtt_done()第735行再次释放相同指针

安全影响评估

潜在风险

  • 内存损坏:双重释放可能导致内存损坏,引发不可预测行为或崩溃
  • 任意代码执行:攻击者可能通过操纵内存布局覆盖函数指针
  • 拒绝服务:导致curl进程崩溃或变得无响应

利用条件

  • 恶意MQTT服务器能够控制传输缓冲区可用性
  • 精确的时间同步,使得双重释放在其他线程分配相同内存块之间发生
  • 在高度多线程的服务器环境中风险更高

开发团队回应

漏洞确认

cURL团队确认这是一个真实的bug,但在实际利用难度上存在分歧:

bagder观点

  • 需要恶意MQTT服务器精确控制时序
  • 双重释放发生时间极短(微秒级),难以精确利用
  • 实际利用链复杂,难以构成安全威胁

jimfuller观点

  • 在某些平台malloc实现缺乏检查时可能成为攻击跳板
  • 即使有严格堆分配检查,多线程环境下仍可能发生UAF

修复方案

开发团队提供了修复补丁,将sendleftovers转换为dynbuf实现,从根本上避免双重释放问题。修复已通过GitHub PR #16823提交。

最终状态

报告被标记为"Informative"而非安全漏洞,主要基于实际利用难度评估。但技术层面确认这是真实的双重释放bug,已在代码层面修复。

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