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