Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

openssl CVE-2016-0799分析 #38

Open
xinali opened this issue Apr 23, 2019 · 0 comments
Open

openssl CVE-2016-0799分析 #38

xinali opened this issue Apr 23, 2019 · 0 comments

Comments

@xinali
Copy link
Owner

xinali commented Apr 23, 2019

openssl CVE-2016-0799分析

环境准备

git clone https://github.com/openssl/openssl

漏洞分析

利用github直接搜索

1555943154416

可以看到存在解决这个问题的commit,进入

1555943313776

commit做了很完善的说明,那就根据commit说明来具体看一下为什么会出现这个问题,切换到其父commit

git checkout 069c3c0908dfa8418753d0c25890a9d4fb67178d

首先出现问题的最主要的函数是这个

static void
doapr_outch(char **sbuffer,
            char **buffer, size_t *currlen, size_t *maxlen, int c)
{
    /* If we haven't at least one buffer, someone has doe a big booboo */
    assert(*sbuffer != NULL || buffer != NULL);

    /* |currlen| must always be <= |*maxlen| */
    assert(*currlen <= *maxlen);

    if (buffer && *currlen == *maxlen) {
        *maxlen += 1024;
        if (*buffer == NULL) {
            *buffer = OPENSSL_malloc(*maxlen);
            if (*buffer == NULL) {
                /* Panic! Can't really do anything sensible. Just return */
                return;
            }
            if (*currlen > 0) {
                assert(*sbuffer != NULL);
                memcpy(*buffer, *sbuffer, *currlen);
            }
            *sbuffer = NULL;
        } else {
            *buffer = OPENSSL_realloc(*buffer, *maxlen);
            if (!*buffer) {
                /* Panic! Can't really do anything sensible. Just return */
                return;
            }
        }
    }

    if (*currlen < *maxlen) {
        if (*sbuffer)
            (*sbuffer)[(*currlen)++] = (char)c;
        else
            (*buffer)[(*currlen)++] = (char)c;
    }
    return;
}

这个函数可能会出现如下问题

1. 没有错误处理,导致错误
2. size_t溢出,导致错误

而且根据这里

 if (*currlen < *maxlen) {
        if (*sbuffer)
            (*sbuffer)[(*currlen)++] = (char)c;
        else
            (*buffer)[(*currlen)++] = (char)c;
    }

可以基本推测,该函数肯定是会被循环调用的。

考虑这么一种情况在

条件 结果
第一次buffer && *currlen == *maxlen执行后 *sbuffer=NULL
第二次buffer && *currlen == *maxlen执行后 如果relloc分配失败,*buffer=NULL

再次循环来到这里

if (*currlen < *maxlen) {
        if (*sbuffer)
            (*sbuffer)[(*currlen)++] = (char)c;
        else
            (*buffer)[(*currlen)++] = (char)c;
    }

*sbuffer==NULL,进入

(*buffer)[(*currlen)++] = (char)c;

*buffer==NULL,而currlen不可控,可直接导致内存被改写

总结

  1. 分配失败,尽量直接处理
  2. 考虑整数溢出的问题

参考

OpenSSL CVE-2016-0799: heap corruption via BIO_printf

@xinali xinali changed the title openssl CVE-2016-0799分析 openssl CVE-2016-0799分析(不间断更新) Apr 24, 2019
@xinali xinali changed the title openssl CVE-2016-0799分析(不间断更新) openssl CVE-2016-0799分析 Apr 24, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant