GHOST漏洞原理简单分析

继 ShellShock漏洞之后,Linux又爆出一重大漏洞。网上各种关于漏洞检查和修复的文章,但很难找到一篇讲述这个漏洞原理的。在阅读网上流传的测试代码后,写一下个人对这个漏洞的简单分析。

这应该是漏洞发布的网址,里面有最详细的解释,本人才疏学浅,只看了少部分,想深入了解的可以直接阅读,如本文有错误,请指正。

http://www.openwall.com/lists/oss-security/2015/01/27/9

漏洞简介:

GHOST是Linux glibc库上的一个安全漏洞,CVE编号为CVE-2015-0235。这是一个缓冲区溢出漏洞,攻击者可以利用它远程执行代码。第一个受影响的版本是GNU C库的glibc-2.2。

其实这个漏洞很早就被发现,在2013年5月21号(在glibc-2.17和glibc-2.18发布之间)已经修复,只是一直没被重视,。目前Qualys公司的安全人员开发了一套完整的针对Exim邮件服务器的攻击PoC,测试中发现可以绕过所有现有保护 ( ASLR,PIE和NX )。且可以攻破32位和64位的机器。这个漏洞回到了人们的视线。

所以,如果你的系统采用最新的glibc是没有这个漏洞的,比如fedora20。之所以现在漏洞被重视,是因为很多系统都没使用新版本的glibc,服务器系统稳定性高于一切,不会很积极把组建升级到新版本,特别是glibc这种基础库。

漏洞原理:

什么是缓冲区溢出:

缓冲区溢出是c程序中经常出现的情况,比如遍历数组时没有控制范围,就会出现段错误。这就是缓冲区溢出,显示段错误是因为系统拦截了越界的操作。

但是,如果系统因为某种原因没有拦截越界操作,那就可能成为一个漏洞。心脏流血就是一个类似的漏洞,但是它是越界读。如果是越界写,就可能覆盖掉不该覆盖的内存段。如果这块内存是数据,那就会造成数据错误。如果这块内存是一个代码,那就可能引起执行错误,精心设计引起的溢出会让系统执行攻击者的代码。

漏洞在哪里产生:

漏洞是glibc中的__nss_hostname_digits_dot()函数导致的,漏洞可以通过gethostbyname *()函数来触发,本地和远程均可行。

gethostbyname*()函数的作用是解析域名。事实上这类函数已经被淘汰。但是很多代码依然依赖这些函数。

我们分析一下网上的这个检测代码:

01 #include <netdb.h>
02 #include <stdio.h>
03 #include <stdlib.h>
04 #include <string.h>
05 #include <errno.h>
06   
07 #define CANARY "in_the_coal_mine"
08   
09 struct {           //测试的结构体 
10   char buffer[1024];           //缓冲区 
11   char canary[sizeof(CANARY)];       //内存区,通常紧接着buffer。 
12 } temp = { "buffer", CANARY };
13   
14 int main(void) {
15   struct hostent resbuf;           //主机信息的结构体 
16   struct hostent *result;
17   int herrno;
18   int retval;
19   
20   /*** strlen (name) = size_needed - sizeof (*host_addr) - sizeof (*h_addr_ptrs) - 1; ***/
21   //对于这个公式还有些疑问
22   size_t len = sizeof(temp.buffer) - 16*sizeof(unsigned char) - 2*sizeof(char *) - 1;
23   char name[sizeof(temp.buffer)];
24   memset(name, '0', len);
25   name[len] = '\0';
26   
27   retval = gethostbyname_r(name, &resbuf, temp.buffer, sizeof(temp.buffer), &result, &herrno);
28   
29   if (strcmp(temp.canary, CANARY) != 0) {     //如果tmp.carry被覆盖了,说明溢出成功。 
30     puts("vulnerable");
31     exit(EXIT_SUCCESS);
32   }
33   if (retval == ERANGE) {                     //函数返回了失败,说明指针越界后被拦截并返回错误码 
34     puts("not vulnerable");
35     exit(EXIT_SUCCESS);
36   }
37   puts("should not happen");           //未溢出,这是不可能的。
38   exit(EXIT_FAILURE);
39 }

这里要先讲一下gethostbyname_r函数,它的参数比较特别。

resbuf是个hostent结构体,结构体中有好几个指针,指向写着主机信息的内存区。而这个内存区就是代码中的tmp.buffer。

name 是要查询的域名,它会被发送到DNS来查询IP等信息。但是这样并不容易引起溢出。

还有一个坑是如果name输入的是IP地址,则不会去DNS查询,而是直接写入到hostent指向的内存区中。这里因为没有进行合法性判断,所以输入奇怪的IP,比如检测代码中的一串0。它会被直接写入tmp.buffer,一同写入的还包括解析的主机信息。所以就很容易超过tmp.buffer的长度,造成溢出。

通过gethostbyname()函数或gethostbyname2()函数,将可能产生一个堆上的缓冲区溢出。经由gethostbyname_r()或gethostbyname2_r(),则会触发调用者提供的缓冲区溢出(理论上说,调用者提供的缓冲区可位于堆,栈,.data节和.bss节等。但是,目前还没有看到这样的情况)。测试代码就是用的gethostbyname_r()。

因为有对IP的判断,所以溢出的内容(name)有一些限制。

  1. 它的第一个字符必须是一个数字。
  2. 它的最后一个字符不能是”.”(点)。
  3. 它必须只包含数字和点(我们称之为“digits-and-dots”要求)。
  4. 它必须足够长,以至于缓冲区溢出。例如,不可重入gethostbyname *()函数最初分配缓冲的调用malloc(1024)(“1 kb”的要求)。
  5. 它必须被成功解析为一个IPv4地址inet_aton(),或作为一个IPv6地址inet_pton()方法。

