PolarSSL 未初始化内存导致远程命令执行
杀戮 (杂役) | 2015-01-20 17:00
0x00 简介
原文: https://www.certifiedsecure.com/polarssl-advisory/
相关报道:http://threatpost.com/potential-code-execution-flaw-haunts-polarssl-library/110505
PolarSSL 源码:https://github.com/polarssl/polarssl/
今天早些时候PolarSSL被爆出远程命令执行,嗯,应该是今天,PolarSSL是一个开源的ssl代码库,被相当多的开源项目使用,具体可以在以下这个网址看见,之后同学们就会觉得,卧槽是个大洞。
https://polarssl.org/kb/generic/projects-using-polarssl
该漏洞的利用可以通过使用特殊构造的 X.509 证书,当PolarSSL将证书进行解析时漏洞被触发。博主的意思似乎是 可以构造一个恶意服务器,或者一个恶意客户端,然后去玩坏别人,我个人倒是觉得他可能已经实践过了。
0x01 版本影响
PolarSSL >= PolarSSL 1.0
0x02 漏洞原因
漏洞代码 https://github.com/polarssl/polarssl/blob/master/library/asn1parse.c 244行 到 292 行
# asn1_get_sequence_of 解析 ASN1 , 就当成解析 x.509证书就好了, ASN1是证书数据结构的一种形式。
int asn1_get_sequence_of( unsigned char **p,
const unsigned char *end,
asn1_sequence *cur,
int tag)
{
int ret;
size_t len;
asn1_buf *buf;
/* Get main sequence tag */
if( ( ret = asn1_get_tag( p, end, &len,
ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
return( ret );
if( *p + len != end )
return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
while( *p < end )
{
buf = &(cur->buf);
buf->tag = **p;
if( ( ret = asn1_get_tag( p, end, &buf->len, tag ) ) != 0 )
return( ret );
buf->p = *p;
*p += buf->len;
#分配和指定下一个指针的时候没有进行 零初始化(就是都设置成0),就添加入cur。
if( *p < end )
{
cur->next = (asn1_sequence *) polarssl_malloc(
sizeof( asn1_sequence ) );
if( cur->next == NULL )
return( POLARSSL_ERR_ASN1_MALLOC_FAILED );
#memset( cur->next, 0, sizeof( asn1_sequence ) ); 这行是补丁,把cur->next设置成0
cur = cur->next;
}
}
/* Set final sequence entry's next pointer to NULL */
cur->next = NULL;
if( *p != end )
return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
return( 0 );
}
因为没有进行零初始化,下次迭代的时候下面的代码会被触发
# asn1_get_tag获取tag和tag的长度,赋值给ret,如果不为0,将其返回。
if( ( ret = asn1_get_tag( p, end, &buf->len, tag ) ) != 0 )
return( ret );
就是说链表的 最后一个 指针"NEXT" 从不进行初始化。
下面就是最后的处理代码:
漏洞代码: https://github.com/polarssl/polarssl/blob/master/library/x509_crt.c 2039行->2046行
seq_cur = cert_cur->ext_key_usage.next;
# 迭代链表,似乎是因为最后一个next未进行初始化导致内存可控。
while( seq_cur != NULL )
{
seq_prv = seq_cur;
seq_cur = seq_cur->next;
polarssl_zeroize( seq_prv, sizeof( x509_sequence ) );
polarssl_free( seq_prv );
}
牛逼哒哒的博主最后提出了两种利用方式,为经初始化的内容可以通过操纵堆分配进行控制,反过来说可以清除任意内存地址,或者在任意内存地址上触发free()。
关于利用的技巧可以参考下面两篇博客
[1]: The poisoned NUL byte, 2014 edition LINK (嘛,project zero最近真是无处不在)
[2]: Understanding the heap by breaking it LINK