dradis-acunetix 4.12.0 → 4.14.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: f524ed0cb7e422e55d6a417c7f44ffcc75062ad8fd270c3974b5d4df36296cb7
4
- data.tar.gz: 3c76fdd522b2471213d32b88e5fe83675b22fd5cf542f3b560cf589169656fac
3
+ metadata.gz: 70ada77a2b5ccc95dea1ee7de02fb8ff3dc64b53b4083cd6a6bbc5ef0ef2436a
4
+ data.tar.gz: ea41c007052e86cc1911e6c14869207bf8826b2498088fcd2f0a9d884dbd3972
5
5
  SHA512:
6
- metadata.gz: 1cd647ad42044b3e6eaed0bdd803cbac50e64f82d2bff5d8849b631409e64a41d4f280a4ee045286b5618e6bf587d8860786e65eb8dcb8e1f72e8b835c739b4b
7
- data.tar.gz: b6d4cf1be6d5fd42cad884af20b045551c2390f6c18bae467aaecfd03e289e49c29c903e5440c8ca495c87cce6e6d6839c93e92a6d110ad173dcbb7984edd192
6
+ metadata.gz: b440d35fc20eee027b5cc8c959ba16e7d646d725c1e6db537740b2b8c2b24c20671a136b31d66f9b632f976d98ea514b5d4b8ffbb8c18723a8579645bf712e1d
7
+ data.tar.gz: abb9e364750381d45c33ba282cd47811c05a4e4fb51a7f9d89d348fc9f48d6cd55ff1712fac2673865139c5b8ec9a5dcebefbd3b57e1d623622ac862869aeda9
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ v4.14.0 (October 2024)
2
+ - Separate general importer into Acunetix360 & Standard importers
3
+
4
+ v4.13.0 (July 2024)
5
+ - No changes
6
+
1
7
  v4.12.0 (May 2024)
2
8
  - Migrate integration to use Mappings Manager
3
9
  - Update Dradis links in README
@@ -26,7 +26,7 @@ Gem::Specification.new do |spec|
26
26
  spec.add_dependency 'dradis-plugins', '~> 4.0'
27
27
  spec.add_dependency 'nokogiri', '~> 1.3'
28
28
 
29
- spec.add_development_dependency 'bundler', '~> 1.6'
29
+ spec.add_development_dependency 'bundler', '~> 2'
30
30
  spec.add_development_dependency 'rake', '~> 10.0'
31
31
  spec.add_development_dependency 'rspec-rails'
32
32
  spec.add_development_dependency 'combustion', '~> 0.5.2'
@@ -0,0 +1,95 @@
1
+ module Dradis::Plugins::Acunetix
2
+ module Acunetix360
3
+ def self.meta
4
+ package = Dradis::Plugins::Acunetix
5
+ {
6
+ name: package::Engine::plugin_name,
7
+ description: 'Upload Acunetix360 output file (.xml)',
8
+ version: package.version
9
+ }
10
+ end
11
+
12
+ class Importer < Dradis::Plugins::Upload::Importer
13
+ attr_accessor :scan_node, :xml
14
+
15
+ def self.templates
16
+ { evidence: 'evidence_360', issue: 'vulnerability_360' }
17
+ end
18
+
19
+ def initialize(args = {})
20
+ args[:plugin] = Dradis::Plugins::Acunetix
21
+ super(args)
22
+ end
23
+
24
+ # The framework will call this function if the user selects this plugin from
25
+ # the dropdown list and uploads a file.
26
+ # @returns true if the operation was successful, false otherwise
27
+ def import(params = {})
28
+ file_content = File.read(params.fetch(:file))
29
+
30
+ logger.info { 'Parsing Acunetix360 output file...' }
31
+ @xml = Nokogiri::XML( file_content )
32
+ logger.info { 'Done.' }
33
+
34
+ unless xml.xpath('//acunetix-360').present?
35
+ error = 'No Acunetix360 results were detected in the uploaded file. Ensure you uploaded an Acunetix360 XML report.'
36
+ logger.fatal { error }
37
+ content_service.create_note text: error
38
+ return false
39
+ end
40
+
41
+ process_acunetix360
42
+
43
+ logger.info { 'Acunetix360 file successfully imported' }
44
+ true
45
+ end
46
+
47
+ private
48
+
49
+ def process_acunetix360
50
+ process_target_node
51
+ process_acunetix360_vulnerabilities
52
+ end
53
+
54
+ def process_target_node
55
+ target_xml = xml.at_xpath('//acunetix-360/target')
56
+ @scan_node = content_service.create_node(
57
+ label: target_xml.at_xpath('url').text,
58
+ type: :host
59
+ )
60
+
61
+ logger.info { "Creating target node: #{scan_node.label}" }
62
+
63
+ if scan_node.respond_to?(:properties)
64
+ scan_node.set_property(:scan_id, target_xml.at_xpath('scan-id').text)
65
+ scan_node.set_property(:initiated, target_xml.at_xpath('initiated').text)
66
+ scan_node.set_property(:duration, target_xml.at_xpath('duration').text)
67
+ end
68
+ end
69
+
70
+ def process_acunetix360_vulnerabilities
71
+ logger.info { 'Creating issues from Acunetix360 vulnerabilities.' }
72
+
73
+ xml.xpath('//acunetix-360/vulnerabilities/vulnerability').each do |vuln_xml|
74
+ issue_text = mapping_service.apply_mapping(
75
+ source: 'vulnerability_360',
76
+ data: vuln_xml
77
+ )
78
+
79
+ type = vuln_xml.at_xpath('type').text
80
+
81
+ logger.info { "\t\t => Creating new issue: #{type}" }
82
+ issue = content_service.create_issue(text: issue_text, id: type)
83
+
84
+ evidence_text = mapping_service.apply_mapping(
85
+ source: 'evidence_360',
86
+ data: vuln_xml
87
+ )
88
+
89
+ logger.info { "\t\t => Creating new evidence" }
90
+ content_service.create_evidence(issue: issue, node: scan_node, content: evidence_text)
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -5,5 +5,17 @@ module Dradis::Plugins::Acunetix
5
5
  include ::Dradis::Plugins::Base
6
6
  description 'Processes Acunetix XML format'
7
7
  provides :upload
8
+
9
+ # Because this plugin provides two export modules, we have to overwrite
10
+ # the default .uploaders() method.
11
+ #
12
+ # See:
13
+ # Dradis::Plugins::Upload::Base in dradis-plugins
14
+ def self.uploaders
15
+ [
16
+ Dradis::Plugins::Acunetix::Standard,
17
+ Dradis::Plugins::Acunetix::Acunetix360
18
+ ]
19
+ end
8
20
  end
9
21
  end
@@ -8,7 +8,7 @@ module Dradis
8
8
 
9
9
  module VERSION
10
10
  MAJOR = 4
11
- MINOR = 12
11
+ MINOR = 14
12
12
  TINY = 0
