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.xml


I 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: