基于Metasploit利用GHOST漏洞最终版 联系客服

发布时间 : 星期二 文章基于Metasploit利用GHOST漏洞最终版更新完毕开始阅读4bcad1d0767f5acfa0c7cd7e

基于Metasploit利用GHOST 漏洞获得远程Exim邮件服务器SHELL

? 分析阶段

1. GHOST漏洞分析及其条件限制

2. 如何利用受GHOST漏洞影响的Exim服务的原理 ? 实际操作阶段

1. 渗透环境搭建:KaliLinux与Metasploit 2. 使用Nmap对目标进行端口扫描及服务查点 3. 快速检查被渗透目标是否存在ghost漏洞

4. 使用Metasploit加载GHOST漏洞攻击模块进行远程入侵,获得远程主机shell

========= 分析开始 =========

? GHOST漏洞分析及其条件限制

GHOST漏洞是2015年1月27号公布的Linux底层漏洞,国际编号为CVE-2015-0235,存在于GNU C库(glibc)中,受影响的Linux发现版本有:Debian 7 (wheezy),Red Hat Enterprise,Linux 6 & 7,CentOS 6 & 7,Ubuntu 12.04等。 存在漏洞的函数__nss_hostname_digits_dots()由glibc的非重入版本的文件:

nss/getXXbyYY.c,以及重入版本:nss/getXXbyYY_r.c提供。然而,这个函数的调用是由#ifdef HANDLE_DIGITS_DOTS来定义的,这个宏定义只在这几个文件有: - inet/gethstbynm.c - inet/gethstbynm2.c - inet/gethstbynm_r.c - inet/gethstbynm2_r.c - nscd/gethstbynm3_r.c

以上这些文件实现gethostbyname*()函数族,因此也只有它们会调用__nss_hostname_digits_dots(),并且可能触发它的缓冲区溢出。该函数的作用是:“如果主机名是IPv4/IPv6地址,就跳过费时的DNS查找”。 glibc-2.17的代码如下:

35 int

36 __nss_hostname_digits_dots (const char *name, struct hostent *resbuf, 37 char **buffer, size_t *buffer_size, 38 size_t buflen, struct hostent **result,

39 enum nss_status *status, int af, int *h_errnop) 40 { ..

57 if (isdigit (name[0]) || isxdigit (name[0]) || name[0] == ':') 58 {

59 const char *cp; 60 char *hostname;

61 typedef unsigned char host_addr_t[16]; 62 host_addr_t *host_addr;

63 typedef char *host_addr_list_t[2]; 64 host_addr_list_t *h_addr_ptrs; 65 char **h_alias_ptr; 66 size_t size_needed; ..

85 size_needed = (sizeof (*host_addr)

86 + sizeof (*h_addr_ptrs) + strlen (name) + 1); 87

88 if (buffer_size == NULL) 89 {

90 if (buflen < size_needed) 91 { ..

95 goto done;

96 } 97 }

98 else if (buffer_size != NULL && *buffer_size < size_needed) 99 {

100 char *new_buf;

101 *buffer_size = size_needed;

102 new_buf = (char *) realloc (*buffer, *buffer_size); 103

104 if (new_buf == NULL) 105 { ...

114 goto done; 115 }

116 *buffer = new_buf; 117 } ...

121 host_addr = (host_addr_t *) *buffer; 122 h_addr_ptrs = (host_addr_list_t *)

123 ((char *) host_addr + sizeof (*host_addr));

124 h_alias_ptr = (char **) ((char *) h_addr_ptrs + sizeof (*h_addr_ptrs)); 125 hostname = (char *) h_alias_ptr + sizeof (*h_alias_ptr); 126

127 if (isdigit (name[0])) 128 {

129 for (cp = name;; ++cp) 130 {

131 if (*cp == '\\0') 132 {

133 int ok; 134

135 if (*--cp == '.') 136 break; ...

142 if (af == AF_INET)

143 ok = __inet_aton (name, (struct in_addr *) host_addr); 144 else 145 {

146 assert (af == AF_INET6);

147 ok = inet_pton (af, name, host_addr) > 0; 148 } 149 if (! ok) 150 { ...

154 goto done; 155 } 156

157 resbuf->h_name = strcpy (hostname, name); ...

194 goto done;

195 } 196

197 if (!isdigit (*cp) && *cp != '.') 198 break; 199 } 200 } ...

Ln 85-86计算所需的缓冲区大小size_needed来存储三个不同的实体: HOST_ADDR,h_addr_ptrs和name(hostname) 。Ln 88-117 确保缓冲区足够大:Ln 88-97对应于函数重入的情况,Ln 98-117为非重入的情况。 Ln

121-125

处理存储四个不同实体的指针地址,

HOST_ADDR,h_addr_ptrs,h_alias_ptr ,和hostname。 计算size_needed时,漏掉了一个sizeof( * h_alias_ptr ) - 也即一个char指针的大小。

因此, strcpy的( )所在的Ln157应该可以让我们写过缓冲区的末尾,至多(取决于函数strlen(name)和对齐) 4个字节 (32位),或8个字节(64位)...

为了在行157触发溢出,主机名参数必须符合下列要求: - 它的第一个字符必须是数字(Ln 127) 。 - 它的最后一个字符不能是点 “.”(Ln 135 ) 。

- 它必须只包含数字和点(Ln 197 ) (我们称之为“数字和点”的要求) 。

- 它必须足够长以溢出缓冲区。例如,非重入的gethostbyname *()函数最开始就会通过调用malloc (1024)来分配自己的缓冲区 (申请 “1 KB”) 。

- 它必须成功地解析为IPv4地址。也即它必须通过INET_ATON()函数的检测!

? 如何利用受GHOST漏洞影响的Exim服务的原理:

在本节中,我们将介绍如何对Exim SMTP邮件服务器实现远程执行代码,绕过NX保护和glibc的malloc强化。