dradis-burp 3.9.0 → 3.10.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 +11 -4
- data/lib/burp/issue.rb +14 -10
- data/lib/dradis/plugins/burp/gem_version.rb +1 -1
- data/lib/dradis/plugins/burp/importer.rb +93 -50
- data/spec/burp_upload_spec.rb +12 -11
- data/spec/fixtures/files/burp.xml +1 -1
- data/templates/issue.fields +2 -0
- data/templates/issue.sample +21 -10
- data/templates/issue.template +8 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fcd4870b2ac20839adc44a4abd01a94c6796a158
|
4
|
+
data.tar.gz: 73390a8db93ced0c81c63b37ab32bf0a3597b734
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 99e04356a79bc4f7dbeb11ef5e1ba7fb9d0ce32e8f091d09cdaf5210e7881484d2af1c33b308885c20c7ba2d82ee2cef5b20c78b5689c0ae9d9d16657a51401c
|
7
|
+
data.tar.gz: b831bdc6aef442661eadbdeeebc6a92c3a5f6c1f9050f6b7728a326326045e82ff00ebf8efddfd978690a19c554e8996a2233a520611d907bf2e4af41c6ca62f
|
data/CHANGELOG.md
CHANGED
@@ -1,18 +1,25 @@
|
|
1
|
-
## Dradis Framework 3.
|
1
|
+
## Dradis Framework 3.10 (August, 2018) ##
|
2
|
+
|
3
|
+
* Adds `references` and `vulnerability_classifications` as available fields
|
4
|
+
|
5
|
+
* Adds `hostname` as a Node property
|
6
|
+
|
7
|
+
* Fixes formatting errors including `<p>`, `<a href="">`, and `<table>` tags
|
2
8
|
|
3
|
-
*
|
9
|
+
* Findings with <type>134217728</type> are not bundled together into one Issue
|
4
10
|
|
11
|
+
## Dradis Framework 3.9 (January, 2018) ##
|
12
|
+
|
13
|
+
* Encode content with UTF-8 to avoid incompatible db errors (v3.8.1)
|
5
14
|
|
6
15
|
## Dradis Framework 3.8 (September, 2017) ##
|
7
16
|
|
8
17
|
* No changes.
|
9
18
|
|
10
|
-
|
11
19
|
## Dradis Framework 3.7 (July, 2017) ##
|
12
20
|
|
13
21
|
* Detect non-base64 encoded files and binary req/res data.
|
14
22
|
|
15
|
-
|
16
23
|
## Dradis Framework 3.6 (March, 2017) ##
|
17
24
|
|
18
25
|
* Detect non-base64 encoded files and binary req/res data.
|
data/lib/burp/issue.rb
CHANGED
@@ -26,7 +26,7 @@ module Burp
|
|
26
26
|
# simple tags
|
27
27
|
:serial_number, :type, :name, :host, :path, :location, :severity,
|
28
28
|
:confidence, :background, :remediation_background, :detail,
|
29
|
-
:remediation_detail,
|
29
|
+
:remediation_detail, :references, :vulnerability_classifications,
|
30
30
|
|
31
31
|
# nested tags
|
32
32
|
:request, :response
|
@@ -64,6 +64,7 @@ module Burp
|
|
64
64
|
:detail => 'issueDetail',
|
65
65
|
:remediation_background => 'remediationBackground',
|
66
66
|
:remediation_detail => 'remediationDetail',
|
67
|
+
:vulnerability_classifications => 'vulnerabilityClassifications',
|
67
68
|
:serial_number => 'serialNumber'
|
68
69
|
}
|
69
70
|
|
@@ -98,27 +99,30 @@ module Burp
|
|
98
99
|
result.gsub!(/&/, '&')
|
99
100
|
result.gsub!(/</, '<')
|
100
101
|
result.gsub!(/>/, '>')
|
102
|
+
result.gsub!(/ /, ' ')
|
101
103
|
|
102
104
|
result.gsub!(/<b>(.*?)<\/b>/, '*\1*')
|
103
|
-
result.gsub!(/<br
|
104
|
-
result.gsub!(/<br>/, "\n")
|
105
|
+
result.gsub!(/<br>|<\/br>/){"\n"}
|
105
106
|
result.gsub!(/<font.*?>(.*?)<\/font>/m, '\1')
|
106
|
-
result.gsub!(/<
|
107
|
+
result.gsub!(/<h\d?>(.*?)<\/h\d?>/, '*\1*')
|
107
108
|
result.gsub!(/<i>(.*?)<\/i>/, '\1')
|
108
|
-
result.gsub!(/<p
|
109
|
+
result.gsub!(/<p>|<\/p>/){"\n"}
|
109
110
|
result.gsub!(/<pre.*?>(.*?)<\/pre>/m){|m| "\n\nbc.. #{ $1 }\n\np. \n" }
|
110
111
|
|
111
|
-
result.gsub!(/<ul
|
112
|
-
result.gsub!(
|
113
|
-
result.gsub!(/<
|
114
|
-
|
112
|
+
result.gsub!(/<ul>(.*?)<\/ul>/m){|m| "#{ $1 }\n"}
|
113
|
+
result.gsub!(/<li>(.*?)<\/li>/m){|m| "\n* #{ $1 }"}
|
114
|
+
result.gsub!(/<a href=\"(.*?)\">(.*?)<\/a>/i) { "\"#{$2.strip}\":#{$1.strip}" }
|
115
|
+
|
116
|
+
result.gsub!(/<table>(.*?)<\/table>/m){|m| "\n\n#{ $1 }\n\n" }
|
117
|
+
result.gsub!(/<tr>(.*?)<\/tr>/m){|m| "|#{ $1 }\n" }
|
118
|
+
result.gsub!(/<td>(.*?)<\/td>/, '\1|')
|
115
119
|
|
116
120
|
result
|
117
121
|
end
|
118
122
|
|
119
123
|
# Some of the values have embedded HTML content that we need to strip
|
120
124
|
def tags_with_html_content
|
121
|
-
[:background, :detail, :remediation_background, :remediation_detail]
|
125
|
+
[:background, :detail, :remediation_background, :remediation_detail, :references, :vulnerability_classifications]
|
122
126
|
end
|
123
127
|
|
124
128
|
def requestresponse_child(field)
|
@@ -5,91 +5,134 @@ module Dradis::Plugins::Burp
|
|
5
5
|
# the dropdown list and uploads a file.
|
6
6
|
# @returns true if the operation was successful, false otherwise
|
7
7
|
def import(params = {})
|
8
|
-
file_content = File.read(
|
8
|
+
file_content = File.read(params[:file])
|
9
9
|
|
10
10
|
if file_content =~ /base64="false"/
|
11
11
|
error = "Burp input contains HTTP request / response data that hasn't been Base64-encoded.\n"
|
12
|
-
error <<
|
12
|
+
error << 'Please re-export your scanner results making sure the Base-64 encode option is selected.'
|
13
13
|
|
14
14
|
logger.fatal{ error }
|
15
15
|
content_service.create_note text: error
|
16
16
|
return false
|
17
17
|
end
|
18
18
|
|
19
|
-
logger.info{ 'Parsing Burp Scanner output file...' }
|
20
|
-
doc = Nokogiri::XML(
|
21
|
-
logger.info{'Done.'}
|
19
|
+
logger.info { 'Parsing Burp Scanner output file...' }
|
20
|
+
doc = Nokogiri::XML(file_content)
|
21
|
+
logger.info { 'Done.' }
|
22
22
|
|
23
23
|
if doc.root.name != 'issues'
|
24
24
|
error = "Document doesn't seem to be in the Burp Scanner XML format."
|
25
|
-
logger.fatal{ error }
|
25
|
+
logger.fatal { error }
|
26
26
|
content_service.create_note text: error
|
27
27
|
return false
|
28
28
|
end
|
29
29
|
|
30
30
|
# This will be filled in by the Processor while iterating over the issues
|
31
|
-
hosts = []
|
32
|
-
affected_host = nil
|
33
|
-
issue_text = nil
|
34
|
-
evidence_text = nil
|
31
|
+
@hosts = []
|
32
|
+
@affected_host = nil
|
33
|
+
@issue_text = nil
|
34
|
+
@evidence_text = nil
|
35
35
|
|
36
36
|
doc.xpath('issues/issue').each do |xml_issue|
|
37
|
-
|
38
|
-
|
37
|
+
process_issue(xml_issue)
|
38
|
+
end
|
39
39
|
|
40
|
-
|
40
|
+
logger.info { 'Burp Scanner results successfully imported' }
|
41
|
+
true
|
42
|
+
end
|
41
43
|
|
42
|
-
|
43
|
-
host_label = xml_issue.at('host').text if host_label.empty?
|
44
|
-
affected_host = content_service.create_node(label: host_label, type: :host)
|
45
|
-
logger.info{ "\taffects: #{ host_label }" }
|
44
|
+
private
|
46
45
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
46
|
+
# Creates the Nodes/properties
|
47
|
+
def process_issue(xml_issue)
|
48
|
+
host_label = xml_issue.at('host')['ip']
|
49
|
+
host_label = xml_issue.at('host').text if host_label.empty?
|
50
|
+
affected_host = content_service.create_node(label: host_label, type: :host)
|
51
|
+
logger.info { "\taffects: #{host_label}" }
|
53
52
|
|
54
|
-
|
55
|
-
|
56
|
-
|
53
|
+
unless @hosts.include?(affected_host.label)
|
54
|
+
@hosts << affected_host.label
|
55
|
+
url = xml_issue.at('host').text
|
56
|
+
affected_host.set_property(:hostname, url)
|
57
|
+
affected_host.save
|
58
|
+
end
|
57
59
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
60
|
+
# Burp extensions don't follow the "unique type for every Issue" logic
|
61
|
+
# so we have to deal with them separately
|
62
|
+
if xml_issue.at('type').text.to_str == '134217728'
|
63
|
+
process_extension_issues(affected_host, xml_issue)
|
64
|
+
else
|
65
|
+
process_burp_issues(affected_host, xml_issue)
|
66
|
+
end
|
67
|
+
end
|
64
68
|
|
65
|
-
|
66
|
-
|
67
|
-
|
69
|
+
# If the Issues come from the Burp app, use the type as the plugin_ic
|
70
|
+
def process_burp_issues(affected_host, xml_issue)
|
71
|
+
issue_name = xml_issue.at('name').text
|
72
|
+
issue_type = xml_issue.at('type').text.to_i
|
68
73
|
|
69
|
-
|
74
|
+
logger.info { "Adding #{issue_name} (#{issue_type})" }
|
70
75
|
|
71
|
-
|
72
|
-
|
76
|
+
create_issue(
|
77
|
+
affected_host: affected_host,
|
78
|
+
id: issue_type,
|
79
|
+
xml_issue: xml_issue
|
80
|
+
)
|
81
|
+
end
|
82
|
+
|
83
|
+
# If the Issues come from a Burp extension (type = 134217728), then
|
84
|
+
# use the name (spaces removed) as the plugin_id
|
85
|
+
def process_extension_issues(affected_host, xml_issue)
|
86
|
+
ext_name = xml_issue.at('name').text
|
87
|
+
ext_name = ext_name.gsub!(" ", "")
|
88
|
+
|
89
|
+
logger.info { "Adding #{ext_name}" }
|
90
|
+
|
91
|
+
create_issue(
|
92
|
+
affected_host: affected_host,
|
93
|
+
id: ext_name,
|
94
|
+
xml_issue: xml_issue
|
95
|
+
)
|
96
|
+
end
|
97
|
+
|
98
|
+
def create_issue(affected_host:, id:, xml_issue:)
|
99
|
+
issue_text =
|
100
|
+
template_service.process_template(
|
101
|
+
template: 'issue',
|
73
102
|
data: xml_issue
|
74
103
|
)
|
75
104
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
}
|
105
|
+
if issue_text.include?(::Burp::INVALID_UTF_REPLACE)
|
106
|
+
logger.info do
|
107
|
+
"\tdetected invalid UTF-8 bytes in your issue. " \
|
108
|
+
"Replacing them with '#{::Burp::INVALID_UTF_REPLACE}'."
|
81
109
|
end
|
110
|
+
end
|
111
|
+
|
112
|
+
issue = content_service.create_issue(text: issue_text, id: id)
|
82
113
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
114
|
+
logger.info do
|
115
|
+
"\tadding evidence for this instance to #{affected_host.label}."
|
116
|
+
end
|
117
|
+
|
118
|
+
evidence_text =
|
119
|
+
template_service.process_template(
|
120
|
+
template: 'evidence',
|
121
|
+
data: xml_issue
|
87
122
|
)
|
88
123
|
|
124
|
+
if evidence_text.include?(::Burp::INVALID_UTF_REPLACE)
|
125
|
+
logger.info do
|
126
|
+
"\tdetected invalid UTF-8 bytes in your evidence. " \
|
127
|
+
"Replacing them with '#{::Burp::INVALID_UTF_REPLACE}'."
|
128
|
+
end
|
89
129
|
end
|
90
|
-
logger.info{ 'Burp Scanner results successfully imported' }
|
91
|
-
return true
|
92
|
-
end
|
93
130
|
|
131
|
+
content_service.create_evidence(
|
132
|
+
issue: issue,
|
133
|
+
node: affected_host,
|
134
|
+
content: evidence_text
|
135
|
+
)
|
136
|
+
end
|
94
137
|
end
|
95
138
|
end
|
data/spec/burp_upload_spec.rb
CHANGED
@@ -37,10 +37,9 @@ describe 'Burp upload plugin' do
|
|
37
37
|
# They return their argument hashes as objects mimicking
|
38
38
|
# Nodes, Issues, etc
|
39
39
|
allow(@content_service).to receive(:create_node) do |args|
|
40
|
-
OpenStruct.new(args)
|
41
|
-
|
42
|
-
|
43
|
-
OpenStruct.new(args)
|
40
|
+
obj = OpenStruct.new(args)
|
41
|
+
obj.define_singleton_method(:set_property) { |_, __| }
|
42
|
+
obj
|
44
43
|
end
|
45
44
|
allow(@content_service).to receive(:create_issue) do |args|
|
46
45
|
OpenStruct.new(args)
|
@@ -50,24 +49,20 @@ describe 'Burp upload plugin' do
|
|
50
49
|
end
|
51
50
|
end
|
52
51
|
|
53
|
-
it "creates nodes, issues,
|
52
|
+
it "creates nodes, issues, and evidence as needed" do
|
54
53
|
|
55
|
-
# Host node
|
54
|
+
# Host node
|
56
55
|
#
|
57
56
|
# create_node should be called once for each issue in the xml,
|
58
57
|
# but ContentService knows it's already created and NOOPs
|
59
58
|
expect(@content_service).to receive(:create_node)
|
60
59
|
.with(hash_including label: '10.0.0.1')
|
61
60
|
.exactly(4).times
|
62
|
-
# create_note should be calld just once
|
63
|
-
expect(@content_service).to receive(:create_note) do |args|
|
64
|
-
expect(args[:text]).to include("#[HostInfo]#\nhttp://www.test.com")
|
65
|
-
OpenStruct.new(args)
|
66
|
-
end.once
|
67
61
|
|
68
62
|
# create_issue should be called once for each issue in the xml
|
69
63
|
expect(@content_service).to receive(:create_issue) do |args|
|
70
64
|
expect(args[:text]).to include("#[Title]#\nIssue 1")
|
65
|
+
expect(args[:id]).to eq(8781630)
|
71
66
|
OpenStruct.new(args)
|
72
67
|
end.once
|
73
68
|
expect(@content_service).to receive(:create_evidence) do |args|
|
@@ -78,6 +73,7 @@ describe 'Burp upload plugin' do
|
|
78
73
|
|
79
74
|
expect(@content_service).to receive(:create_issue) do |args|
|
80
75
|
expect(args[:text]).to include("#[Title]#\nIssue 2")
|
76
|
+
expect(args[:id]).to eq(8781631)
|
81
77
|
OpenStruct.new(args)
|
82
78
|
end.once
|
83
79
|
expect(@content_service).to receive(:create_evidence) do |args|
|
@@ -86,8 +82,12 @@ describe 'Burp upload plugin' do
|
|
86
82
|
expect(args[:node].label).to eq("10.0.0.1")
|
87
83
|
end.once
|
88
84
|
|
85
|
+
# Issue 3 is an Extension finding so we need to confirm
|
86
|
+
# that it triggers process_extension_issues instead of process_burp_issues
|
87
|
+
# and the plugin_id is not set to the Type (134217728)
|
89
88
|
expect(@content_service).to receive(:create_issue) do |args|
|
90
89
|
expect(args[:text]).to include("#[Title]#\nIssue 3")
|
90
|
+
expect(args[:id]).to eq("Issue3")
|
91
91
|
OpenStruct.new(args)
|
92
92
|
end.once
|
93
93
|
expect(@content_service).to receive(:create_evidence) do |args|
|
@@ -98,6 +98,7 @@ describe 'Burp upload plugin' do
|
|
98
98
|
|
99
99
|
expect(@content_service).to receive(:create_issue) do |args|
|
100
100
|
expect(args[:text]).to include("#[Title]#\nIssue 4")
|
101
|
+
expect(args[:id]).to eq(8781633)
|
101
102
|
OpenStruct.new(args)
|
102
103
|
end.once
|
103
104
|
expect(@content_service).to receive(:create_evidence) do |args|
|
data/templates/issue.fields
CHANGED
data/templates/issue.sample
CHANGED
@@ -1,12 +1,23 @@
|
|
1
1
|
<issue>
|
2
|
-
<serialNumber>
|
3
|
-
<type>
|
4
|
-
<name
|
5
|
-
<host ip="
|
6
|
-
<path><![CDATA[/
|
7
|
-
<location><![CDATA[/
|
8
|
-
<severity>
|
9
|
-
<confidence>
|
10
|
-
<issueBackground><![CDATA[
|
11
|
-
|
2
|
+
<serialNumber>5863488220648493056</serialNumber>
|
3
|
+
<type>16777984</type>
|
4
|
+
<name><![CDATA[Strict transport security not enforced]]></name>
|
5
|
+
<host ip="192.168.1.1">https://this.is.a.url</host>
|
6
|
+
<path><![CDATA[/]]></path>
|
7
|
+
<location><![CDATA[/]]></location>
|
8
|
+
<severity>Low</severity>
|
9
|
+
<confidence>Certain</confidence>
|
10
|
+
<issueBackground><![CDATA[<p> The application fails to prevent users from connecting to it over unencrypted connections. An attacker able to modify a legitimate user's network traffic could bypass the application's use of SSL/TLS encryption, and use the application as a platform for attacks against its users. This attack is performed by rewriting HTTPS links as HTTP, so that if a targeted user follows a link to the site from an HTTP page, their browser never attempts to use an encrypted connection. The sslstrip tool automates this process. </p>
|
11
|
+
<p>
|
12
|
+
To exploit this vulnerability, an attacker must be suitably positioned to intercept and modify the victim's network traffic.This scenario typically occurs when a client communicates with the server over an insecure connection such as public Wi-Fi, or a corporate or home network that is shared with a compromised computer. Common defenses such as switched networks are not sufficient to prevent this. An attacker situated in the user's ISP or the application's hosting infrastructure could also perform this attack. Note that an advanced adversary could potentially target any connection made over the Internet's core infrastructure. </p>]]></issueBackground>
|
13
|
+
<remediationBackground><![CDATA[<p>The application should instruct web browsers to only access the application using HTTPS. To do this, enable HTTP Strict Transport Security (HSTS) by adding a response header with the name 'Strict-Transport-Security' and the value 'max-age=expireTime', where expireTime is the time in seconds that browsers should remember that the site should only be accessed using HTTPS. Consider adding the 'includeSubDomains' flag if appropriate.</p>
|
14
|
+
<p>Note that because HSTS is a "trust on first use" (TOFU) protocol, a user who has never accessed the application will never have seen the HSTS header, and will therefore still be vulnerable to SSL stripping attacks. To mitigate this risk, you can optionally add the 'preload' flag to the HSTS header, and submit the domain for review by browser vendors.</p>]]></remediationBackground>
|
15
|
+
<references><![CDATA[<ul>
|
16
|
+
<li><a href="https://developer.mozilla.org/en-US/docs/Web/Security/HTTP_strict_transport_security">HTTP Strict Transport Security</a></li>
|
17
|
+
<li><a href="http://www.thoughtcrime.org/software/sslstrip/">sslstrip</a></li>
|
18
|
+
<li><a href="https://hstspreload.appspot.com/">HSTS Preload Form</a></li>
|
19
|
+
</ul>]]></references>
|
20
|
+
<vulnerabilityClassifications><![CDATA[<ul>
|
21
|
+
<li><a href="https://cwe.mitre.org/data/definitions/523.html">CWE-523: Unprotected Transport of Credentials</a></li>
|
22
|
+
</ul>]]></vulnerabilityClassifications>
|
12
23
|
</issue>
|
data/templates/issue.template
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dradis-burp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Martin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-08-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dradis-plugins
|
@@ -151,7 +151,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
151
151
|
version: '0'
|
152
152
|
requirements: []
|
153
153
|
rubyforge_project:
|
154
|
-
rubygems_version: 2.
|
154
|
+
rubygems_version: 2.6.8
|
155
155
|
signing_key:
|
156
156
|
specification_version: 4
|
157
157
|
summary: Burp Scanner upload plugin for the Dradis Framework.
|