Each one of these buffers are on the stack. We see there is an overflow possibility on method and http_version. However for method, there is a strcmp("GET") following immediatly after, and overflowing http_version would just overwrite method. Moreover, those two buffers are not used thereafter.

Then, the program discards HTTP headers line by line (1024 chars max) until it founds an empty CRLF line, and calls serve() with the socket and &url as parameters. serve() parses the URL to get the hostname/port couple, performs the HTTP request and echoes the result. If the domain name cannot be resolved (error in gethostbyname), clienterror("404", "Not found", "Could not find DNS entry for %s"%(hostname)) is called.

We control details, which has a maximum length of roughly 0x800 (a bit less than 0x800 max for the first sscanf, to which is prefixed "Could not..."). As the stack buffer (buf1) is only 0x458 long, we have a pretty large overflow under the return address. However, we cannot use one of '\x00\x09\x0a\x0c\x20\x2f\x3a\x2f' in our input, some because they are scanf delimiters, some because they are URL delimiters. Moreover, what lies after our overflow is also overwritten by HTML junk. This means that we cannot simply leak addresses or do a 2 stage exploitation, as we cannot perform send() or recv() with correct descriptors.

The executable is stackexec, so the first possibility is to bruteforce the stack address, we 2 nopsled+shellcode both before and after the return address (~0x1000 bytes steps). In ropasaurus we saw that the machines were actually x64, so the stack addresses would go from ~ 0xff600000 to 0xffff0000 for a 32-bit process. Remotely, this means a ~20mn exploit.

A second possiblity is to find a ret2libc that does not use null bytes to copy a and execute a shellcode onto the bss. This is possible with sprintf, as long as we fulfill 3 conditions: we can find each bytes of the shellcode at a fixed address, we have enough space for the rop chain to copy them all, the addresses don't use any of the chars '\x00\x09\x0a\x0c\x20\x2f\x3a\x2f'. For the shellcode, we just need to place a normal shellcode on the stack, and a tiny bytecode on the bss that returns a bit higher onto the stack (or lower if we place the shellcode before the return address). For instance:

BITS 32
mov eax, esp
add ax, 0x0101
push eax
ret

So, if we can find the bytes of this small bytecode, copy in the bss by chaining sprintfs on addresses that do not contain forbidden chars and return into the bss, we win. And winning we do:

Contenu populaire

Totally, tiredness tends to make me search for way too complicated things :) Thanks for sharing

k3rensk123/04/13 22:37

This is pretty nice I really learned a lot from this solution. Very nice. However, you could've saved yourself some time by closely looking at the disassembly. There is a copy of the data you send at a higher address on the stack than the address you are overflowing at. Essentially, by the time you trigger the overflow the stack roughly looks like this: