CVE-2013-2028 经典栈溢出漏洞复现资料整理

一个经典的由整数溢出导致栈溢出的漏洞。下面感觉写的有点乱。

复现漏洞

  • CVE-2013-2028:nginx 栈溢出漏洞

相关基础知识

  • 栈的基础知识:https://ctf-wiki.github.io/ctf-wiki/pwn/linux/stackoverflow/stack-intro-zh/

  • 栈溢出原理:https://ctf-wiki.github.io/ctf-wiki/pwn/linux/stackoverflow/stackoverflow-basic-zh/

  • 基础的ROP:https://ctf-wiki.github.io/ctf-wiki/pwn/linux/stackoverflow/basic-rop-zh/

  • 一步一步学rop(蒸米rop):

    • 一步一步学ROP(x86):http://www.vuln.cn/6645
    • 一步一步学ROP(x64):http://www.vuln.cn/6644
    • 其他人学习蒸米rop的记录:https://www.yuque.com/hxfqg9/bin/zzg02e

CVE-2013-2028原理

参考资料

  • (这篇比较详细)https://www.cnblogs.com/iamstudy/articles/nginx_CVE-2013-2028_brop.html
  • https://www.anquanke.com/post/id/85331
  • http://www.91ri.org/6029.html

原理简述

CVE-2013-2028是nginx的一个整数溢出导致栈溢出的漏洞。

从触发漏洞的关键函数ngx_http_discard_request_body开始分析。这个函数中,会对chunked的值进行判断,如果chunked的值为1,则会进入到if语句内部处理逻辑,会调用另一个函数ngx_http_discard_request_body_filter

ngx_http_discard_request_body(ngx_http_request_t *r)
{
    if (size || r->headers_in.chunked) {
        rc = ngx_http_discard_request_body_filter(r, r->header_in);
        if (rc != NGX_OK) {
            return rc;
        }
        if (r->headers_in.content_length_n == 0) {
            return NGX_OK;
        }
    }
    ngx_http_read_discarded_request_body

在执行ngx_http_discard_request_body离开if语句逻辑后,会执行ngx_http_read_discarded_request_body。首先先看if里的ngx_http_discard_request_body_filter函数。

ngx_http_discard_request_body_filter(ngx_http_request_t *r, ngx_buf_t *b)
{
     for ( ;; ) {
            rc = ngx_http_parse_chunked(r, b, rb->chunked);
            if (rc == NGX_OK) {
                /* a chunk has been parsed successfully */
            }
            if (rc == NGX_DONE) {
                /* a whole response has been parsed successfully */
            }
            if (rc == NGX_AGAIN) {
                /* set amount of data we want to see next time */
                r->headers_in.content_length_n = rb->chunked->length;
                break;
            }

注意在for循环中会进行三个if语句逻辑处理,分别对应三种NGX状态,在rc==NGX_AGAIN的时候,会对content_length_n成员变量进行赋值。NGX_AGAIN就是要第二次接收时才会触发,所以要发两个数据包才会触发该漏洞。

通过动态调试会知道content_length_n的值成了一个极大值0xfdffbbffa8afed92。随后进入ngx_http_read_discarded_request_body函数处理。

src/http/ngx_http_request_body.c:676
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_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "http read discarded body");
    ngx_memzero(&b, sizeof(ngx_buf_t));
    b.temporary = 1;
    for ( ;; ) {
        if (r->headers_in.content_length_n == 0) {
            r->read_event_handler = ngx_http_block_reading;
            return NGX_OK;
        }
        if (!r->connection->read->ready) {
            return NGX_AGAIN;
        }
        size = (size_t) ngx_min(r->headers_in.content_length_n,
                                NGX_HTTP_DISCARD_BUFFER_SIZE);//key!!
        n = r->connection->recv(r->connection, buffer, size);//key!!

在22行,会调用ngx_min函数进行比较,会取content_length_n和NGX_HTTP_DISCARD_BUFFER_SIZE里较小的值。由于content_length_n为一个负数,这里的比较是进行有符号比较,因此,最小值是content_length_n。由于在比较时,ecx存放后8位,edx存放前8位,随后会将ecx的值交给size,这个size是极大值,比buffer的4096大很多,在进行recv的时候,就会接收一个超过buffer大小的数据,造成栈溢出。

总而言之就是,一个整数溢出导致的栈溢出。

安装漏洞环境

ubuntu 安装

获取nginx源码

sudo apt-get update -y
sudo apt-get install -y libssl-dev gcc make wget tar
wget https://github.com/nginx/nginx/archive/release-1.4.0.tar.gz && tar xfv release-1.4.0.tar.gz

build

Without stack cookies:

./auto/configure --without-http_rewrite_module --without-http_gzip_module
vim Makefile
# Add '-fno-stack-protector' to the CFLAGS
make -j4
sudo make install

With stack cookies:

./auto/configure --without-http_rewrite_module --without-http_gzip_module
make -j4
sudo make install

run

sudo /usr/local/nginx/sbin/nginx -g "daemon off;"

在浏览器输入localhost,可以看到如下界面,说明nginx服务开启成功了

CVE-2013-2028 经典栈溢出漏洞复现资料整理_第1张图片

docker安装

参考:https://github.com/m4drat/CVE-2013-2028-Exploit

这时访问localhost:8081可以出现上面一样的界面,因为docker-compose里将80端口映射到8081了。

metasploit框架

搜索漏洞

search cve-2013-2028

使用exp

use exploit/linux/http/nginx_chunked_size 

这里没写全,可以看msf的文档复现。

触发漏洞

可以参考这个链接来触发漏洞:
https://github.com/mudongliang/LinuxFlaw/tree/master/CVE-2013-2028

网站上现有的exp

github:

  • (python实现,代码量相对多,文档详细)https://github.com/kitctf/nginxpwn
  • (python实现,代码量少,文档不详细,但代码易懂,我主要基于这个复现)https://github.com/m4drat/CVE-2013-2028-Exploit
  • (ruby实现,也有文档,但不太详细)https://github.com/danghvu/nginx-1.4.0
  • (not stable):https://github.com/tachibana51/CVE-2013-2028-x64-bypass-ssp-and-pie-PoC

exploit db:

  • CVE-2013-2028:https://www.exploit-db.com/exploits/32277

你可能感兴趣的:(漏洞复现,安全,整数溢出,栈溢出,nginx)