Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 6 Jan 2016 21:57:34 -0500
From:      Peter Chen <peterchencs@gmail.com>
To:        Henry Hu <henry.hu.sh@gmail.com>
Cc:        "freebsd-hackers@freebsd.org" <freebsd-hackers@freebsd.org>
Subject:   Re: Nginx Vulnerability on FreeBSD
Message-ID:  <CAHF3bU8BvZcrjFVFwPSF=NotM2FCQgpE1BPgX8Ns2BRV2sHQRg@mail.gmail.com>
In-Reply-To: <CAHF3bU8K3MYASnOOzH2h_Lj7yYR%2B_ex9LmZfAjkFSxVMbPofEw@mail.gmail.com>
References:  <CAHF3bU_KEYaTmeCQvkbPHPG2o=GRZXXXAYiDh4WfFeeLywroNA@mail.gmail.com> <CAEJt7hZiXHALJGaPSua24D_djXrbjiAdfY4A3t3=KGd4Rm1rvA@mail.gmail.com> <CAHF3bU8K3MYASnOOzH2h_Lj7yYR%2B_ex9LmZfAjkFSxVMbPofEw@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
After I tried that on FreeBSD, and used "truss" to trace system calls, the
Nginx worker process still cannot crash.

It seems that FreeBSD's recvfrom() automatically divide the received data
into 4096-sized chunks, and it will not overflow. The system call trace is
as follows (different from
http://www.vnsecurity.net/research/2013/05/21/analysis-of-nginx-cve-2013-2028.html
's
1024 and 4112, here the recvfrom's received size is 1024, 4096 and 16):

========================================================
kevent(8,{},0,{0x6,EVFILT_READ,0x0,0,0x1,0x801cd3000},512,0x0) = 1 (0x1)
gettimeofday({1452134269.299028 },0x0) = 0 (0x0)
accept4(0x6,0x7fffffffe650,0x7fffffffe6bc,0x20000000,0xffff,0x2) = 3 (0x3)
kevent(8,{0x3,EVFILT_READ,EV_ADD|EV_ENABLE|EV_CLEAR,0,0x0,0x801cd30e0},1,{0x3,EVFILT_READ,EV_CLEAR,0,0x1410,0x801cd30e0},512,{60.000000000
}) = 1 (0x1)
gettimeofday({1452134269.299901 },0x0) = 0 (0x0)
recvfrom(3,"GET / HTTP/1.1rnHost: 1337.vnsec"...,1024,0x0,NULL,0x0) = 1024
(0x400)
writev(0x3,0x7fffffffdcb0,0x2,0x7fffffffffffef87,0x68,0x1) = 172 (0xac)
shutdown(3,SHUT_WR) = 0 (0x0)
recvfrom(3,"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...,4096,0x0,NULL,0x0) = 4096
(0x1000)
recvfrom(3,"AAAAAAAACCCCCCCC",4096,0x0,NULL,0x0) = 16 (0x10)
kevent(8,{},0,{0x3,EVFILT_READ,EV_CLEAR|EV_EOF,54,0x0,0x801cd30e0},512,{5.000000000
}) = 1 (0x1)
gettimeofday({1452134269.306013 },0x0) = 0 (0x0)
write(4,"172.16.187.1 - - [06/Jan/2016:21"...,1089) = 1089 (0x441)
close(3)
========================================================

Any idea how to make the crash happen? I can modify the kernel if needed.
But I did not find recvfrom()'s maximum "len" in the recvfrom system call
implementation -- sys_recvfrom.
(
https://github.com/freebsd/freebsd/blob/63cd1c131acbe2c4896430de52395b168ee9b73d/sys/kern/uipc_syscalls.c
)

Thanks!!

On Tue, Jan 5, 2016 at 12:59 AM, Peter Chen <peterchencs@gmail.com> wrote:

> Thanks a million for the prompt reply! I'll try
> http://www.vnsecurity.net/research/2013/05/21/analysis-of-nginx-cve-2013-2028.html
> .
>
> On Tue, Jan 5, 2016 at 12:49 AM, Henry Hu <henry.hu.sh@gmail.com> wrote:
>
>>
>>
>> On Tue, Jan 5, 2016 at 12:14 AM, Peter Chen <peterchencs@gmail.com>
>> wrote:
>>
>>> Hi,
>>>
>>> I am trying to do a security research experiment on FreeBSD.
>>> I try to test the Nginx Vulnerability CVE-2013-2028 on FreeBSD x86-64,
>>> with
>>> Nginx 1.3.9/1.4.0.
>>> (https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-2028)
>>>
>>> However, most exploit samples can succeed on Linux, but not FreeBSD.
>>> The basic idea for the exploit, is to send a packet with a very large
>>> chunk
>>> size, making the victim process stack-overflow. After Nginx's many
>>> crashes,
>>> the attacker can find enough gadgets to launch a return-oriented
>>> programming attack.
>>>
>>> However, it is hard to let Nginx worker process crash (due to overwritten
>>> return address) on FreeBSD. Process crash is the first step of the whole
>>> exploit.
>>>
>>> I guess (probably a wrong guess) the reason may be: the exploit needs to
>>> set MTU to a large value. But FreeBSD seems only to allows a max MTU of
>>> 16110.
>>>
>>> It is probably because of other reasons. Any comments/suggestions on
>>> this,
>>> just to make the victim process crash?
>>>
>>> Here are two exploit code examples, which can run against Linux target,
>>> but
>>> fail to make the Nginx worker process crash on FreeBSD:
>>>
>>> http://www.scs.stanford.edu/brop/
>>> http://www.scs.stanford.edu/brop/nginx-1.4.0-exp.tgz
>>>
>>> https://www.exploit-db.com/docs/27074.pdf
>>> http://seclists.org/fulldisclosure/2013/Jul/att-90/ngxunlock_pl.bin
>>>
>>>
>> With a simple experiment on nginx 1.4.0, it's possible that FreeBSD has
>> more strict checks in recvfrom.
>>
>> For the exploit:
>> Pwning IP 127.0.0.1
>> Pwning
>> Checking for vuln... Not vuln2
>>
>> From error.log:
>> 2016/01/05 00:43:35 [alert] 79819#0: *14 recv() failed (22: Invalid
>> argument) while sending response to client, client: 127.0.0.1, server:
>> localhost, request: "GET / HTTP/1.1", host: "bla.com"
>> From ktrace:
>>  79819 nginx    CALL  recvfrom(0x3,0x801a15400,0x400,0,0,0)
>>  79819 nginx    GIO   fd 3 read 104 bytes
>>        "GET / HTTP/1.1\r
>> ...
>>  79819 nginx    CALL
>> recvfrom(0x3,0x7fffffffcf30,0xeadbeefdeadbef03,0,0,0)
>>  79819 nginx    RET   recvfrom -1 errno 22 Invalid argument
>>
>>
>> From an analysis, this should succeed:
>> (from
>> http://www.vnsecurity.net/research/2013/05/21/analysis-of-nginx-cve-2013-2028.html
>> )
>>
>> strace -p 11337 -s 5000 2>&1 | grep recv
>> recvfrom(3, "GET / HTTP/1.1rnHost: 1337.vnsecurity.netrnAccept:
>> */*rnTransfer-Encoding: chunkedrnrnfff...snip..fff0f0f0f0f", 1024, 0, NULL,
>> NULL) = 1024
>> recvfrom(3, "AAA..snip..AACCCCCCCC", 18446744069667229461, 0, NULL, NULL)
>> = 4112
>>
>>
>>>
>>> Thanks!!
>>>
>>> Best,
>>> Peter
>>> _______________________________________________
>>> freebsd-hackers@freebsd.org mailing list
>>> https://lists.freebsd.org/mailman/listinfo/freebsd-hackers
>>> To unsubscribe, send any mail to "
>>> freebsd-hackers-unsubscribe@freebsd.org"
>>>
>>
>>
>>
>> --
>> Cheers,
>> Henry
>>
>
>



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAHF3bU8BvZcrjFVFwPSF=NotM2FCQgpE1BPgX8Ns2BRV2sHQRg>