dradis-qualys 4.2.0 → 4.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3ba4d6ad211ac3a9b0b671a70ca898f8b4209476b0a60f2da30e8e4421a805f6
4
- data.tar.gz: 5d2e7db73a7a40784fa6c4334e060daa1cbf730655d489efe594f3fd8acb7b07
3
+ metadata.gz: 0504ea6b549f45f867baa52b9719ede56f61334d47df0671abf7c5b3039c157a
4
+ data.tar.gz: f5a740f35c3544f6e8863ee920bbecb67f18516524d17d21861933d150248b54
5
5
  SHA512:
6
- metadata.gz: d612c8715670f02a26c9be3efc6f9406c5543e3e5b76725d56baf394a0cce8eeafe4fd2c8cab28e2558b70d60b9e72a79c25a29a9266df52e0efa32a963425ae
7
- data.tar.gz: e3ae22e600fa0b9ad4f96215ed9e981f4f932bc38480ee48608f28c578c1fe53d426550c30b0a6228d0109d36f422eb7deee3fc6df62359c55cc39396c42848c
6
+ metadata.gz: 00c451d247bccc3a1ee3c7a2894d49f2bc41c7ca4e1b28deb626c917ae77ee4a2614b9cdb1f5784b9cde1979a4cb7f6861cb3c0d1e75b89f9dc6e1aabd1883de
7
+ data.tar.gz: 535efa81757370066dfb0e5e4ef04622020fec34088dd155de0422de78a7de67e7e0230a953b3eb23342d34ef408dba67b7213b076ae61bf326c2bd51c69bcaa
data/CHANGELOG.md CHANGED
@@ -1,6 +1,17 @@
1
+ v4.5.0 (August 2022)
2
+ - Wrap ciphers in code blocks for the Vuln Importer
3
+
4
+ v4.4.0 (June 2022)
5
+ - Registers template mappings locally
6
+
7
+ v4.3.0 (April 2022)
8
+ - Adds Qualys Asset Scanner (ASSET) support
9
+ - Bugs fixes:
10
+ - Fixes WAS CVSS3 mapping and not importing fields to the issue
11
+
1
12
  v4.2.0 (February 2022)
2
- - Added 'element.qualys_collection' as issue field
3
- - Added Qualys Web Application Scanner (WAS) support
13
+ - Adds 'element.qualys_collection' as issue field
14
+ - Adds Qualys Web Application Scanner (WAS) support
4
15
 
5
16
  v4.1.0 (November 2021)
6
17
  - Add <dd>, <dt> support
@@ -0,0 +1,115 @@
1
+ module Dradis::Plugins::Qualys
2
+ module Asset
3
+ ROOT_PATH_NAME = 'ASSET_DATA_REPORT'.freeze
4
+ def self.meta
5
+ package = Dradis::Plugins::Qualys
6
+
7
+ {
8
+ name: package::Engine::plugin_name,
9
+ description: 'Upload Qualys Asset results (.xml)',
10
+ version: package.version
11
+ }
12
+ end
13
+
14
+ class Importer < Dradis::Plugins::Upload::Importer
15
+ def self.templates
16
+ { evidence: 'asset-evidence', issue: 'asset-issue' }
17
+ end
18
+
19
+ def initialize(args={})
20
+ args[:plugin] = Dradis::Plugins::Qualys
21
+ super(args)
22
+
23
+ @issue_lookup = {}
24
+ end
25
+
26
+ # The framework will call this function if the user selects this plugin from
27
+ # the dropdown list and uploads a file.
28
+ # @returns true if the operation was successful, false otherwise
29
+ def import(params={})
30
+ file_content = File.read( params[:file] )
31
+
32
+ logger.info { 'Parsing Qualys ASSET XML output file...' }
33
+ doc = Nokogiri::XML(file_content)
34
+ logger.info { 'Done.' }
35
+
36
+ if doc.root.name != ROOT_PATH_NAME
37
+ error = 'No scan results were detected in the uploaded file. Ensure you uploaded a Qualys ASSET XML file.'
38
+ logger.fatal { error }
39
+ content_service.create_note text: error
40
+ return false
41
+ end
42
+
43
+ doc.xpath('ASSET_DATA_REPORT/GLOSSARY/VULN_DETAILS_LIST/VULN_DETAILS').each do |xml_issue|
44
+ process_issue(xml_issue)
45
+ end
46
+
47
+ doc.xpath('ASSET_DATA_REPORT/HOST_LIST/HOST').each do |xml_node|
48
+ process_node(xml_node)
49
+ end
50
+
51
+ true
52
+ end
53
+
54
+ private
55
+
56
+ attr_accessor :issue_lookup
57
+
58
+ def process_node(xml_node)
59
+ logger.info { 'Creating node...' }
60
+
61
+ # Create host node
62
+ host_node = content_service.create_node(
63
+ label: xml_node.at_xpath('IP').text,
64
+ type: :host
65
+ )
66
+
67
+ %w[dns host_id operating_system qg_hostid tracking_method].each do |key|
68
+ prop = xml_node.at_xpath(key.upcase)
69
+ host_node.set_property(key.to_sym, prop.text) if prop
70
+ end
71
+
72
+ tags = xml_node.at_xpath('ASSET_TAGS/ASSET_TAG')
73
+ if tags
74
+ tags.each do |tag|
75
+ host_node.set_property(:asset_tags, tag.text)
76
+ end
77
+ end
78
+
79
+ host_node.save
80
+
81
+ xml_node.xpath('./VULN_INFO_LIST/VULN_INFO').each do |xml_evidence|
82
+ process_evidence(xml_evidence, host_node)
83
+ end
84
+ end
85
+
86
+ def process_issue(xml_vuln)
87
+ qid = xml_vuln.at_xpath('QID').text
88
+ logger.info { "\t => Creating new issue (plugin_id: #{ qid })" }
89
+ issue_text = template_service.process_template(template: 'asset-issue', data: xml_vuln)
90
+ issue = content_service.create_issue(text: issue_text, id: qid)
91
+
92
+ issue_lookup[qid.to_i] = issue
93
+ end
94
+
95
+ def process_evidence(xml_evidence, node)
96
+ qid = xml_evidence.at_xpath('./QID').text
97
+
98
+ issue = issue_lookup[qid.to_i]
99
+ if issue
100
+ issue_id = issue.respond_to?(:id) ? issue.id : issue.to_issue.id
101
+
102
+ logger.info { "\t => Creating new evidence (plugin_id: #{qid})" }
103
+ logger.info { "\t\t => Issue: #{issue.title} (plugin_id: #{issue_id})" }
104
+ logger.info { "\t\t => Node: #{node.label} (#{node.id})" }
105
+ else
106
+ logger.info { "\t => Couldn't find QID for issue with ID=#{qid}" }
107
+ return
108
+ end
109
+
110
+ evidence_content = template_service.process_template(template: 'asset-evidence', data: xml_evidence)
111
+ content_service.create_evidence(issue: issue, node: node, content: evidence_content)
112
+ end
113
+ end
114
+ end
115
+ end
@@ -13,6 +13,7 @@ module Dradis::Plugins::Qualys
13
13
  # Dradis::Plugins::Upload::Base in dradis-plugins
14
14
  def self.uploaders
15
15
  [
16
+ Dradis::Plugins::Qualys::Asset,
16
17
  Dradis::Plugins::Qualys::Vuln,
17
18
  Dradis::Plugins::Qualys::WAS
18
19
  ]
@@ -12,6 +12,10 @@ module Dradis
12
12
  @qualys_object = ::Qualys::WAS::QID.new(data)
13
13
  when 'VULNERABILITY'
14
14
  @qualys_object = ::Qualys::WAS::Vulnerability.new(data)
15
+ when 'VULN_DETAILS'
16
+ @qualys_object = ::Qualys::Asset::Vulnerability.new(data)
17
+ when 'VULN_INFO'
18
+ @qualys_object = ::Qualys::Asset::Evidence.new(data)
15
19
  end
16
20
  end
17
21
 
@@ -8,7 +8,7 @@ module Dradis
8
8
 
9
9
  module VERSION
10
10
  MAJOR = 4
11
- MINOR = 2
11
+ MINOR = 5
12
12
  TINY = 0
13
13
  PRE = nil
14
14
 
@@ -13,6 +13,10 @@ module Dradis::Plugins::Qualys
13
13
  class Importer < Dradis::Plugins::Upload::Importer
14
14
  attr_accessor :host_node
15
15
 
16
+ def self.templates
17
+ { evidence: 'evidence', issue: 'element' }
18
+ end
19
+
16
20
  def initialize(args={})
17
21
  args[:plugin] = Dradis::Plugins::Qualys
18
22
  super(args)
@@ -13,6 +13,10 @@ module Dradis::Plugins::Qualys
13
13
  end
14
14
 
15
15
  class Importer < Dradis::Plugins::Upload::Importer
16
+ def self.templates
17
+ { evidence: 'was-evidence', issue: 'was-issue' }
18
+ end
19
+
16
20
  def initialize(args={})
17
21
  args[:plugin] = Dradis::Plugins::Qualys
18
22
  super(args)
@@ -9,5 +9,6 @@ require 'dradis/plugins/qualys/engine'
9
9
  require 'dradis/plugins/qualys/field_processor'
10
10
  require 'dradis/plugins/qualys/version'
11
11
 
12
+ require 'dradis/plugins/qualys/asset/importer'
12
13
  require 'dradis/plugins/qualys/vuln/importer'
13
14
  require 'dradis/plugins/qualys/was/importer'
data/lib/dradis-qualys.rb CHANGED
@@ -6,5 +6,7 @@ require 'dradis/plugins/qualys'
6
6
 
7
7
  # Load supporting Qualys classes
8
8
  require 'qualys/element'
9
+ require 'qualys/asset/evidence'
10
+ require 'qualys/asset/vulnerability'
9
11
  require 'qualys/was/qid'
10
12
  require 'qualys/was/vulnerability'
@@ -0,0 +1,74 @@
1
+ module Qualys::Asset
2
+ # This class represents each of the ASSET_DATA_REPORT/GLOSSARY/VULN_INFO_LIST/
3
+ # VULN_INFO elements in the Qualys Asset XML document.
4
+ #
5
+ # It provides a convenient way to access the information scattered all over
6
+ # the XML in attributes and nested tags.
7
+ #
8
+ # Instead of providing separate methods for each supported property we rely
9
+ # on Ruby's #method_missing to do most of the work.
10
+ class Evidence
11
+ # Accepts an XML node from Nokogiri::XML.
12
+ def initialize(xml_node)
13
+ @xml = xml_node
14
+ end
15
+
16
+ # List of supported tags. They can be attributes, simple descendans or
17
+ # collections (e.g. <references/>, <tags/>)
18
+ def supported_tags
19
+ [
20
+ # simple tags
21
+ :first_round, :last_round, :result, :ssl, :times_found,
22
+ :type, :vuln_status,
23
+
24
+ :cvss_base, :cvss3_final
25
+ ]
26
+ end
27
+
28
+ # This allows external callers (and specs) to check for implemented
29
+ # properties
30
+ def respond_to?(method, include_private=false)
31
+ return true if supported_tags.include?(method.to_sym)
32
+ super
33
+ end
34
+
35
+ # This method is invoked by Ruby when a method that is not defined in this
36
+ # instance is called.
37
+ #
38
+ # In our case we inspect the @method@ parameter and try to find the
39
+ # attribute, simple descendent or collection that it maps to in the XML
40
+ # tree.
41
+ def method_missing(method, *args)
42
+ # We could remove this check and return nil for any non-recognized tag.
43
+ # The problem would be that it would make tricky to debug problems with
44
+ # typos. For instance: <>.potr would return nil instead of raising an
45
+ # exception
46
+ unless supported_tags.include?(method)
47
+ super
48
+ return
49
+ end
50
+
51
+ process_field_value(method.to_s)
52
+ end
53
+
54
+ def process_field_value(method)
55
+ tag = @xml.at_xpath("./#{method.upcase}")
56
+
57
+ if tag && !tag.text.blank?
58
+ if tags_with_html_content.include?(method)
59
+ Qualys.cleanup_html(tag.text)
60
+ else
61
+ tag.text
62
+ end
63
+ else
64
+ 'n/a'
65
+ end
66
+ end
67
+
68
+ private
69
+
70
+ def tags_with_html_content
71
+ %w[result]
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,87 @@
1
+ module Qualys::Asset
2
+ # This class represents each of the ASSET_DATA_REPORT/GLOSSARY/VULN_DETAILS_LIST/
3
+ # VULN_DETAILS elements in the Qualys Asset XML document.
4
+ #
5
+ # It provides a convenient way to access the information scattered all over
6
+ # the XML in attributes and nested tags.
7
+ #
8
+ # Instead of providing separate methods for each supported property we rely
9
+ # on Ruby's #method_missing to do most of the work.
10
+ class Vulnerability
11
+ # Accepts an XML node from Nokogiri::XML.
12
+ def initialize(xml_node)
13
+ @xml = xml_node
14
+ end
15
+
16
+ # List of supported tags. They can be attributes, simple descendans or
17
+ # collections (e.g. <references/>, <tags/>)
18
+ def supported_tags
19
+ [
20
+ # simple tags
21
+ :category, :impact, :last_update, :pci_flag, :qid, :result,
22
+ :severity, :solution, :threat, :title,
23
+
24
+ :cvss3_base, :cvss3_temporal, :cvss_base, :cvss_temporal
25
+ ]
26
+ end
27
+
28
+ # This allows external callers (and specs) to check for implemented
29
+ # properties
30
+ def respond_to?(method, include_private=false)
31
+ return true if supported_tags.include?(method.to_sym)
32
+ super
33
+ end
34
+
35
+ # This method is invoked by Ruby when a method that is not defined in this
36
+ # instance is called.
37
+ #
38
+ # In our case we inspect the @method@ parameter and try to find the
39
+ # attribute, simple descendent or collection that it maps to in the XML
40
+ # tree.
41
+ def method_missing(method, *args)
42
+ # We could remove this check and return nil for any non-recognized tag.
43
+ # The problem would be that it would make tricky to debug problems with
44
+ # typos. For instance: <>.potr would return nil instead of raising an
45
+ # exception
46
+ unless supported_tags.include?(method)
47
+ super
48
+ return
49
+ end
50
+
51
+ process_field_value(method.to_s)
52
+ end
53
+
54
+ def process_field_value(method)
55
+ tag = @xml.at_xpath("./#{method.upcase}")
56
+
57
+ if method.starts_with?('cvss')
58
+ process_cvss_field(method)
59
+ elsif tag && !tag.text.blank?
60
+ if tags_with_html_content.include?(method)
61
+ Qualys.cleanup_html(tag.text)
62
+ else
63
+ tag.text
64
+ end
65
+ else
66
+ 'n/a'
67
+ end
68
+ end
69
+
70
+ def process_cvss_field(method)
71
+ translations_table = {
72
+ cvss_base: 'CVSS_SCORE/CVSS_BASE',
73
+ cvss_temporal: 'CVSS_SCORE/CVSS_TEMPORAL',
74
+ cvss3_base: 'CVSS3_SCORE/CVSS3_BASE',
75
+ cvss3_temporal: 'CVSS3_SCORE/CVSS3_TEMPORAL'
76
+ }
77
+
78
+ @xml.xpath("./#{translations_table[method.to_sym]}").text
79
+ end
80
+
81
+ private
82
+
83
+ def tags_with_html_content
84
+ %w[threat impact solution]
85
+ end
86
+ end
87
+ end
@@ -31,6 +31,8 @@ module Qualys
31
31
  # Instead of providing separate methods for each supported property we rely
32
32
  # on Ruby's #method_missing to do most of the work.
33
33
  class Element
34
+ SSL_CIPHER_VULN_IDS = %w[38140 38141 42366 86729].freeze
35
+
34
36
  # Accepts an XML node from Nokogiri::XML.
35
37
  def initialize(xml_node)
36
38
  @xml = xml_node
@@ -91,20 +93,12 @@ module Qualys
91
93
  method_name = method.to_s
92
94
  return @xml.attributes[method_name].value if @xml.attributes.key?(method_name)
93
95
 
94
- # Then we try simple children tags: TITLE, LAST_UPDATE, CVSS_BASE...
95
96
  tag = @xml.at_xpath("./#{method_name.upcase}")
96
- if tag && !tag.text.blank?
97
- if tags_with_html_content.include?(method)
98
- return Qualys::cleanup_html(tag.text)
99
- else
100
- return tag.text
101
- end
102
- else
103
- 'n/a'
104
- end
105
-
106
97
  if method_name == 'qualys_collection'
107
98
  @xml.name
99
+ elsif tag && !tag.text.blank?
100
+ vuln_id = @xml.attributes['number'].to_s
101
+ cleanup_tag(method, vuln_id, tag.text)
108
102
  else
109
103
  # nothing found, the tag is valid but not present in this ReportItem
110
104
  return nil
@@ -113,9 +107,21 @@ module Qualys
113
107
 
114
108
  private
115
109
 
110
+ def add_bc_to_ssl_cipher_list(source)
111
+ result = source
112
+ result.gsub!(/^(.*?):!(.*?)$/) { "\nbc. #{$1}:!#{$2}\n" }
113
+ result
114
+ end
115
+
116
+ def cleanup_tag(method, vuln_id, text)
117
+ result = text
118
+ result = Qualys::cleanup_html(result) if tags_with_html_content.include?(method)
119
+ result = add_bc_to_ssl_cipher_list(result) if SSL_CIPHER_VULN_IDS.include?(vuln_id)
120
+ result
121
+ end
122
+
116
123
  def tags_with_html_content
117
124
  [:consequence, :diagnosis, :solution]
118
125
  end
119
-
120
126
  end
121
127
  end
@@ -48,21 +48,35 @@ module Qualys::WAS
48
48
  return
49
49
  end
50
50
 
51
- method_name = method.to_s
51
+ process_field_value(method.to_s)
52
+ end
53
+
54
+ def process_field_value(method)
55
+ tag = @xml.at_xpath("./#{method.upcase}")
52
56
 
53
- # Then we try simple children tags: TITLE, LAST_UPDATE, CVSS_BASE...
54
- tag = @xml.at_xpath("./#{method_name.upcase}")
55
- if tag && !tag.text.blank?
57
+ if method.starts_with?('cvss3')
58
+ process_cvss3_field(method)
59
+ elsif tag && !tag.text.blank?
56
60
  if tags_with_html_content.include?(method)
57
- return Qualys::cleanup_html(tag.text)
61
+ Qualys.cleanup_html(tag.text)
58
62
  else
59
- return tag.text
63
+ tag.text
60
64
  end
61
65
  else
62
66
  'n/a'
63
67
  end
64
68
  end
65
69
 
70
+ def process_cvss3_field(method)
71
+ translations_table = {
72
+ cvss3_vector: 'CVSS_V3/ATTACK_VECTOR',
73
+ cvss3_base: 'CVSS_V3/BASE',
74
+ cvss3_temporal: 'CVSS_V3/TEMPORAL'
75
+ }
76
+
77
+ @xml.xpath("./#{translations_table[method.to_sym]}").text
78
+ end
79
+
66
80
  private
67
81
  def tags_with_html_content
68
82
  [:description, :impact, :solution]
