Thursday, May 23, 2013

Jinx Part 2: nginx CVE-2013-2028

Who doesn't love vulnerabilities in web servers? We've written nginx bugs before and it was a lot of fun. Now Immunity is pleased to release to its CEU customers the 64 bit version of CVE-2013-2028 written up by a new member of the Linux exploit team. Since this is exploit is in recent versions of nginx only and in our experience most modern web servers tend to be 64 bit, we decided to develop against that architecture. This particular exploit is a good example of a modern remote exploit against hard to exploit software. There has been some good analysis of this vulnerability thus far but as Immunity has a working exploit we thought it worthwhile to chime in.

One of the first hurdles to overcome is not knowing a function's location in memory, ASLR has made information leak vulnerabilities very valuable as a result of its widespread implementation. In the absence of an information leak an attacker is left with brute force or another alternative that we'll discuss later. From there it's on to a ROP chain which may be very dependent on the version of libraries available on the system. Complicating all this is the fact that compiling software from scratch on Linux systems is very common, system administrators may pass any number of configuration or compiler options that change things just enough to break exploits that make too many assumptions.

A problem with basing targeting for exploits on pre-compiled binaries that you might get through apt-get or yum is that maintaining a list of targets and offset combinations becomes very cumbersome. And you've got to test against a large cross section of distribution and server version combinations which can be time intensive. When developing the exploit for this vulnerability we decided to make it as universal as possible and find all the memory locations we would need manually. This has the consequence of taking more time to run (5-20 minutes) but the benefit of working out of the box against more environment combinations. You may remember a similar situation with our exploit for Samba's CVE-2012-1182.

With this vulnerability the exploit takes over an nginx worker process (defined in conf/nginx.conf, default 4) and that process will not respond to other normal nginx work while your shell is active so launching a trojan and getting out of the worker if there aren't many will help avoid detection. In talking with the developer who wrote up this exploit another interesting issue presented itself. There is a condition whereby the target is vulnerable but not exploitable. If the stack canary or function addresses we use from libc contain bad bytes then that can cause exploitation to fail. The worker processes inherit their canaries from the parent and therefore killing them won't grant you a new canary and if by some cosmic roll of the dice libc is in a bad location then you're just out of luck. The upshot is that failed exploitation attempts will only kill the worker process and you can try again.

This exploit reuses the socket that established the connection to the web server in the first place. This is very helpful when dealing with hosts that have strict egress filtering, for instance where web servers are not able to initiate outbound connections. So before you upload and execute your trojan to get out of the worker process you'll want to determine what egress filtering (if any) may be in place. If you anticipate strict egress filtering is present then compromising the server during off hours and automating finding an egress part should be part of your game plan. The likelihood of crashing the server or the parent nginx process with this exploit is very low, nor did we observe the case of a worker process getting hung and no longer being available. In our testing we found the exploit to reliably get a shell over 90% of the time. The exploit presents a low risk high reliability method for getting a shell on an nginx webserver.

No comments: