Linux漏洞分析入门笔记-CVE-2015-0235
Ubuntu 12.04 32位
ida 7.0
0x00:漏洞描述
1.glibc的__nss_hostname_digits_dots存在缓冲区溢出漏洞,导致使用gethostbyname系列函数的某些软件存在代码执行或者信息泄露的安全风险。
通过gethostbyname()函数或gethostbyname2()函数,将可能产生一个堆上的缓冲区溢出。经由gethostbyname_r()或gethostbyname2_r(),则会触发调用者提供的缓冲区溢出, 漏洞产生时至多sizeof(char* )个字节可被覆盖(因为char*指针的大小,即32位系统上为4个字节,64位系统为8个字节)。
0x01:漏洞分析
1.先静态分析glibc源码中的__nss_hostname_digits_dots函数流程,如图1所示。
图1
图1代码大致流程就是在__nss_hostname_digits_dots中,计算了size_needed,当size_needed > buff_size时,会调用realloc重新申请size_needed的空间。
图2
图2代码流程在计算size_need时,少加了一个sizeof(*h_alias_ptr),少算了4个字节,所以当name全为数字或者.号时,会将name拷贝到buff的hostname,造成一个指针大小字节的堆溢出。
所以要触发成功需要满足的条件为,size_need足够大,让其调用realloc重新分配。name全为数字或者.号。
2.选择一个受漏洞影响的程序clockdiff来调试分析,在IDA中对__nss_hostname_digits_dots下好断点,如图3所示:
图3
F9运行,第一次断下无用不是处理我们自己输入的参数,直接跳过。第二次断下,发现gethostbyname的参数为我们输入的参数。Gethostbyname中调用__nss_hostname_digits_dots,其中缓冲区的大小默认为0x400。在调用realloc处下断点,此时buffer_size= 0x41B,刚好是输入参数的长度,因为size_need大于buffer_size所以须要重新分配空间。
图4
通过上面的判断与计算空间大小后执行到stcpy处(溢出点),通过前面空间的计算,加上字符串结尾的空字节,刚好溢出了一个指针字节。
0x02:总结
1.产生漏洞的条件是当gethostbyname()函灵敏被调用时且满足下面两个条件。
a.size_need足够大,让其调用realloc重新分配。
b.name全为数字或者.号