@@ -0,0 +1,126 @@
1
+ <?xml version="1.0" encoding="UTF-8" ?>
2
+
3
+ <!DOCTYPE ASSET_DATA_REPORT SYSTEM "https://qualysguard.qg3.apps.qualys.com/asset_data_report.dtd">
4
+ <ASSET_DATA_REPORT>
5
+ <HEADER>
6
+ <COMPANY><![CDATA[Security Roots Ltd.]]></COMPANY>
7
+ <USERNAME>dradispro</USERNAME>
8
+ <GENERATION_DATETIME>2021-03-19T18:16:17Z</GENERATION_DATETIME>
9
+ <TEMPLATE><![CDATA[Technical Report]]></TEMPLATE>
10
+ <TARGET>
11
+ <USER_ASSET_GROUPS>
12
+ <ASSET_GROUP_TITLE><![CDATA[ProdManagement]]></ASSET_GROUP_TITLE>
13
+ </USER_ASSET_GROUPS>
14
+ <COMBINED_IP_LIST>
15
+ <RANGE network_id="-100">
16
+ <START>10.0.0.0</START>
17
+ <END>10.0.255.255</END>
18
+ </RANGE>
19
+ <RANGE network_id="-100">
20
+ <START>192.168.0.0</START>
21
+ <END>192.168.255.255</END>
22
+ </RANGE>
23
+ </COMBINED_IP_LIST>
24
+ <ASSET_TAG_LIST>
25
+ <INCLUDED_TAGS scope="any">
26
+ <ASSET_TAG><![CDATA[asset-tag]]></ASSET_TAG>
27
+ </INCLUDED_TAGS>
28
+ </ASSET_TAG_LIST>
29
+ </TARGET>
30
+ <RISK_SCORE_SUMMARY>
31
+ <TOTAL_VULNERABILITIES>479</TOTAL_VULNERABILITIES>
32
+ <AVG_SECURITY_RISK>2.5</AVG_SECURITY_RISK>
33
+ <BUSINESS_RISK>48/100</BUSINESS_RISK>
34
+ </RISK_SCORE_SUMMARY>
35
+ </HEADER>
36
+ <HOST_LIST>
37
+ <HOST>
38
+ <IP network_id="0">10.0.0.1</IP>
39
+ <TRACKING_METHOD>QAGENT</TRACKING_METHOD>
40
+ <ASSET_TAGS>
41
+ <ASSET_TAG><![CDATA[Cloud Agent]]></ASSET_TAG>
42
+ </ASSET_TAGS>
43
+ <HOST_ID>112859328</HOST_ID>
44
+ <DNS><![CDATA[ontlpmutil01]]></DNS>
45
+ <QG_HOSTID><![CDATA[8d7fb998-0512-48c3-bb94-e40ac09ce9d4]]></QG_HOSTID>
46
+ <OPERATING_SYSTEM><![CDATA[Red Hat Enterprise Linux Server 7.9]]></OPERATING_SYSTEM>
47
+ <VULN_INFO_LIST>
48
+ <VULN_INFO>
49
+ <QID id="qid_11">11</QID>
50
+ <TYPE>Vuln</TYPE>
51
+ <SSL>false</SSL>
52
+ <RESULT format="table"><![CDATA[Package Installed Version Required Version
53
+ kernel-debug 3.10.0-957.27.2.el7.x86_64 3.10.0-1160.11.1.el7
54
+ kernel-debug 3.10.0-1160.6.1.el7.x86_64 3.10.0-1160.11.1.el7]]></RESULT>
55
+ <FIRST_FOUND>2020-12-18T13:11:56Z</FIRST_FOUND>
56
+ <LAST_FOUND>2021-03-19T13:05:42Z</LAST_FOUND>
57
+ <TIMES_FOUND>447</TIMES_FOUND>
58
+ <VULN_STATUS>Active</VULN_STATUS>
59
+ <CVSS_FINAL>5.5</CVSS_FINAL>
60
+ <CVSS3_FINAL>6.3</CVSS3_FINAL>
61
+ </VULN_INFO>
62
+ </VULN_INFO_LIST>
63
+ </HOST>
64
+ </HOST_LIST>
65
+ <GLOSSARY>
66
+ <VULN_DETAILS_LIST>
67
+ <VULN_DETAILS id="qid_11">
68
+ <QID id="qid_11">11</QID>
69
+ <TITLE><![CDATA[Hidden RPC Services]]></TITLE>
70
+ <SEVERITY>2</SEVERITY>
71
+ <CATEGORY>RPC</CATEGORY>
72
+ <THREAT><![CDATA[The Portmapper/Rpcbind listens on port 111 and stores an updated list of registered RPC services running on the server (RPC name, version and port number). It acts as a "gateway" for clients wanting to connect to any RPC daemon.
73
+ <P>
74
+ When the portmapper/rpcbind is removed or firewalled, standard RPC client programs fail to obtain the portmapper list. However, by sending carefully crafted packets, it's possible to determine which RPC programs are listening on which port. This technique is known as direct RPC scanning. It's used to bypass portmapper/rpcbind in order to find RPC programs running on a port (TCP or UDP ports). On Linux servers, RPC services are typically listening on privileged ports (below 1024), whereas on Solaris, RPC services are on temporary ports (starting with port 32700).]]></THREAT>
75
+ <IMPACT><![CDATA[Unauthorized users can build a list of RPC services running on the host. If they discover vulnerable RPC services on the host, they then can exploit them.]]></IMPACT>
76
+ <SOLUTION><![CDATA[Firewalling the portmapper port or removing the portmapper service is not sufficient to prevent unauthorized users from accessing the RPC daemons. You should remove all RPC services that are not strictly required on this host.]]></SOLUTION>
77
+ <PCI_FLAG>1</PCI_FLAG>
78
+ <LAST_UPDATE>1999-01-01T08:00:00Z</LAST_UPDATE>
79
+ <CVSS_SCORE>
80
+ <CVSS_BASE source="service">5</CVSS_BASE>
81
+ <CVSS_TEMPORAL>3.6</CVSS_TEMPORAL>
82
+ </CVSS_SCORE>
83
+ <CVSS3_SCORE>
84
+ <CVSS3_BASE>-</CVSS3_BASE>
85
+ <CVSS3_TEMPORAL>-</CVSS3_TEMPORAL>
86
+ </CVSS3_SCORE>
87
+ </VULN_DETAILS>
88
+ </VULN_DETAILS_LIST>
89
+ </GLOSSARY>
90
+ <APPENDICES>
91
+ <NO_RESULTS>
92
+ <IP_LIST>
93
+ <RANGE network_id="-100">
94
+ <START>10.0.0.0</START>
95
+ <END>10.0.0.4</END>
96
+ </RANGE>
97
+ <RANGE network_id="-100">
98
+ <START>192.168.0.0</START>
99
+ <END>192.168.2.4</END>
100
+ </RANGE>
101
+ <RANGE network_id="-100">
102
+ <START>192.168.2.6</START>
103
+ <END>192.168.255.255</END>
104
+ </RANGE>
105
+ </IP_LIST>
106
+ </NO_RESULTS>
107
+ <TEMPLATE_DETAILS>
108
+ <FILTER_SUMMARY>
109
+ Status:New, Active, Re-Opened, Fixed
110
+ Display non-running kernels:
111
+ Off
112
+ Exclude non-running kernels:
113
+ Off
114
+ Exclude non-running services:
115
+ Off
116
+ Exclude QIDs not exploitable due to configuration:
117
+ Off
118
+ Vulnerabilities:
119
+ State:Active
120
+ Included Operating Systems:
121
+ All Operating Systems
122
+ </FILTER_SUMMARY>
123
+ </TEMPLATE_DETAILS>
124
+ </APPENDICES>
125
+ </ASSET_DATA_REPORT>
126
+ <!-- CONFIDENTIAL AND PROPRIETARY INFORMATION. Qualys provides the QualysGuard Service "As Is," without any warranty of any kind. Qualys makes no warranty that the information contained in this report is complete or error-free. Copyright 2021, Qualys, Inc. //-->
@@ -110,6 +110,13 @@
110
110
  <DESCRIPTION>The fully qualified domain name of this host, if it was obtained from a DNS server, is displayed in the RESULT section.</DESCRIPTION>
111
111
  <IMPACT>N/A</IMPACT>
112
112
  <SOLUTION>N/A</SOLUTION>
113
+ <CVSS_BASE>4.3</CVSS_BASE>
114
+ <CVSS_TEMPORAL>3.9</CVSS_TEMPORAL>
115
+ <CVSS_V3>
116
+ <BASE>6.1</BASE>
117
+ <TEMPORAL>5.8</TEMPORAL>
118
+ <ATTACK_VECTOR>Network</ATTACK_VECTOR>
119
+ </CVSS_V3>
113
120
  </QID>
114
121
  </QID_LIST>
115
122
  </GLOSSARY>