13
13
  PRE = nil
14
14
 
@@ -73,81 +73,81 @@ module Dradis::Plugins::Acunetix
73
73
  'evidence_360.http_response_duration'
74
74
  ],
75
75
  evidence: [
76
- 'evidence.details',
77
76
  'evidence.affects',
78
- 'evidence.parameter',
77
+ 'evidence.aop_additional',
79
78
  'evidence.aop_source_file',
80
79
  'evidence.aop_source_line',
81
- 'evidence.aop_additional',
80
+ 'evidence.details',
82
81
  'evidence.is_false_positive',
82
+ 'evidence.parameter',
83
83
  'evidence.request',
84
84
  'evidence.response'
85
85
  ],
86
86
  report_item: [
87
- 'report_item.name',
88
- 'report_item.module_name',
89
- 'report_item.severity',
90
- 'report_item.type',
91
- 'report_item.impact',
92
- 'report_item.description',
93
- 'report_item.detailed_information',
94
- 'report_item.recommendation',
95
- 'report_item.request',
96
- 'report_item.response',
87
+ 'report_item.cve_list',
97
88
  'report_item.cvss_descriptor',
98
89
  'report_item.cvss_score',
99
90
  'report_item.cvss3_descriptor',
100
91
  'report_item.cvss3_score',
101
92
  'report_item.cvss3_tempscore',
102
93
  'report_item.cvss3_envscore',
103
- 'report_item.cve_list',
104
- 'report_item.references'
94
+ 'report_item.description',
95
+ 'report_item.detailed_information',
96
+ 'report_item.impact',
97
+ 'report_item.module_name',
98
+ 'report_item.name',
99
+ 'report_item.recommendation',
100
+ 'report_item.references',
101
+ 'report_item.request',
102
+ 'report_item.response',
103
+ 'report_item.severity',
104
+ 'report_item.type'
105
105
  ],
106
106
  scan: [
107
- 'scan.name',
108
- 'scan.short_name',
109
- 'scan.start_url',
110
- 'scan.start_time',
111
- 'scan.finish_time',
112
- 'scan.scan_time',
113
107
  'scan.aborted',
114
- 'scan.responsive',
115
108
  'scan.banner',
109
+ 'scan.name',
116
110
  'scan.os',
117
- 'scan.web_server',
118
- 'scan.technologies'
111
+ 'scan.finish_time',
112
+ 'scan.responsive',
113
+ 'scan.scan_time',
114
+ 'scan.short_name',
115
+ 'scan.start_time',
116
+ 'scan.start_url',
117
+ 'scan.technologies',
118
+ 'scan.web_server'
119
119
  ],
120
120
  vulnerability_360: [
121
- 'vulnerability_360.name',
122
- 'vulnerability_360.type',
123
- 'vulnerability_360.url',
121
+ 'vulnerability_360.capec',
122
+ 'vulnerability_360.certainty',
123
+ 'vulnerability_360.confirmed',
124
+ 'vulnerability_360.cvss_base',
125
+ 'vulnerability_360.cvss_environmental',
126
+ 'vulnerability_360.cvss_temporal',
127
+ 'vulnerability_360.cvss_vector',
128
+ 'vulnerability_360.cvss31_base',
129
+ 'vulnerability_360.cvss31_environmental',
130
+ 'vulnerability_360.cvss31_temporal',
131
+ 'vulnerability_360.cvss31_vector',
132
+ 'vulnerability_360.cwe',
124
133
  'vulnerability_360.description',
134
+ 'vulnerability_360.exploitation_skills',
135
+ 'vulnerability_360.external_references',
136
+ 'vulnerability_360.hipaa',
125
137
  'vulnerability_360.impact',
138
+ 'vulnerability_360.iso27001',
139
+ 'vulnerability_360.name',
140
+ 'vulnerability_360.owasp',
141
+ 'vulnerability_360.owasppc',
142
+ 'vulnerability_360.pci32',
126
143
  'vulnerability_360.remedial_actions',
127
- 'vulnerability_360.exploitation_skills',
128
144
  'vulnerability_360.remedial_procedure',
129
145
  'vulnerability_360.remedy_references',
130
- 'vulnerability_360.external_references',
131
146
  'vulnerability_360.severity',
132
- 'vulnerability_360.certainty',
133
- 'vulnerability_360.confirmed',
134
147
  'vulnerability_360.state',
135
- 'vulnerability_360.owasp',
148
+ 'vulnerability_360.type',
149
+ 'vulnerability_360.url',
136
150
  'vulnerability_360.wasc',
137
- 'vulnerability_360.cwe',
138
- 'vulnerability_360.capec',
139
- 'vulnerability_360.pci32',
140
- 'vulnerability_360.hipaa',
141
- 'vulnerability_360.owasppc',
142
- 'vulnerability_360.iso27001',
143
- 'vulnerability_360.cvss_vector',
144
- 'vulnerability_360.cvss_base',
145
- 'vulnerability_360.cvss_temporal',
146
- 'vulnerability_360.cvss_environmental',
147
- 'vulnerability_360.cvss31_vector',
148
- 'vulnerability_360.cvss31_base',
149
- 'vulnerability_360.cvss31_temporal',
150
- 'vulnerability_360.cvss31_environmental'
151
151
  ]
152
152
  }.freeze
153
153
  end
