I made a multi-thread based HTTP proxy server written in C.
It works fine for simple case, but it crashes occasionally.
Can you find me the bug?
(it has watchdog, proxy server will be respawned after crashing)
* uname -a of server : FreeBSD bsd32 9.1-RELEASE FreeBSD 9.1-RELEASE #0 r243826: Tue Dec 4 06:55:39 UTC 2012 root@obrian.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC i386
So the server has a running log.
Every log entry is stored in a double linked list,
when the number of entries exceeds 32 the oldest is removed from the back of the list
(by taking the prev of the log head).
The log can be accessed remotely (by making a http request).
The vulnerability
After digging/dicking around for a while with the server itself and FreeBSD.
You notice that:
There is a straight forward overflow in the host field of the log entries
We can control the next and prev pointers
We can leak the next and prev pointers (by filling all the host field and reading the log)
The prev pointer of the head is only overwritten after a new entry is added
We can overwrite the next and prev pointers
We can use the “log cleaning” functionality to get arbitraty writes!
There are no protections on the binary whatsoever!
Our stategy
Fill the log (32 entries)
Insert shellcode into host field and a leak the next pointer (to get its address)
Create an log entry (tail) like this:
1
2
3
4
5
6
7
+0 | IP
+4 | Port
+8 | 112 bytes of junk
+120 | Our next
+124 | Our prev
+128 | next
+132 | prev
Make “Our next” the address of the return address (taking care of offset)
Make “Our prev” the value (address of shellcode)
Make a new entry with prev pointing at the (tail - 0x8)
“Clean the log”
Win?
Do it
After writing shellcode (reverse shell) –
and taking care to avoid null bytes and slashes.