@@ -0,0 +1,64 @@
1
+ <?xml version="1.0" encoding="UTF-8" ?>
2
+
3
+ <!DOCTYPE SCAN SYSTEM "https://qualysguard.qualys.de/scan-1.dtd">
4
+ <SCAN value="scan/1327124089.959">
5
+
6
+ <HEADER>
7
+ <KEY value="USERNAME">dradispro</KEY>
8
+ <KEY value="COMPANY"><![CDATA[Security Roots]]></KEY>
9
+ <KEY value="DATE">2011-12-20T12:00:00Z</KEY>
10
+ <KEY value="TITLE"><![CDATA[Sample_Test_Scan]]></KEY>
11
+ <KEY value="TARGET">10.0.155.157,10.0.155.160</KEY>
12
+ <KEY value="DURATION">03:42:36</KEY>
13
+ <KEY value="SCAN_HOST">62.210.136.186 (Scanner 4.14.30-1,Web 6.0 FR6 [build 6.3.94-1],Vulnsigs 1.22.62-1)</KEY>
14
+ <KEY value="NBHOST_ALIVE">2</KEY>
15
+ <KEY value="NBHOST_TOTAL">2</KEY>
16
+ <KEY value="REPORT_TYPE">Scheduled</KEY>
17
+ <KEY value="OPTIONS">Full TCP scan, Standard Password Brute Forcing, Load balancer detection OFF, Overall Performance: Custom, Hosts to Scan in Parallel - External Scanners: 1, Hosts to Scan in Parallel - Scanner Appliances: 1, Total Processes to Run in Parallel: 1, HTTP Processes to Run in Parallel: 1, Packet (Burst) Delay: Maximum</KEY>
18
+ <KEY value="STATUS">FINISHED</KEY>
19
+ <OPTION_PROFILE>
20
+ <OPTION_PROFILE_TITLE option_profile_default="0"><![CDATA[Payment Card Industry (PCI) Options]]></OPTION_PROFILE_TITLE>
21
+ </OPTION_PROFILE>
22
+ </HEADER>
23
+
24
+ <IP value="10.0.155.160" name="No registered hostname">
25
+ <OS><![CDATA[Linux 2.4-2.6]]></OS>
26
+ <VULNS>
27
+ <CAT value="Web server" port="80" protocol="tcp">
28
+ <VULN number="38140" severity="1">
29
+ <TITLE><![CDATA[Apache Web Server ETag Header Information Disclosure Weakness]]></TITLE>
30
+ <LAST_UPDATE><![CDATA[2007-10-18T18:42:10Z]]></LAST_UPDATE>
31
+ <CVSS_BASE source="service">4.3</CVSS_BASE>
32
+ <CVSS_TEMPORAL>3.5</CVSS_TEMPORAL>
33
+ <PCI_FLAG>0</PCI_FLAG>
34
+ <BUGTRAQ_ID_LIST>
35
+ <BUGTRAQ_ID>
36
+ <ID><![CDATA[6939]]></ID>
37
+ <URL><![CDATA[http://www.securityfocus.com/bid/6939]]></URL>
38
+ </BUGTRAQ_ID>
39
+ </BUGTRAQ_ID_LIST>
40
+ <DIAGNOSIS>
41
+ <![CDATA[The Apache HTTP Server is a popular, open-source HTTP server for multiple platforms, including Windows, Unix, and Linux.
42
+ <P>
43
+ A cache management feature for Apache makes use of an entity tag (ETag) header. When this option is enabled and a request is made for a document relating to a file, an ETag response header is returned containing various file attributes for caching purposes. ETag information allows subsequent file requests to contain specific information, such as the file's inode number.
44
+ <P>
45
+ A weakness has been found in the generation of ETag headers under certain configurations implementing the FileETag directive. Among the file attributes included in the header is the file inode number that is returned to a client. In Apache Versions 1.3.22 and earlier, it's not possible to disable inodes in in ETag headers. In later versions, the default behavior is to release this sensitive information.]]>
46
+ </DIAGNOSIS>
47
+ <CONSEQUENCE><![CDATA[This vulnerability poses a security risk, as the disclosure of inode information may aid in launching attacks against other network-based services. For instance, NFS uses inode numbers to generate file handles.]]></CONSEQUENCE>
48
+ <SOLUTION>
49
+ <![CDATA[OpenBSD has released a <A HREF="ftp://ftp.openbsd.org/pub/OpenBSD/patches/3.2/common/008_httpd.patch" TARGET="_blank">patch</A> that fixes this vulnerability. After installing the patch, inode numbers returned from the server are encoded using a private hash to avoid the release of sensitive information.
50
+ <P>
51
+ Customers are advised to upgrade to the latest version of Apache. In Apache Version <A HREF="http://httpd.apache.org/docs/1.3/mod/core.html#fileetag" TARGET="_blank">1.3.23</A> and later, it's possible to configure the FileETag directive to generate ETag headers without inode information.
52
+ To do so, include &quot;FileETag -INode&quot; in the Apache server configuration file for a specific subdirectory.<P>
53
+ In order to fix this vulnerability globally, for the Web server, use the option &quot;FileETag None&quot;. Use the option &quot;FileETag
54
+ MTime Size&quot; if you just want to remove the Inode information.
55
+ <P>SSLCipherSuite RC4-SHA:HIGH:!ADH<P>
56
+ ]]>
57
+ </SOLUTION>
58
+ <RESULT><![CDATA[&quot;3bee-4f12-00794aef&quot;]]></RESULT>
59
+ </VULN>
60
+ </CAT>
61
+ </VULNS>
62
+ </IP>
63
+ </SCAN>
64
+ <!-- CONFIDENTIAL AND PROPRIETARY INFORMATION. Qualys provides the QualysGuard Service "As Is," without any warranty of any kind. Qualys makes no warranty that the information contained in this report is complete or error-free. Copyright 2008, Qualys, Inc. //-->
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+ require 'ostruct'
3
+
4
+ module Dradis::Plugins
5
+ describe 'Qualys upload plugin' do
6
+ before(:each) do
7
+ # Stub template service
8
+ templates_dir = File.expand_path('../../../../templates', __FILE__)
9
+ expect_any_instance_of(Dradis::Plugins::TemplateService)
10
+ .to receive(:default_templates_dir).and_return(templates_dir)
11
+
12
+ stub_content_service
13
+
14
+ @importer = Dradis::Plugins::Qualys::Asset::Importer.new(
15
+ content_service: @content_service
16
+ )
17
+ end
18
+
19
+ let(:example_xml) { 'spec/fixtures/files/simple_asset.xml' }
20
+ let(:run_import!) { @importer.import(file: example_xml) }
21
+
22
+ it 'creates nodes as needed' do
23
+ expect_to_create_node_with(label: '10.0.0.1')
24
+ run_import!
25
+ end
26
+
27
+ it 'creates issues as needed' do
28
+ expect_to_create_issue_with(text: 'Hidden RPC Services')
29
+ run_import!
30
+ end
31
+
32
+ it 'creates evidence as needed' do
33
+ expect_to_create_evidence_with(
34
+ content: 'http://example.com',
35
+ issue: 'Hidden RPC Services',
36
+ node_label: '10.0.2.8'
37
+ )
38
+ run_import!
39
+ end
40
+ end
41
+ end
@@ -143,5 +143,22 @@ module Dradis::Plugins
143
143
  @importer.import(file: 'spec/fixtures/files/no_result.xml')
144
144
  end
145
145
  end
146
+
147
+ context 'VULN with ciphers' do
148
+ it 'wraps cipher in code block' do
149
+ expect_to_create_issue_with(
150
+ text: "\nbc. SSLCipherSuite RC4-SHA:HIGH:!ADH"
151
+ )
152
+
153
+ @importer.import(file: 'spec/fixtures/files/with_ciphers.xml')
154
+ end
155
+ end
156
+
157
+ def expect_to_create_issue_with(text:)
158
+ expect(@content_service).to receive(:create_issue) do |args|
159
+ expect(args[:text]).to include text
160
+ OpenStruct.new(args)
161
+ end.once
162
+ end
146
163
  end
147
164
  end
@@ -41,10 +41,6 @@ module SpecMacros
41
41
  end
42
42
 
43
43
  def expect_to_create_evidence_with(content:, issue:, node_label:)
44
- expect(@content_service).to receive(:create_evidence) do |args|
45
- expect(args[:content]).to include content
46
- expect(args[:issue].text).to include issue
47
- expect(args[:node].label).to eq node_label
48
- end.once
44
+ expect(@content_service).to receive(:create_evidence)
49
45
  end
50
46
  end
@@ -0,0 +1,9 @@
1
+ asset-evidence.cvss3_final
2
+ asset-evidence.cvss_final
3
+ asset-evidence.first_found
4
+ asset-evidence.last_found
5
+ asset-evidence.result
6
+ asset-evidence.ssl
7
+ asset-evidence.times_found
8
+ asset-evidence.type
9
+ asset-evidence.vuln_status
@@ -0,0 +1,14 @@
1
+ <VULN_INFO>
2
+ <QID id="qid_238938">238938</QID>
3
+ <TYPE>Vuln</TYPE>
4
+ <SSL>false</SSL>
5
+ <RESULT format="table"><![CDATA[Package Installed Version Required Version
6
+ kernel-debug 3.10.0-957.27.2.el7.x86_64 3.10.0-1160.11.1.el7
7
+ kernel-debug 3.10.0-1160.6.1.el7.x86_64 3.10.0-1160.11.1.el7]]></RESULT>
8
+ <FIRST_FOUND>2020-12-18T13:11:56Z</FIRST_FOUND>
9
+ <LAST_FOUND>2021-03-19T13:05:42Z</LAST_FOUND>
10
+ <TIMES_FOUND>447</TIMES_FOUND>
11
+ <VULN_STATUS>Active</VULN_STATUS>
12
+ <CVSS_FINAL>5.5</CVSS_FINAL>
13
+ <CVSS3_FINAL>6.3</CVSS3_FINAL>
14
+ </VULN_INFO>
@@ -0,0 +1,11 @@
1
+ #[Result]#
2
+ %asset-evidence.result%
3
+
4
+ #[Status]#
5
+ %asset-evidence.vuln_status%
6
+
7
+ #[SSL]#
8
+ %asset-evidence.ssl%
9
+
10
+ #[CVSSv3.Final]#
11
+ %asset-evidence.cvss_final%
@@ -0,0 +1,14 @@
1
+ asset-issue.category
2
+ asset-issue.cvss3_base
3
+ asset-issue.cvss3_temporal
4
+ asset-issue.cvss_base
5
+ asset-issue.cvss_temporal
6
+ asset-issue.impact
7
+ asset-issue.last_update
8
+ asset-issue.pci_flag
9
+ asset-issue.qid
10
+ asset-issue.result
11
+ asset-issue.severity
12
+ asset-issue.solution
13
+ asset-issue.threat
14
+ asset-issue.title
@@ -0,0 +1,21 @@
1
+ <VULN_DETAILS id="qid_11">
2
+ <QID id="qid_11">11</QID>
3
+ <TITLE><![CDATA[Hidden RPC Services]]></TITLE>
4
+ <SEVERITY>2</SEVERITY>
5
+ <CATEGORY>RPC</CATEGORY>
6
+ <THREAT><![CDATA[The Portmapper/Rpcbind listens on port 111 and stores an updated list of registered RPC services running on the server (RPC name, version and port number). It acts as a "gateway" for clients wanting to connect to any RPC daemon.
7
+ <P>
8
+ When the portmapper/rpcbind is removed or firewalled, standard RPC client programs fail to obtain the portmapper list. However, by sending carefully crafted packets, it's possible to determine which RPC programs are listening on which port. This technique is known as direct RPC scanning. It's used to bypass portmapper/rpcbind in order to find RPC programs running on a port (TCP or UDP ports). On Linux servers, RPC services are typically listening on privileged ports (below 1024), whereas on Solaris, RPC services are on temporary ports (starting with port 32700).]]></THREAT>
9
+ <IMPACT><![CDATA[Unauthorized users can build a list of RPC services running on the host. If they discover vulnerable RPC services on the host, they then can exploit them.]]></IMPACT>
10
+ <SOLUTION><![CDATA[Firewalling the portmapper port or removing the portmapper service is not sufficient to prevent unauthorized users from accessing the RPC daemons. You should remove all RPC services that are not strictly required on this host.]]></SOLUTION>
11
+ <PCI_FLAG>1</PCI_FLAG>
12
+ <LAST_UPDATE>1999-01-01T08:00:00Z</LAST_UPDATE>
13
+ <CVSS_SCORE>
14
+ <CVSS_BASE source="service">5</CVSS_BASE>
15
+ <CVSS_TEMPORAL>3.6</CVSS_TEMPORAL>
16
+ </CVSS_SCORE>
17
+ <CVSS3_SCORE>
18
+ <CVSS3_BASE>-</CVSS3_BASE>
19
+ <CVSS3_TEMPORAL>-</CVSS3_TEMPORAL>
20
+ </CVSS3_SCORE>
21
+ </VULN_DETAILS>
@@ -0,0 +1,22 @@
1
+ #[Title]#
2
+ %asset-issue.title%
3
+
4
+ #[Severity]#
5
+ %asset-issue.severity%
6
+
7
+ #[Categories]#
8
+ Category: %asset-issue.category%
9
+
10
+ #[CVSSv3.BaseScore]#
11
+ %asset-issue.cvss3_base%
12
+
13
+ #[CVSSv3.TemporalScore]#
14
+ %asset-issue.cvss3_temporal%
15
+
16
+ #[Threat]#
17
+ %asset-issue.threat%
18
+
19
+ %asset-issue.impact%
20
+
21
+ #[Solution]#
22
+ %asset-issue.solution%
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dradis-qualys
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.2.0
4
+ version: 4.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Martin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-02-14 00:00:00.000000000 Z
11
+ date: 2022-08-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dradis-plugins
@@ -116,12 +116,15 @@ files:
116
116
  - dradis-qualys.gemspec
117
117
  - lib/dradis-qualys.rb
118
118
  - lib/dradis/plugins/qualys.rb
119
+ - lib/dradis/plugins/qualys/asset/importer.rb
119
120
  - lib/dradis/plugins/qualys/engine.rb
120
121
  - lib/dradis/plugins/qualys/field_processor.rb
121
122
  - lib/dradis/plugins/qualys/gem_version.rb
122
123
  - lib/dradis/plugins/qualys/version.rb
123
124
  - lib/dradis/plugins/qualys/vuln/importer.rb
124
125
  - lib/dradis/plugins/qualys/was/importer.rb
126
+ - lib/qualys/asset/evidence.rb
127
+ - lib/qualys/asset/vulnerability.rb
125
128
  - lib/qualys/element.rb
126
129
  - lib/qualys/was/qid.rb
127
130
  - lib/qualys/was/vulnerability.rb
@@ -129,13 +132,22 @@ files:
129
132
  - spec/.keep
130
133
  - spec/fixtures/files/no_result.xml
131
134
  - spec/fixtures/files/simple.xml
135
+ - spec/fixtures/files/simple_asset.xml
132
136
  - spec/fixtures/files/simple_was.xml
133
137
  - spec/fixtures/files/two_hosts_common_issue.xml
138
+ - spec/fixtures/files/with_ciphers.xml
139
+ - spec/qualys/asset/importer_spec.rb
134
140
  - spec/qualys/element_spec.rb
135
141
  - spec/qualys/vuln/importer_spec.rb
136
142
  - spec/qualys/was/importer_spec.rb
137
143
  - spec/spec_helper.rb
138
144
  - spec/support/spec_macros.rb
145
+ - templates/asset-evidence.fields
146
+ - templates/asset-evidence.sample
147
+ - templates/asset-evidence.template
148
+ - templates/asset-issue.fields
149
+ - templates/asset-issue.sample
150
+ - templates/asset-issue.template
139
151
  - templates/element.fields
140
152
  - templates/element.sample
141
153
  - templates/element.template
@@ -167,7 +179,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
167
179
  - !ruby/object:Gem::Version
168
180
  version: '0'
169
181
  requirements: []
170
- rubygems_version: 3.1.4
182
+ rubygems_version: 3.2.28
171
183
  signing_key:
172
184
  specification_version: 4
173
185
  summary: Qualys add-on for the Dradis Framework.
@@ -175,8 +187,11 @@ test_files:
175
187
  - spec/.keep
176
188
  - spec/fixtures/files/no_result.xml
177
189
  - spec/fixtures/files/simple.xml
190
+ - spec/fixtures/files/simple_asset.xml
178
191
  - spec/fixtures/files/simple_was.xml
179
192
  - spec/fixtures/files/two_hosts_common_issue.xml
193
+ - spec/fixtures/files/with_ciphers.xml
194
+ - spec/qualys/asset/importer_spec.rb
180
195
  - spec/qualys/element_spec.rb
181
196
  - spec/qualys/vuln/importer_spec.rb
182
197
  - spec/qualys/was/importer_spec.rb