@@ -0,0 +1,102 @@
1
+ module Dradis::Plugins::Acunetix
2
+ module Standard
3
+ def self.meta
4
+ package = Dradis::Plugins::Acunetix
5
+ {
6
+ name: package::Engine::plugin_name,
7
+ description: 'Upload Standard Acunetix output file (.xml)',
8
+ version: package.version
9
+ }
10
+ end
11
+
12
+ class Importer < Dradis::Plugins::Upload::Importer
13
+ attr_accessor :scan_node, :xml
14
+
15
+ def self.templates
16
+ { evidence: 'evidence', issue: 'report_item' }
17
+ end
18
+
19
+ def initialize(args = {})
20
+ args[:plugin] = Dradis::Plugins::Acunetix
21
+ super(args)
22
+ end
23
+
24
+ # The framework will call this function if the user selects this plugin from
25
+ # the dropdown list and uploads a file.
26
+ # @returns true if the operation was successful, false otherwise
27
+ def import(params = {})
28
+ file_content = File.read(params.fetch(:file))
29
+
30
+ logger.info { 'Parsing Standard Acunetix output file...' }
31
+ @xml = Nokogiri::XML(file_content)
32
+ logger.info { 'Done.' }
33
+
34
+ unless xml.xpath('/ScanGroup/Scan').present?
35
+ error = 'No scan results were detected in the uploaded file (/ScanGroup/Scan). Ensure you uploaded an Acunetix XML report.'
36
+ logger.fatal { error }
37
+ content_service.create_note text: error
38
+ return false
39
+ end
40
+
41
+ process_standard
42
+
43
+ logger.info { 'Standard Acunetix file successfully imported' }
44
+ true
45
+ end
46
+
47
+ private
48
+
49
+ def process_standard
50
+ xml.xpath('/ScanGroup/Scan').each do |xml_scan|
51
+ process_scan(xml_scan)
52
+ end
53
+ end
54
+
55
+ def process_scan(xml_scan)
56
+ url = xml_scan.at_xpath('./StartURL').text()
57
+ start_url = URI::parse(url).host || url # urls wo/ protocol returned nil
58
+
59
+ self.scan_node = content_service.create_node(label: start_url, type: :host)
60
+ logger.info{ "\tScan start URL: #{start_url}" }
61
+
62
+ # Define Node properties
63
+ if scan_node.respond_to?(:properties)
64
+ scan_node.set_property(:short_name, xml_scan.at_xpath('./ShortName').text() )
65
+ scan_node.set_property(:start_url, start_url)
66
+ scan_node.set_property(:start_time, xml_scan.at_xpath('./StartTime').text() )
67
+ scan_node.set_property(:finish_time, xml_scan.at_xpath('./FinishTime').text() )
68
+ scan_node.set_property(:scan_time, xml_scan.at_xpath('./ScanTime').text() )
69
+ scan_node.set_property(:aborted, xml_scan.at_xpath('./Aborted').text() )
70
+ scan_node.set_property(:responsive, xml_scan.at_xpath('./Responsive').text() )
71
+ scan_node.set_property(:banner, xml_scan.at_xpath('./Banner').text() )
72
+ scan_node.set_property(:os, xml_scan.at_xpath('./Os').text() )
73
+ scan_node.set_property(:web_server, xml_scan.at_xpath('./WebServer').text() )
74
+ scan_node.set_property(:technologies, xml_scan.at_xpath('./Technologies').text() )
75
+ scan_node.save
76
+ end
77
+
78
+ scan_note = mapping_service.apply_mapping(source: 'scan', data: xml_scan)
79
+ content_service.create_note text: scan_note, node: scan_node
80
+
81
+ xml_scan.xpath('./ReportItems/ReportItem').each do |xml_report_item|
82
+ process_report_item(xml_report_item)
83
+ end
84
+ end
85
+
86
+ def process_report_item(xml_report_item)
87
+ plugin_id = "%s/%s" % [
88
+ xml_report_item.at_xpath('./ModuleName').text(),
89
+ xml_report_item.at_xpath('./Name').text()
90
+ ]
91
+ logger.info { "\t\t => Creating new issue (plugin_id: #{plugin_id})" }
92
+
93
+ issue_text = mapping_service.apply_mapping(source: 'report_item', data: xml_report_item)
94
+ issue = content_service.create_issue(text: issue_text, id: plugin_id)
95
+
96
+ logger.info { "\t\t => Creating new evidence" }
97
+ evidence_content = mapping_service.apply_mapping(source: 'evidence', data: xml_report_item)
98
+ content_service.create_evidence(issue: issue, node: scan_node, content: evidence_content)
99
+ end
100
+ end
101
+ end
102
+ end
@@ -5,9 +5,10 @@ module Dradis
5
5
  end
6
6
  end
7
7
 
8
+ require 'dradis/plugins/acunetix/acunetix360/importer'
8
9
  require 'dradis/plugins/acunetix/engine'
9
10
  require 'dradis/plugins/acunetix/field_processor'
10
- require 'dradis/plugins/acunetix/importer'
11
11
  require 'dradis/plugins/acunetix/mapping'
12
+ require 'dradis/plugins/acunetix/standard/importer'
12
13
  require 'dradis/plugins/acunetix/version'
13
14
 
@@ -1,10 +1,27 @@
1
1
  class AcunetixTasks < Thor
2
2
  include Rails.application.config.dradis.thor_helper_module
3
-
4
- namespace "dradis:plugins:acunetix"
5
3
 
6
- desc "upload FILE", "upload Acunetix XML results"
7
- def upload(file_path)
4
+ namespace 'dradis:plugins:acunetix:upload'
5
+
6
+ desc 'standard FILE', 'upload Standard Acunetix XML results'
7
+ def standard(file_path)
8
+ detect_and_set_project_scope
9
+ importer = Dradis::Plugins::Acunetix::Standard::Importer.new(task_options)
10
+
11
+ process_upload(importer, file_path)
12
+ end
13
+
14
+ desc 'acunetix_360 FILE', 'upload Acunetix360 XML results'
15
+ def acunetix_360(file_path)
16
+ detect_and_set_project_scope
17
+ importer = Dradis::Plugins::Acunetix::Acunetix360::Importer.new(task_options)
18
+
19
+ process_upload(importer, file_path)
20
+ end
21
+
22
+ private
23
+
24
+ def process_upload(importer, file_path)
8
25
  require 'config/environment'
9
26
 
10
27
  unless File.exists?(file_path)
@@ -12,9 +29,6 @@ class AcunetixTasks < Thor
12
29
  exit -1
13
30
  end
14
31
 
15
- detect_and_set_project_scope
16
- importer = Dradis::Plugins::Acunetix::Importer.new(task_options)
17
32
  importer.import(file: file_path)
18
33
  end
19
-
20
34
  end