对此,这个溢出可以对内存块写数字( ‘0 ‘…’ 9′) ,点( “.”) ,和一个终止空字符(‘\0’ ) 。

看上去这个溢出还是有不少限制的,不知道安全人员会通过怎么样巧妙的方式来攻击。

总结:

缓冲区溢出是Linux乃至C类语言很忌惮的东西,它引起的结果其实是让系统把数据当成代码执行。这和SQL注入差不多,但是实现方式不同:

  • SQL注入是因为SQL语言分析的问题,语法中就没把数据和代码分离好。
  • 缓冲区溢出是因为操作内存代码的漏洞。

转载请注明:旅途@KryptosX » GHOST漏洞原理简单分析

时间: 2016-05-27

GHOST漏洞原理简单分析的相关文章

iOS中的定时操作比较和原理简单分析

定时操作对于开发人员来说有着广泛的应用场景:对于iOS开发,实现定时操作的手法也有多种,这里我们简单的进行比较和分析. 1. NSTimer  简单易上手,最高级的api,调用也比较方便.(精度也最低) 但:NSTimer在不做任何额外设置的情况下只能在主线程使用,且会受到其他任务的干扰(主线程runloop执行其他任务,nstimer就不能及时触发): 可以设置NSRunLoopCommonModes来对其加以改善,这个时候主线程的UI操作已经不会阻塞它的触发了. performselecto

Ofsatr 2.6搜索漏洞的简单分析_漏洞研究

看到网上有类似的工具,但分析的文章却没找到,听小黑说黑客手册上有,可惜偶没有杂志,所以就抓包然后看下代码,大致分析了一下.这个漏洞很巧妙.也很经典 :)    GET /search.php?keyword=By%20CN911&cachefile=an85.php%2500&treadinfo=〈?fputs(fop   en(chr(46).chr(47).chr(46).chr(46).chr(47).chr(46).chr(46).chr(47).chr(98).chr(98).c

DWR的Converter实现原理简单分析及应用

我们在应用 DWR 调用远程方法时涉及到 JS 与 JAVA 之间参数和返回值的数据转换,例如: JS 的 123 与 Java 的 int或 Integer.long 间的转换 JS 的 "2009-06-23" 与 Java 的 java.util.Date 之间的转换 JS 的 "[1,2,3]" 与 Java 的 int[] 间的转换 JS 的 "{id:123, name: 'Unmi'}" 与 Java 的 Class Person{

PHP文件上传原理简单分析

//表单上传只能使用multipart/form-data编码格式 $_FILES系统函数; $_FILES['myFile']['name']文件名称 $_FILES['myFile']['type']文件的类型,服务端进行限制 image/** image/x-png application/x-zip-compressed $_FILES['myFile']['size']上传文件大小 $_FILES['myFile']['tmp_name']上传服务后保存临时文件名 $_FILES['m

PHP文件上传原理简单分析_php技巧

//表单上传只能使用multipart/form-data编码格式 $_FILES系统函数; $_FILES['myFile']['name']文件名称 $_FILES['myFile']['type']文件的类型,服务端进行限制 image/** image/x-png application/x-zip-compressed $_FILES['myFile']['size']上传文件大小 $_FILES['myFile']['tmp_name']上传服务后保存临时文件名 $_FILES['m

ShellShock漏洞原理分析

9月24日,广泛存在于Linux的bash漏洞曝光.因为此漏洞可以执行远程命令,所以极为危.危害程度可能超过前段时间的心脏流血漏洞. 漏洞编号CVE-2014-6271,以及打了补丁之后被绕过的CVE-2014-7169,又称ShellShock漏洞. 漏洞起因: 要是用一句话概括这个漏洞,就是代码和数据没有正确区分. 此次漏洞很像SQL注入,通过特别设计的参数使得解析器错误地执行了参数中的命令.这其实是所有解析性语言都可能存在的问题. 1 env x='() { :;}; echo vulne

jquery的相关内容:jquery的简单分析

文章简介:jquery原理的简单分析,扒开jquery的小外套. 引言 最近LZ还在消化系统原理的第三章,因此这部分内容LZ打算再沉淀一下再写.本次笔者和各位来讨论一点前端的内容,其实有关jquery,在很久之前,LZ就写过一篇简单的源码分析.只不过当时刚开始写博客,写的相对来讲比较随意,直接就把源码给贴上来了,尽管加了很多注释,但还是会略显粗糙. 这次LZ再次执笔,准备稍微规范一点的探讨一下jquery的相关内容. jquery的外衣 jquery是一个轻量级的JS框架,这点相信大部分人都听过

对新型无文件后门 JS_POWMET 的简单分析

本文讲的是对新型无文件后门 JS_POWMET 的简单分析, 由于高明的网络犯罪分子会在不留下痕迹的情况下进行攻击,因此不留痕迹的恶意软件将成为未来最常见的攻击方法,而且这种苗头已经开始显现了.比如,今年6月,安全研究人员就发现了一个新的无文件勒索病毒, 被称为"Sorebrect",它将恶意代码注入到目标系统的合法进程svchost.exe中, 然后自毁以躲避检测. 然而,许多所谓的无文件恶意攻击只是在进入用户系统时才是无文件的,而在最终执行其有效载荷时还是会暴露自己,所以要想使用完

Java NIO原理图文分析及代码实现

[本文转载于Java NIO原理图文分析及代码实现] 前言:  最近在分析hadoop的RPC(Remote Procedure Call Protocol ,远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议.可以参考:http://baike.baidu.com/view/32726.htm )机制时,发现hadoop的RPC机制的实现主要用到了两个技术:动态代理(动态代理可以参考博客:http://weixiaolu.iteye.com/blog/