articles
articles copied to clipboard
openssl CVE-2016-0799分析
openssl CVE-2016-0799分析
环境准备
git clone https://github.com/openssl/openssl
漏洞分析
利用github
直接搜索
可以看到存在解决这个问题的commit
,进入
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
不可控,可直接导致内存被改写
总结
- 分配失败,尽量直接处理
- 考虑整数溢出的问题