@@ -0,0 +1,61 @@
1
+ # To run, execute from Dradis main app folder:
2
+ # bin/rspec [dradis-acunetix path]/spec/acunetix/acunetix360/importer_spec.rb
3
+ require 'rails_helper'
4
+ require 'ostruct'
5
+ require File.expand_path('../../../../../dradis-plugins/spec/support/spec_macros.rb', __FILE__)
6
+
7
+ include Dradis::Plugins::SpecMacros
8
+
9
+ module Dradis::Plugins
10
+ describe Acunetix::Acunetix360::Importer do
11
+ before do
12
+ @fixtures_dir = File.expand_path('../../../fixtures/files/', __FILE__)
13
+ end
14
+
15
+ before(:each) do
16
+ stub_content_service
17
+
18
+ @importer = described_class.new(content_service: @content_service)
19
+ end
20
+
21
+ def run_import!
22
+ @importer.import(file: @fixtures_dir + '/acunetix360.xml')
23
+ end
24
+
25
+ it 'creates nodes as needed' do
26
+ expect(@content_service).to receive(:create_node).with(hash_including label: 'http://aspnet.testsparker.com/', type: :host).once
27
+
28
+ run_import!
29
+ end
30
+
31
+ it 'creates issues from vulnerability elements' do
32
+ expect(@content_service).to receive(:create_issue) do |args|
33
+ expect(args[:text]).to include("#[Title]#\nBlind SQL Injection")
34
+ expect(args[:id]).to eq('ConfirmedBlindSqlInjection')
35
+ end.once
36
+
37
+ expect(@content_service).to receive(:create_issue) do |args|
38
+ expect(args[:text]).to include("#[Title]#\nCross-site Scripting")
39
+ expect(args[:id]).to eq('Xss')
40
+ end.once
41
+
42
+ run_import!
43
+ end
44
+
45
+ it 'creates evidence from vulnerability elements' do
46
+ expect(@content_service).to receive(:create_evidence) do |args|
47
+ expect(args[:content]).to include('POST /blog/%27))%20WAITFOR%20DELAY%20%270%3a0%3a25%27')
48
+ expect(args[:issue].id).to eq('ConfirmedBlindSqlInjection')
49
+ expect(args[:node].label).to eq('http://aspnet.testsparker.com/')
50
+ end.once
51
+
52
+ expect(@content_service).to receive(:create_evidence) do |args|
53
+ expect(args[:content]).to include('GET /About.aspx HTTP/1.1')
54
+ expect(args[:issue].id).to eq('Xss')
55
+ expect(args[:node].label).to eq('http://aspnet.testsparker.com/')
56
+ end
57
+
58
+ run_import!
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,100 @@
1
+ # To run, execute from Dradis main app folder:
2
+ # bin/rspec [dradis-acunetix path]/spec/acunetix/standard/importer_spec.rb
3
+ require 'rails_helper'
4
+ require 'ostruct'
5
+ require File.expand_path('../../../../../dradis-plugins/spec/support/spec_macros.rb', __FILE__)
6
+
7
+ include Dradis::Plugins::SpecMacros
8
+
9
+ module Dradis::Plugins
10
+ describe Acunetix::Standard::Importer do
11
+ before do
12
+ @fixtures_dir = File.expand_path('../../../fixtures/files/', __FILE__)
13
+ end
14
+
15
+ before(:each) do
16
+ stub_content_service
17
+
18
+ @importer = described_class.new(content_service: @content_service)
19
+ end
20
+
21
+ def run_import!
22
+ @importer.import(file: @fixtures_dir + '/simple.acunetix.xml')
23
+ end
24
+
25
+ it 'creates nodes as needed' do
26
+ expect(@content_service).to receive(:create_node).with(hash_including label: 'testphp.vulnweb.com', type: :host).once
27
+
28
+ run_import!
29
+ end
30
+
31
+ it 'creates notes as needed' do
32
+ expect(@content_service).to receive(:create_note) do |args|
33
+ expect(args[:text]).to include('Scan Thread 1')
34
+ expect(args[:node].label).to eq('testphp.vulnweb.com')
35
+ end.once
36
+
37
+ run_import!
38
+ end
39
+
40
+ it 'creates issues from report_item elements' do
41
+ expect(@content_service).to receive(:create_issue) do |args|
42
+ expect(args[:text]).to include('HTML form without CSRF protection')
43
+ expect(args[:id]).to eq('Crawler/HTML form without CSRF protection')
44
+ end.once
45
+
46
+ expect(@content_service).to receive(:create_issue) do |args|
47
+ expect(args[:text]).to include('Clickjacking: X-Frame-Options header missing')
48
+ expect(args[:id]).to eq('Scripting (Clickjacking_X_Frame_Options.script)/Clickjacking: X-Frame-Options header missing')
49
+ end.once
50
+
51
+ run_import!
52
+ end
53
+
54
+ it 'creates evidence from report_item elements' do
55
+ expect(@content_service).to receive(:create_evidence) do |args|
56
+ expect(args[:content]).to include('Form name:')
57
+ expect(args[:issue].id).to eq('Crawler/HTML form without CSRF protection')
58
+ expect(args[:node].label).to eq('testphp.vulnweb.com')
59
+ end.once
60
+
61
+ expect(@content_service).to receive(:create_evidence) do |args|
62
+ expect(args[:content]).to include('Web Server')
63
+ expect(args[:issue].id).to eq('Scripting (Clickjacking_X_Frame_Options.script)/Clickjacking: X-Frame-Options header missing')
64
+ expect(args[:node].label).to eq('testphp.vulnweb.com')
65
+ end
66
+
67
+ run_import!
68
+ end
69
+
70
+ describe 'Regression tests' do
71
+ # Regression test for github.com/dradis/dradis-nexpose/issues/1
72
+ describe 'Source HTML parsing' do
73
+ it 'identifies code/pre blocks and replaces them with the Textile equivalent' do
74
+
75
+ expect(@content_service).to receive(:create_issue) do |args|
76
+ expect(args[:text]).to include('SQL injection (verified)')
77
+ expect(args[:text]).not_to include('<code>')
78
+ expect(args[:text]).not_to include('<pre')
79
+ expect(args[:id]).to eq('Scripting (Sql_Injection.script)/SQL injection (verified)')
80
+ end.once
81
+
82
+ @importer.import(file: @fixtures_dir + '/code-pre.acunetix.xml')
83
+ end
84
+ end
85
+
86
+ # Regression test to make sure that commas are replaced with decimals in the CVSSv3 scores
87
+ describe 'CVSS clean up decimals' do
88
+ it 'identifies commas used as decimals in CVSSv3 scores and replaces them with periods' do
89
+
90
+ expect(@content_service).to receive(:create_issue) do |args|
91
+ expect(args[:text]).to include('5.3')
92
+ end
93
+
94
+ @importer.import(file: @fixtures_dir + '/commas-format.acunetix.xml')
95
+ end
96
+ end
97
+
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,280 @@
1
+ <?xml version="1.0" encoding="utf-8" ?>
2
+ <acunetix-360 generated="16/06/2020 10:42 AM">
3
+ <target>
4
+ <scan-id>1234</scan-id>
5
+ <url>http://aspnet.testsparker.com/</url>
6
+ <initiated>16/06/2020 09:47 AM</initiated>
7
+ <duration>00:51:11.4005587</duration>
8
+ </target>
9
+ <vulnerabilities>
10
+ <vulnerability>
11
+ <LookupId>a000a00a-0000-000a-000-abcd00a0000a</LookupId>
12
+ <url>
13
+ http://aspnet.testsparker.com/blog/
14
+ </url>
15
+ <type>ConfirmedBlindSqlInjection</type>
16
+ <name>Blind SQL Injection</name>
17
+ <severity>Critical</severity>
18
+ <certainty>100</certainty>
19
+ <confirmed>True</confirmed>
20
+ <state>Present</state>
21
+ <FirstSeenDate>6/16/2020 1:41:23 PM +00:00</FirstSeenDate>
22
+ <LastSeenDate>6/16/2020 1:41:23 PM +00:00</LastSeenDate>
23
+ <classification>
24
+ <owasp>A1</owasp>
25
+ <wasc>19</wasc>
26
+ <cwe>89</cwe>
27
+ <capec>66</capec>
28
+ <pci32>6.5.1</pci32>
29
+ <hipaa>164.306(a), 164.308(a)</hipaa>
30
+ <owasppc></owasppc>
31
+ <iso27001>A.14.2.5</iso27001>
32
+ <cvss>
33
+ <vector>CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N</vector>
34
+ <score>
35
+ <type>Base</type>
36
+ <value>8.6</value>
37
+ <severity>High</severity>
38
+ </score>
39
+ <score>
40
+ <type>Temporal</type>
41
+ <value>8.6</value>
42
+ <severity>High</severity>
43
+ </score>
44
+ <score>
45
+ <type>Environmental</type>
46
+ <value>8.6</value>
47
+ <severity>High</severity>
48
+ </score>
49
+ </cvss>
50
+ <cvss31>
51
+ <vector>CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N</vector>
52
+ <score>
53
+ <type>Base</type>
54
+ <value>8.6</value>
55
+ <severity>High</severity>
56
+ </score>
57
+ <score>
58
+ <type>Temporal</type>
59
+ <value>8.6</value>
60
+ <severity>High</severity>
61
+ </score>
62
+ <score>
63
+ <type>Environmental</type>
64
+ <value>8.6</value>
65
+ <severity>High</severity>
66
+ </score>
67
+ </cvss31>
68
+ </classification>
69
+ <http-request>
70
+ <method>POST</method>
71
+ <parameters>
72
+ <parameter name="__VIEWSTATE" type="Post" value="/wEPDwUJLTIzMTExOTgyZGSsxJXO6Juz0H9WnmLaZ/ANH9shOpBmzSi1EHH6egImZA==" />
73
+ <parameter name="__VIEWSTATEGENERATOR" type="Post" value="5C9CE5AE" />
74
+ <parameter name="param1" type="UrlRewrite" value="&amp;apos;))&amp;#32;WAITFOR&amp;#32;DELAY&amp;#32;&amp;apos;0:0:25&amp;apos;--" vulnerable="vulnerable" />
75
+ </parameters>
76
+ <content>
77
+ <![CDATA[POST /blog/%27))%20WAITFOR%20DELAY%20%270%3a0%3a25%27--/HTTP1.1
78
+ Host: aspnet.testsparker.com
79
+ Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
80
+ Accept-Encoding: gzip, deflate
81
+ Accept-Language: en-us,en;q=0.5
82
+ Cache-Control: no-cache
83
+ Content-Length: 118
84
+ Content-Type: application/x-www-form-urlencoded
85
+ Cookie: ASP.NET_SessionId=44lomqqluxhcl2e4yxvrmxsq; TestCookie=Hello
86
+ Referer: http://aspnet.testsparker.com/blog/is-bitcoin-anonymous-95/
87
+ User-Agent: Chrome/70.0.3538.77
88
+ X-Scanner: Acunetix 360]]>
89
+ </content>
90
+ </http-request>
91
+ <http-response>
92
+ <status-code>404</status-code>
93
+ <duration>25053.3534</duration>
94
+ <content>
95
+ <![CDATA[HTTP/1.1 404 Not Found
96
+ Server: Microsoft-IIS/8.5
97
+ X-Powered-By: ASP.NET
98
+ X-AspNet-Version: 4.0.30319
99
+ Content-Length: 3084
100
+ Content-Type: text/html; charset=utf-8
101
+ Date: Tue, 16 Jun 2020 13:23:36 GMT
102
+ Cache-Control: private
103
+ <!DOCTYPE html>
104
+ <html xmlns="http://www.w3.org/1999/xhtml">
105
+ <head><meta http-equiv="content-type" content="text/html; charset=UTF-8" /><meta charset="utf-8" /><title>
106
+ Bitcoin Web Site
107
+ </title><meta name="generator" content="Bootply" /><meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" /><link href="//maxcdn.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet" /><link href="/statics/style.css" rel="stylesheet" />
108
+ </head>
109
+ <body>
110
+ <div id="resetbar">
111
+ This website is automatically reset at every midnight (00:00 - UTC).
112
+ </div>
113
+ </body>
114
+ </html>
115
+ ]]>
116
+ </content>
117
+ </http-response>
118
+ <description>
119
+ <![CDATA[<p>Acunetix 360 identified a Blind SQL Injection</p>]]>
120
+ </description>
121
+ <impact>
122
+ <![CDATA[<div>Depending on the backend database, the database connection settings, and the operating system, an attacker can mount one or more of the following attacks successfully:
123
+ <ul>
124
+ <li>Reading, updating and deleting arbitrary data or tables from the database</li>
125
+ <li>Executing commands on the underlying operating system</li>
126
+ </ul>
127
+ </div>]]>
128
+ </impact>
129
+ <remedial-actions>
130
+ <![CDATA[<div>
131
+ <ol>
132
+ <li>See the remedy for solution.</li>
133
+ </ol>
134
+ </div>]]>
135
+ </remedial-actions>
136
+ <exploitation-skills>
137
+ <![CDATA[<div>There are numerous freely available tools to exploit SQL injection vulnerabilities.</div>]]>
138
+ </exploitation-skills>
139
+ <remedial-procedure>
140
+ <![CDATA[<div>A robust method for mitigating the threat of SQL injection-based vulnerabilities is to use parameterized queries (<em>prepared statements</em>). Almost all modern languages provide built-in libraries for this. Wherever possible, do not create dynamic SQL queries or SQL queries with string concatenation.</div>]]>
141
+ </remedial-procedure>
142
+ <remedy-references>
143
+ <![CDATA[<div><ul><li><a target='_blank' href='https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet'><i class='icon-external-link'></i>SQL injection Prevention Cheat Sheet</a></li><li><a target='_blank' href='http://bobby-tables.com'><i class='icon-external-link'></i>A guide to preventing SQL injection</a></li></ul></div>]]>
144
+ </remedy-references>
145
+ <external-references>
146
+ <![CDATA[<div><ul><li><a target='_blank' href='https://www.owasp.org/index.php/Blind_SQL_Injection'><i class='icon-external-link'></i>Blind SQL Injection</a></li><li><a target='_blank' href='https://www.acunetix.com/blog/web-security/sql-injection-cheat-sheet/#BlindSQLInjections'><i class='icon-external-link'></i>SQL Injection Cheat Sheet[#Blind]</a></li></ul></div>]]>
147
+ </external-references>
148
+ <proof-of-concept></proof-of-concept>
149
+ </vulnerability>
150
+ <vulnerability>
151
+ <LookupId>a11a1a-11-11a-11-abcd1a111a</LookupId>
152
+ <url>http://aspnet.testsparker.com/About.aspx</url>
153
+ <type>Xss</type>
154
+ <name>Cross-site Scripting</name>
155
+ <severity>High</severity>
156
+ <certainty>100</certainty>
157
+ <confirmed>True</confirmed>
158
+ <state>Present</state>
159
+ <classification>
160
+ <owasp>A3</owasp>
161
+ <wasc>8</wasc>
162
+ <cwe>79</cwe>
163
+ <capec>19</capec>
164
+ <pci32>6.5.7</pci32>
165
+ <hipaa>164.308(a)</hipaa>
166
+ <owasppc></owasppc>
167
+ <iso27001>A.14.2.5</iso27001>
168
+ <cvss>
169
+ <vector>CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N</vector>
170
+ <score>
171
+ <type>Base</type>
172
+ <value>7.4</value>
173
+ <severity>High</severity>
174
+ </score>
175
+ <score>
176
+ <type>Temporal</type>
177
+ <value>7.4</value>
178
+ <severity>High</severity>
179
+ </score>
180
+ <score>
181
+ <type>Environmental</type>
182
+ <value>7.4</value>
183
+ <severity>High</severity>
184
+ </score>
185
+ </cvss>
186
+ <cvss31>
187
+ <vector>CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N</vector>
188
+ <score>
189
+ <type>Base</type>
190
+ <value>7.4</value>
191
+ <severity>High</severity>
192
+ </score>
193
+ <score>
194
+ <type>Temporal</type>
195
+ <value>7.4</value>
196
+ <severity>High</severity>
197
+ </score>
198
+ <score>
199
+ <type>Environmental</type>
200
+ <value>7.4</value>
201
+ <severity>High</severity>
202
+ </score>
203
+ </cvss31>
204
+ </classification>
205
+ <http-request>
206
+ <method>GET</method>
207
+ <parameters>
208
+ <parameter name="hello" type="Querystring" value="&amp;lt;scRipt&amp;gt;netsparker(0x0234AA)&amp;lt;/scRipt&amp;gt;" vulnerable="vulnerable" />
209
+ </parameters>
210
+ <content>
211
+ <![CDATA[GET /About.aspx HTTP/1.1
212
+ Host: aspnet.testsparker.com
213
+ Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
214
+ Accept-Encoding: gzip, deflate
215
+ Accept-Language: en-us,en;q=0.5
216
+ Cache-Control: no-cache
217
+ Cookie: ASP.NET_SessionId=aaaa; TestCookie=Hello
218
+ Referer: http://aspnet.testsparker.com/Guestbook.aspx
219
+ User-Agent: Chrome/70.0.3538.77
220
+ X-Scanner: Acunetix 360]]>
221
+ </content>
222
+ </http-request>
223
+ <http-response>
224
+ <status-code>200</status-code>
225
+ <duration>160.6656</duration>
226
+ <content>
227
+ <![CDATA[HTTP/1.1 200 OK
228
+ Server: Microsoft-IIS/8.5
229
+ X-Powered-By: ASP.NET
230
+ Vary: Accept-Encoding
231
+ X-AspNet-Version: 4.0.30319
232
+ Content-Length: 3267
233
+ Content-Type: text/html; charset=utf-8
234
+ Content-Encoding:
235
+ Date: Tue, 16 Jun 2020 12:54:25 GMT
236
+ Cache-Control: private
237
+ <!DOCTYPE html>
238
+
239
+ <html xmlns="http://www.w3.org/1999/xhtml">
240
+ <head><meta http-equiv="content-type" content="text/html; charset=UTF-8" /><meta charset="utf-8" /><title>
241
+ Bitcoin Web Site
242
+ </title><meta name="generator" content="Bootply" /><meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" /><link href="//maxcdn.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet" /><link href="/statics/style.css" rel="stylesheet" />
243
+ <!--[if lt IE 9]>
244
+ <script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
245
+ <![endif]-->
246
+ </head>
247
+ <body>
248
+ <div id="resetbar">This website is automatically reset at every midnight (00:00 - UTC).</div>
249
+ </body>
250
+ </html>]]>
251
+ </content>
252
+ </http-response>
253
+ <description>
254
+ <![CDATA[<p>Acunetix 360 detected Cross-site Scripting, which allows an attacker to execute a dynamic script (<em>JavaScript, VBScript</em>) in the context of the application.</p>]]>
255
+ </description>
256
+ <impact>
257
+ <![CDATA[<div>There are many different attacks that can be leveraged through the use of cross-site scripting, including:
258
+ <ul>
259
+ <li>Hijacking user's active session.</li>
260
+ <li>Mounting phishing attacks.</li>
261
+ <li>Intercepting data and performing man-in-the-middle attacks.</li>
262
+ </ul>
263
+ </div>]]>
264
+ </impact>
265
+ <remedial-actions></remedial-actions>
266
+ <exploitation-skills></exploitation-skills>
267
+ <remedial-procedure>
268
+ <![CDATA[<div><p><span style="font-weight: 400;">The issue occurs because the browser interprets the input as active HTML, JavaScript or VBScript. To avoid this, output should be encoded according to the output location and context.</span></p></div>]]>
269
+ </remedial-procedure>
270
+ <remedy-references>
271
+ <![CDATA[<div><ul><li><a target='_blank' href='https://www.microsoft.com/en-us/download/details.aspx?id=28589'><i class='icon-external-link'></i>Microsoft Anti-XSS Library</a></li><li><a target='_blank' href='https://www.acunetix.com/blog/web-security/negative-impact-incorrect-csp-implementations/'><i class='icon-external-link'></i>Negative Impact of Incorrect CSP Implementations</a></li></ul></div>]]>
272
+ </remedy-references>
273
+ <external-references>
274
+ <![CDATA[<div><ul><li><a target='_blank' href='https://www.owasp.org/index.php/Cross_site_scripting'><i class='icon-external-link'></i>OWASP - Cross-site Scripting</a></li><li><a target='_blank' href='https://www.acunetix.com/blog/web-security/cross-site-scripting-xss/'><i class='icon-external-link'></i>Cross-site Scripting Web Application Vulnerability</a></li></ul></div>]]>
275
+ </external-references>
276
+ <proof-of-concept></proof-of-concept>
277
+ </vulnerability>
278
+ </vulnerability>
279
+ </vulnerabilities>
280
+ </acunetix-360>
@@ -19,7 +19,7 @@ describe Acunetix::Scan do
19
19
 
20
20
  describe "creating a Scan object with the wrong XML element" do
21
21
  it "raises an error" do
22
- expect{ described_class.new(@xml) }.to raise_error
22
+ expect{ described_class.new(@xml) }.to raise_error(RuntimeError, /Invalid XML/)
23
23
  end
24
24
  end
25
25
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dradis-acunetix
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.12.0
4
+ version: 4.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Martin
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-07 00:00:00.000000000 Z
11
+ date: 2024-10-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dradis-plugins
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '1.6'
47
+ version: '2'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '1.6'
54
+ version: '2'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -96,7 +96,7 @@ dependencies:
96
96
  version: 0.5.2
97
97
  description: This add-on allows you to upload and parse output produced from Acunetix
98
98
  Web Vulnerability Scanner into Dradis.
99
- email:
99
+ email:
100
100
  executables: []
101
101
  extensions: []
102
102
  extra_rdoc_files: []
@@ -119,16 +119,17 @@ files:
119
119
  - lib/acunetix/vulnerability.rb
120
120
  - lib/dradis-acunetix.rb
121
121
  - lib/dradis/plugins/acunetix.rb
122
+ - lib/dradis/plugins/acunetix/acunetix360/importer.rb
122
123
  - lib/dradis/plugins/acunetix/engine.rb
123
124
  - lib/dradis/plugins/acunetix/field_processor.rb
124
- - lib/dradis/plugins/acunetix/formats/acunetix360.rb
125
- - lib/dradis/plugins/acunetix/formats/standard.rb
126
125
  - lib/dradis/plugins/acunetix/gem_version.rb
127
- - lib/dradis/plugins/acunetix/importer.rb
128
126
  - lib/dradis/plugins/acunetix/mapping.rb
127
+ - lib/dradis/plugins/acunetix/standard/importer.rb
129
128
  - lib/dradis/plugins/acunetix/version.rb
130
129
  - lib/tasks/thorfile.rb
131
- - spec/dradis-acunetix_spec.rb
130
+ - spec/acunetix/acunetix360/importer_spec.rb
131
+ - spec/acunetix/standard/importer_spec.rb
132
+ - spec/fixtures/files/acunetix360.xml
132
133
  - spec/fixtures/files/code-pre.acunetix.xml
133
134
  - spec/fixtures/files/commas-format.acunetix.xml
134
135
  - spec/fixtures/files/simple.acunetix.xml
@@ -144,7 +145,7 @@ homepage: https://dradis.com/integrations/acunetix.html
144
145
  licenses:
145
146
  - GPL-2
146
147
  metadata: {}
147
- post_install_message:
148
+ post_install_message:
148
149
  rdoc_options: []
149
150
  require_paths:
150
151
  - lib
@@ -159,12 +160,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
159
160
  - !ruby/object:Gem::Version
160
161
  version: '0'
161
162
  requirements: []
162
- rubygems_version: 3.1.4
163
- signing_key:
163
+ rubygems_version: 3.5.6
164
+ signing_key:
164
165
  specification_version: 4
165
166
  summary: Acunetix add-on for the Dradis Framework.
166
167
  test_files:
167
- - spec/dradis-acunetix_spec.rb
168
+ - spec/acunetix/acunetix360/importer_spec.rb
169
+ - spec/acunetix/standard/importer_spec.rb
170
+ - spec/fixtures/files/acunetix360.xml
168
171
  - spec/fixtures/files/code-pre.acunetix.xml
169
172
  - spec/fixtures/files/commas-format.acunetix.xml
170
173
  - spec/fixtures/files/simple.acunetix.xml
@@ -1,51 +0,0 @@
1
- module Dradis::Plugins::Acunetix::Formats
2
- module Acunetix360
3
-
4
- private
5
-
6
- def process_acunetix360
7
- process_target_node
8
- process_acunetix360_vulnerabilities
9
- end
10
-
11
- def process_target_node
12
- target_xml = xml.at_xpath('//acunetix-360/target')
13
- @scan_node = content_service.create_node(
14
- label: target_xml.at_xpath('url').text,
15
- type: :host
16
- )
17
-
18
- logger.info { "Creating target node: #{scan_node.label}" }
19
-
20
- if scan_node.respond_to?(:properties)
21
- scan_node.set_property(:scan_id, target_xml.at_xpath('scan-id').text)
22
- scan_node.set_property(:initiated, target_xml.at_xpath('initiated').text)
23
- scan_node.set_property(:duration, target_xml.at_xpath('duration').text)
24
- end
25
- end
26
-
27
- def process_acunetix360_vulnerabilities
28
- logger.info { 'Creating issues from Acunetix360 vulnerabilities.' }
29
-
30
- xml.xpath('//acunetix-360/vulnerabilities/vulnerability').each do |vuln_xml|
31
- issue_text = mapping_service.apply_mapping(
32
- source: 'vulnerability_360',
33
- data: vuln_xml
34
- )
35
-
36
- type = vuln_xml.at_xpath('type').text
37
-
38
- logger.info { "\t\t => Creating new issue: #{type}" }
39
- issue = content_service.create_issue(text: issue_text, id: type)
40
-
41
- evidence_text = mapping_service.apply_mapping(
42
- source: 'evidence_360',
43
- data: vuln_xml
44
- )
45
-
46
- logger.info { "\t\t => Creating new evidence" }
47
- content_service.create_evidence(issue: issue, node: scan_node, content: evidence_text)
48
- end
49
- end
50
- end
51
- end
@@ -1,58 +0,0 @@
1
- module Dradis::Plugins::Acunetix::Formats
2
- module Standard
3
-
4
- private
5
-
6
- def process_standard
7
- xml.xpath('/ScanGroup/Scan').each do |xml_scan|
8
- process_scan(xml_scan)
9
- end
10
- end
11
-
12
- def process_scan(xml_scan)
13
- url = xml_scan.at_xpath('./StartURL').text()
14
- start_url = URI::parse(url).host || url # urls wo/ protocol returned nil
15
-
16
- self.scan_node = content_service.create_node(label: start_url, type: :host)
17
- logger.info{ "\tScan start URL: #{start_url}" }
18
-
19
- # Define Node properties
20
- if scan_node.respond_to?(:properties)
21
- scan_node.set_property(:short_name, xml_scan.at_xpath('./ShortName').text() )
22
- scan_node.set_property(:start_url, start_url)
23
- scan_node.set_property(:start_time, xml_scan.at_xpath('./StartTime').text() )
24
- scan_node.set_property(:finish_time, xml_scan.at_xpath('./FinishTime').text() )
25
- scan_node.set_property(:scan_time, xml_scan.at_xpath('./ScanTime').text() )
26
- scan_node.set_property(:aborted, xml_scan.at_xpath('./Aborted').text() )
27
- scan_node.set_property(:responsive, xml_scan.at_xpath('./Responsive').text() )
28
- scan_node.set_property(:banner, xml_scan.at_xpath('./Banner').text() )
29
- scan_node.set_property(:os, xml_scan.at_xpath('./Os').text() )
30
- scan_node.set_property(:web_server, xml_scan.at_xpath('./WebServer').text() )
31
- scan_node.set_property(:technologies, xml_scan.at_xpath('./Technologies').text() )
32
- scan_node.save
33
- end
34
-
35
- scan_note = mapping_service.apply_mapping(source: 'scan', data: xml_scan)
36
- content_service.create_note text: scan_note, node: scan_node
37
-
38
- xml_scan.xpath('./ReportItems/ReportItem').each do |xml_report_item|
39
- process_report_item(xml_report_item)
40
- end
41
- end
42
-
43
- def process_report_item(xml_report_item)
44
- plugin_id = "%s/%s" % [
45
- xml_report_item.at_xpath('./ModuleName').text(),
46
- xml_report_item.at_xpath('./Name').text()
47
- ]
48
- logger.info { "\t\t => Creating new issue (plugin_id: #{plugin_id})" }
49
-
50
- issue_text = mapping_service.apply_mapping(source: 'report_item', data: xml_report_item)
51
- issue = content_service.create_issue(text: issue_text, id: plugin_id)
52
-
53
- logger.info { "\t\t => Creating new evidence" }
54
- evidence_content = mapping_service.apply_mapping(source: 'evidence', data: xml_report_item)
55
- content_service.create_evidence(issue: issue, node: scan_node, content: evidence_content)
56
- end
57
- end
58
- end
@@ -1,43 +0,0 @@
1
- require 'dradis/plugins/acunetix/formats/standard'
2
- require 'dradis/plugins/acunetix/formats/acunetix360'
3
-
4
- module Dradis::Plugins::Acunetix
5
- class Importer < Dradis::Plugins::Upload::Importer
6
- include Dradis::Plugins::Acunetix::Formats::Standard
7
- include Dradis::Plugins::Acunetix::Formats::Acunetix360
8
-
9
- attr_accessor :scan_node, :xml
10
-
11
- def self.templates
12
- { evidence: 'evidence', issue: 'report_item' }
13
- end
14
-
15
- # The framework will call this function if the user selects this plugin from
16
- # the dropdown list and uploads a file.
17
- # @returns true if the operation was successful, false otherwise
18
- def import(params={})
19
- file_content = File.read( params.fetch(:file) )
20
-
21
- logger.info{'Parsing Acunetix output file...'}
22
- @xml = Nokogiri::XML( file_content )
23
- logger.info{'Done.'}
24
-
25
- if xml.xpath('/ScanGroup/Scan').present?
26
- logger.info { 'Standard Acunetix import detected.' }
27
- process_standard
28
-
29
- return true
30
- elsif xml.xpath('//acunetix-360').present?
31
- logger.info { 'Acunetix360 import detected.' }
32
- process_acunetix360
33
-
34
- return true
35
- else
36
- error = "No scan results were detected in the uploaded file (/ScanGroup/Scan). Ensure you uploaded an Acunetix XML report."
37
- logger.fatal{ error }
38
- content_service.create_note text: error
39
- return false
40
- end
41
- end # /import
42
- end
43
- end
@@ -1,109 +0,0 @@
1
- require 'spec_helper'
2
- require 'ostruct'
3
-
4
- module Dradis::Plugins
5
- describe 'Acunetix upload plugin' do
6
- before(:each) do
7
- # Stub template service
8
- templates_dir = File.expand_path('../../templates', __FILE__)
9
- allow_any_instance_of(TemplateService).to \
10
- receive(:default_templates_dir).and_return(templates_dir)
11
-
12
- @content_service = ContentService.new(plugin: Acunetix)
13
- template_service = TemplateService.new(plugin: Acunetix)
14
-
15
- @importer = Acunetix::Importer.new(
16
- content_service: @content_service,
17
- template_service: template_service
18
- )
19
-
20
- # Stub dradis-plugins methods
21
- #
22
- # They return their argument hashes as objects mimicking
23
- # Nodes, Issues, etc
24
- allow(@content_service).to receive(:create_node) do |args|
25
- OpenStruct.new(args)
26
- end
27
- allow(@content_service).to receive(:create_note) do |args|
28
- OpenStruct.new(args)
29
- end
30
- allow(@content_service).to receive(:create_issue) do |args|
31
- OpenStruct.new(args)
32
- end
33
- allow(@content_service).to receive(:create_evidence) do |args|
34
- OpenStruct.new(args)
35
- end
36
- end
37
-
38
- it "creates nodes, issues, notes and an evidences as needed" do
39
-
40
- expect(@content_service).to receive(:create_node).with(hash_including label: "testphp.vulnweb.com", type: :host).once
41
- expect(@content_service).to receive(:create_note) do |args|
42
- expect(args[:text]).to include("#[Title]#\nAcunetix scanner notes (7/10/2014, 11:56:03)")
43
- expect(args[:node].label).to eq("testphp.vulnweb.com")
44
- end.once
45
-
46
- expect(@content_service).to receive(:create_issue) do |args|
47
- expect(args[:text]).to include("#[Title]#\nHTML form without CSRF protection")
48
- expect(args[:id]).to eq("Crawler/HTML form without CSRF protection")
49
- OpenStruct.new(args)
50
- end.once
51
-
52
- expect(@content_service).to receive(:create_issue) do |args|
53
- expect(args[:text]).to include("#[Title]#\nClickjacking: X-Frame-Options header missing")
54
- expect(args[:id]).to eq("Scripting (Clickjacking_X_Frame_Options.script)/Clickjacking: X-Frame-Options header missing")
55
- OpenStruct.new(args)
56
- end.once
57
-
58
- expect(@content_service).to receive(:create_evidence) do |args|
59
- expect(args[:content]).to include("/")
60
- expect(args[:issue].id).to eq("Crawler/HTML form without CSRF protection")
61
- expect(args[:node].label).to eq("testphp.vulnweb.com")
62
- end.once
63
-
64
- expect(@content_service).to receive(:create_evidence) do |args|
65
- expect(args[:content]).to include("Web Server")
66
- expect(args[:issue].id).to eq("Scripting (Clickjacking_X_Frame_Options.script)/Clickjacking: X-Frame-Options header missing")
67
- expect(args[:node].label).to eq("testphp.vulnweb.com")
68
- end.once
69
-
70
- @importer.import(file: 'spec/fixtures/files/simple.acunetix.xml')
71
- end
72
-
73
- # Regression test for github.com/dradis/dradis-nexpose/issues/1
74
- describe "Source HTML parsing" do
75
- it "identifies code/pre blocks and replaces them with the Textile equivalent" do
76
-
77
- expect(@content_service).to receive(:create_issue) do |args|
78
- expect(args[:text]).to include("#[Title]#\nSQL injection (verified)")
79
- expect(args[:text]).not_to include("<code>")
80
- expect(args[:text]).not_to include("<pre")
81
- expect(args[:id]).to eq("Scripting (Sql_Injection.script)/SQL injection (verified)")
82
- OpenStruct.new(args)
83
- end.once
84
-
85
- # expect(@content_service).to receive(:create_evidence) do |args|
86
- # expect(args[:content]).to include("Web Server")
87
- # expect(args[:issue].id).to eq("Scripting (Clickjacking_X_Frame_Options.script)")
88
- # expect(args[:node].label).to eq("testphp.vulnweb.com")
89
- # end.once
90
-
91
- @importer.import(file: 'spec/fixtures/files/code-pre.acunetix.xml')
92
- end
93
- end
94
-
95
- # Regression test to make sure that commas are replaced with decimals in the CVSSv3 scores
96
- describe "CVSS clean up decimals" do
97
- it "identifies commas used as decimals in CVSSv3 scores and replaces them with periods" do
98
-
99
- expect(@content_service).to receive(:create_issue) do |args|
100
- expect(args[:text]).to include("#[CVSS3Score]#\n5.3")
101
- OpenStruct.new(args)
102
- end
103
-
104
- @importer.import(file: 'spec/fixtures/files/commas-format.acunetix.xml')
105
- end
106
- end
107
-
108
- end
109
- end