瑞星卡卡安全论坛

首页 » 个人产品讨论区 » 瑞星杀毒软件 » 瑞星杀毒软件V16+ » 瑞星OpenSSL(CVE-2014-0160)漏洞分析报告
瑞星工程师12 - 2014-4-11 17:10:00
1. CVE-2014-0160漏洞背景
2014年4月7日OpenSSL发布了安全公告,在OpenSSL1.0.1版本中存在严重漏洞(CVE-2014-0160)。OpenSSL Heartbleed模块存在一个BUG,问题存在于ssl/dl_both.c文件中的心跳部分,当攻击者构造一个特殊的数据包,满足用户心跳包中无法提供足够多的数据会导致memcpy函数把SSLv3记录之后的数据直接输出,该漏洞导致攻击者可以远程读取存在漏洞版本的OpenSSL服务器内存中多达64K的数据。
2. OpenSSL受影响版本的分布
根据已经公开的信息,该漏洞影响分布情况如下。
•    OpenSSL 1.0.1f                  (受影响)
•    OpenSSL 1.0.2-beta        (受影响)
•    OpenSSL 1.0.1g                (不受影响)
•    OpenSSL 1.0.0 branch    (不受影响)
•    OpenSSL 0.9.8 branch    (不受影响)

用户系统信息:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.1) Gecko/20090624 Firefox/3.5
瑞星工程师12 - 2014-4-11 17:13:00
3. 产生漏洞的主要原因
比较OpenSSL 1.0.1g、OpenSSL 1.0.1f两个文件。
在这两个文件的ssl文件夹中的d1_both.c、t1_lib.c两个文件中,都有一个tls1_process_heartbeat函数,它就是漏洞的关键。如下图:

图左比图右的代码,添加了两个判断,主要是针对length字段。再查看length的声明,如下图。

OpenSSL 1.0.1f处理过程代码:
#define n2s(c,s)    ((s=(((unsigned int)(c[0]))<< 8)| \
                (((unsigned int)(c[1]))    )),c+=2)
int
dtls1_process_heartbeat(SSL *s)
    {
    unsigned char *p = &s->s3->rrec.data[0], *pl;
    unsigned short hbtype;
    unsigned int payload;
    unsigned int padding = 16; /* Use minimum padding */

    /* Read type and payload length first */
    hbtype = *p++;
    n2s(p, payload);
    pl = p;

    if (s->msg_callback)
        s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT,
            &s->s3->rrec.data[0], s->s3->rrec.length,
            s, s->msg_callback_arg);

    if (hbtype == TLS1_HB_REQUEST)
        {
        unsigned char *buffer, *bp;
        int r;

        /* Allocate memory for the response, size is 1 byte
        * message type, plus 2 bytes payload length, plus
        * payload, plus padding
        */
        buffer = OPENSSL_malloc(1 + 2 + payload + padding);
        bp = buffer;

        /* Enter response type, length and copy payload */
        *bp++ = TLS1_HB_RESPONSE;
        s2n(payload, bp);
        memcpy(bp, pl, payload);
        bp += payload;
        /* Random padding */
        RAND_pseudo_bytes(bp, padding);

        r = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, 3 + payload + padding);

        if (r >= 0 && s->msg_callback)
            s->msg_callback(1, s->version, TLS1_RT_HEARTBEAT,
                buffer, 3 + payload + padding,
                s, s->msg_callback_arg);

        OPENSSL_free(buffer);

        if (r < 0)
            return r;
        }
    else if (hbtype == TLS1_HB_RESPONSE)
        {
        unsigned int seq;

        /* We only send sequence numbers (2 bytes unsigned int),
        * and 16 random bytes, so we just try to read the
        * sequence number */
        n2s(pl, seq);

        if (payload == 18 && seq == s->tlsext_hb_seq)
            {
            dtls1_stop_timer(s);
            s->tlsext_hb_seq++;
            s->tlsext_hb_pending = 0;
            }
        }

    return 0;
    }
处理过程:从数据中读取长度payload,并根据数据包长度直接申请内存,然后拷贝payload 大小的数据到申请的内存空间;由于没有验证length是否真是数据包的实际大小,所以如果让有心人伪造一个length字段(length字段比实际数据要大),就可以越界访问内存,从而导致内存泄漏。

而OpenSSL 1.0.1g 文件中,则对length字段进行了相关的验证。
50hzq - 2014-4-11 17:24:00
支持一下
1
查看完整版本: 瑞星OpenSSL(CVE-2014-0160)漏洞分析报告