- 搭建环境
Ubuntu 12.04 32位
选择漏洞受影响的程序:clockdiff(http://bobao.360.cn/learning/detail/224.html)
安装:
sudo apt-get install iputils-clockdiff
运行:
clockdiff `python -c "print '0' * $((0x20000-16*1-2*4-1-4))"`
发生段错误。
- 源码调试
因为知道漏洞出在glbc中,所以考虑搭建源代码调试glibc环境。
sudo apt-get install libc6-dbg sudo apt-get source libc6-dev //下载eglibc源码
在gdb调试时使用命令 directory <path>/eglibc-2.15/nss/就可以直接在 gethostbyname和__nss_hostname_digits_dots下断点了。
- 静态分析
在__nss_hostname_digits_dots中,计算了size_needed。
当size_needed> buff_size时,会调用realloc重新申请size_needed的空间。
从下图代码中可以知道buff缓冲区的内存布局为:
{ struct host_addr_t host_addr;//0x10字节 struct h_addr_ptrs h_addr_ptrs;//8字节 struct h_alias_ptr h_alias_ptr;//4字节 char * hostname; }
而在计算size_need时,少加了一个sizeof(*h_alias_ptr),少算了4个字节。
所以当name全为数字或者.号时,会将name拷贝到buff的hostname,造成4字节的堆溢出。
要触发成功需要满足的条件为
1>size_need足够大,让其调用realloc重新分配。
2>name全为数字或者.号
- 动态分析
下断点
运行,第一次断下发现是查自己的,直接跳过。
第二次断下,发现gethostbyname的参数为输入的参数。
Gethostbyname中调用__nss_hostname_digits_dots,其中缓冲区的大小默认为0x400。
在调用realloc处下断点,此时buffer_size= 0x0001fffc
在strcpy处下断点
此时,缓冲区的起始地址=host_addr=0x9e0dcd0,而hostname的起始地址为0x9e0dcec,所以真正留给host_name的空间为0x1fffc+host_addr-hostname=0x1ffe0。
而name的总长度= 0x20000-16*1-2*4-1-4= 0x1ffe3,加上字符串结尾的空字节,刚好多出了4个字节。
相关文章《Linux glibc幽灵漏洞简介与修复方法》
【via@91ri.org团队_Ling,未经授权,请勿转载!】