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 +4 -4
- data/CHANGELOG.md +6 -0
- data/dradis-acunetix.gemspec +1 -1
- data/lib/dradis/plugins/acunetix/acunetix360/importer.rb +95 -0
- data/lib/dradis/plugins/acunetix/engine.rb +12 -0
- data/lib/dradis/plugins/acunetix/gem_version.rb +1 -1
- data/lib/dradis/plugins/acunetix/mapping.rb +46 -46
- data/lib/dradis/plugins/acunetix/standard/importer.rb +102 -0
- data/lib/dradis/plugins/acunetix.rb +2 -1
- data/lib/tasks/thorfile.rb +21 -7
- data/spec/acunetix/acunetix360/importer_spec.rb +61 -0
- data/spec/acunetix/standard/importer_spec.rb +100 -0
- data/spec/fixtures/files/acunetix360.xml +280 -0
- data/spec/models/acunetix/scan_spec.rb +1 -1
- metadata +17 -14
- data/lib/dradis/plugins/acunetix/formats/acunetix360.rb +0 -51
- data/lib/dradis/plugins/acunetix/formats/standard.rb +0 -58
- data/lib/dradis/plugins/acunetix/importer.rb +0 -43
- data/spec/dradis-acunetix_spec.rb +0 -109
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 70ada77a2b5ccc95dea1ee7de02fb8ff3dc64b53b4083cd6a6bbc5ef0ef2436a
|
4
|
+
data.tar.gz: ea41c007052e86cc1911e6c14869207bf8826b2498088fcd2f0a9d884dbd3972
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b440d35fc20eee027b5cc8c959ba16e7d646d725c1e6db537740b2b8c2b24c20671a136b31d66f9b632f976d98ea514b5d4b8ffbb8c18723a8579645bf712e1d
|
7
|
+
data.tar.gz: abb9e364750381d45c33ba282cd47811c05a4e4fb51a7f9d89d348fc9f48d6cd55ff1712fac2673865139c5b8ec9a5dcebefbd3b57e1d623622ac862869aeda9
|
data/CHANGELOG.md
CHANGED
data/dradis-acunetix.gemspec
CHANGED
@@ -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', '~>
|
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
|
@@ -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.
|
77
|
+
'evidence.aop_additional',
|
79
78
|
'evidence.aop_source_file',
|
80
79
|
'evidence.aop_source_line',
|
81
|
-
'evidence.
|
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.
|
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.
|
104
|
-
'report_item.
|
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.
|
118
|
-
'scan.
|
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.
|
122
|
-
'vulnerability_360.
|
123
|
-
'vulnerability_360.
|
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.
|
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
|
|
data/lib/tasks/thorfile.rb
CHANGED
@@ -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
|
-
|
7
|
-
|
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="&apos;))&#32;WAITFOR&#32;DELAY&#32;&apos;0:0:25&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="&lt;scRipt&gt;netsparker(0x0234AA)&lt;/scRipt&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.
|
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-
|
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: '
|
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: '
|
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/
|
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.
|
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/
|
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
|