
Metasploit mailing list archives
Metasploit - Qualys integration
From: Sertan Kolat <sertan () mlists olympos org>
Date: Sun, 28 Mar 2010 22:00:50 +0300
Hi all,I patched the framework to support Qualys' XML output file, so that you can use QualysGuard scan report to try automated exploitation of Qualys tested systems.
Just like importing a Nessus or Nmap output, import an existing Qualys XML report file using the db_import_qualys_xml command.
msf > db_create qualys.msfdb [*] Creating a new database instance... [*] Successfully connected to the database [*] File: qualys.msfdb msf > db_import Qualys_Scan_Results_sample.xml [*] Successfully imported /home/warex/Qualys_Scan_Results_sample.xmlI have been testing this for a while and it seems OK. Some adjustments might be needed.
I am attaching the patch, and a sample Qualys report is available at http://bit.ly/aBDCcv (md5: a3e8d9128b2065c9004bed167c5eaec1)
Cheers, -- Sertan Kolat
Index: lib/msf/core/db.rb =================================================================== --- lib/msf/core/db.rb (revision 8914) +++ lib/msf/core/db.rb (working copy) @@ -1100,6 +1100,8 @@ return import_nessus_xml(data, wspace) when "NessusClientData_v2" return import_nessus_xml_v2(data, wspace) + when "SCAN" + return import_qualys_xml(data, wspace) else # Give up if we haven't hit the root tag in the first few lines break if line_count > 10 @@ -1491,7 +1493,71 @@ end end end + + # + # Import Qualys' xml output + # + def import_qualys_xml_file(filename, wspace=workspace) + f = File.open(filename, 'r') + data = f.read(f.stat.size) + import_qualys_xml(data, wspace) + end + def import_qualys_xml(data, wspace=workspace) + + doc = REXML::Document.new(data) + doc.elements.each('/SCAN/IP') do |host| + addr = host.attributes['value'] + + # Open TCP Services List (Qualys ID 82023) + services_tcp = host.elements["SERVICES/CAT/SERVICE[@number='82023']/RESULT"] + if services_tcp + services_tcp.text.scan(/([0-9]+)\t(.*?)\t.*?\t([^\t\n]*)/) do |match| + if match[2] == nil or match[2].strip == 'unknown' + name = match[1].strip + else + name = match[2].strip + end + handle_qualys(wspace, addr, match[0].to_s, 'tcp', 0, nil, nil, name) + end + end + # Open UDP Services List (Qualys ID 82004) + services_udp = host.elements["SERVICES/CAT/SERVICE[@number='82004']/RESULT"] + if services_udp + services_udp.text.scan(/([0-9]+)\t(.*?)\t.*?\t([^\t\n]*)/) do |match| + if match[2] == nil or match[2].strip == 'unknown' + name = match[1].strip + else + name = match[2].strip + end + handle_qualys(wspace, addr, match[0].to_s, 'udp', 0, nil, nil, name) + end + end + + # VULNS are confirmed, PRACTICES are unconfirmed vulnerabilities + host.elements.each('VULNS/CAT | PRACTICES/CAT') do |cat| + port = cat.attributes['port'] + protocol = cat.attributes['protocol'] + cat.elements.each('VULN | PRACTICE') do |vuln| + refs = [] + qid = vuln.attributes['number'] + severity = vuln.attributes['severity'] + vuln.elements.each('VENDOR_REFERENCE_LIST/VENDOR_REFERENCE') do |ref| + refs.push(ref.elements['ID'].text.to_s) + end + vuln.elements.each('CVE_ID_LIST/CVE_ID') do |ref| + refs.push('CVE-' + /C..-([0-9\-]{9})/.match(ref.elements['ID'].text.to_s)[1]) + end + vuln.elements.each('BUGTRAQ_ID_LIST/BUGTRAQ_ID') do |ref| + refs.push('BID-' + ref.elements['ID'].text.to_s) + end + + handle_qualys(wspace, addr, port, protocol, qid, severity, refs) + end + end + end + end + def import_ip_list_file(filename, wspace=workspace) f = File.open(filename, 'r') data = f.read(f.stat.size) @@ -1641,7 +1707,32 @@ :data => description ? description.text : "", :refs => refs) end + + # + # Qualys report parsing/handling + # + def handle_qualys(wspace, addr, port, protocol, qid, severity, refs, name=nil) + report_host(:workspace => wspace, :host => addr, :state => Msf::HostState::Alive) + + info = { :workspace => wspace, :host => addr, :port => port, :proto => protocol } + if name and name != 'unknown' + info[:name] = name + end + + report_service(info) + + return if qid == 0 + + report_vuln( + :workspace => wspace, + :host => addr, + :port => port, + :proto => protocol, + :name => 'QUALYS-' + qid, + :refs => refs) + end + def process_nexpose_data_sxml_refs(vuln) refs = [] vid = vuln.attributes['id'].to_s.downcase Index: lib/msf/ui/console/command_dispatcher/db.rb =================================================================== --- lib/msf/ui/console/command_dispatcher/db.rb (revision 8914) +++ lib/msf/ui/console/command_dispatcher/db.rb (working copy) @@ -61,6 +61,7 @@ "db_import_nessus_nbe" => "Import a Nessus scan result file (NBE)", "db_import_nessus_xml" => "Import a Nessus scan result file (NESSUS)", "db_import_nmap_xml" => "Import a Nmap scan results file (-oX)", + "db_import_qualys_xml" => "Import a Qualys scan results file (XML)", "db_nmap" => "Executes nmap and records the output automatically", } @@ -930,6 +931,22 @@ end # + # Import Qualys XML files + # + def cmd_db_import_qualys_xml(*args) + if (not (args and args.length == 1)) + print_status("Usage: db_import_qualys_xml <result.xml>") + return + end + + if (not File.readable?(args[0])) + print_status("Could not read the Qualys file") + return + end + framework.db.import_qualys_xml_file(args[0]) + end + + # # Import IP List from a file # def cmd_db_import_ip_list(*args)
_______________________________________________ https://mail.metasploit.com/mailman/listinfo/framework
Current thread:
- Metasploit - Qualys integration Sertan Kolat (Mar 28)
- Re: Metasploit - Qualys integration HD Moore (Mar 28)