dradis-burp 3.12.0 → 3.17.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/issue_template.md +16 -0
- data/.github/pull_request_template.md +36 -0
- data/CHANGELOG.md +27 -7
- data/dradis-burp.gemspec +1 -1
- data/lib/burp/html/issue.rb +157 -0
- data/lib/burp/issue.rb +1 -118
- data/lib/burp/xml/issue.rb +127 -0
- data/lib/dradis-burp.rb +2 -0
- data/lib/dradis/plugins/burp.rb +2 -1
- data/lib/dradis/plugins/burp/engine.rb +13 -2
- data/lib/dradis/plugins/burp/field_processor.rb +6 -2
- data/lib/dradis/plugins/burp/gem_version.rb +1 -1
- data/lib/dradis/plugins/burp/html/importer.rb +144 -0
- data/lib/dradis/plugins/burp/xml/importer.rb +144 -0
- data/lib/tasks/thorfile.rb +12 -3
- data/spec/burp_upload_spec.rb +110 -6
- data/spec/fixtures/files/burp.html +229 -0
- data/spec/fixtures/files/burp_issue_severity.xml +118 -0
- data/templates/evidence.fields +1 -1
- data/templates/html_evidence.fields +13 -0
- data/templates/html_evidence.sample +36 -0
- data/templates/html_evidence.template +50 -0
- data/templates/issue.fields +4 -3
- data/templates/issue.template +4 -0
- metadata +20 -9
- data/lib/dradis/plugins/burp/importer.rb +0 -138
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d11d73abaa8f4ff6693de7df049a1e0ec6301ecb91f535728b683c9e493fbf08
|
4
|
+
data.tar.gz: 790c924c63008c2afefacc270c8afe174254dbd353b8b9881e054025ec676b1e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 19c4ee6c62c14272432688d87142a037db20f59d346835387c406d4d1036293fce093d81337a63f5ba8a0565117ace9d70c48a3b43d120d3ce919a125226fb7c
|
7
|
+
data.tar.gz: f05a95f9515215245f1a0674bed64748b3e85684ee79dbdf4ebc5bfba21ec075d1d519181554fcc4d23b4eac10a53a006aa6e8a1e8b962e6a4e4cb57d9b2a15e
|
@@ -0,0 +1,16 @@
|
|
1
|
+
### Steps to reproduce
|
2
|
+
|
3
|
+
Help us help you, how can we reproduce the problem?
|
4
|
+
|
5
|
+
### Expected behavior
|
6
|
+
Tell us what should happen
|
7
|
+
|
8
|
+
### Actual behavior
|
9
|
+
Tell us what happens instead
|
10
|
+
|
11
|
+
### System configuration
|
12
|
+
**Dradis version**:
|
13
|
+
|
14
|
+
**Ruby version**:
|
15
|
+
|
16
|
+
**OS version**:
|
@@ -0,0 +1,36 @@
|
|
1
|
+
### Summary
|
2
|
+
|
3
|
+
Provide a general description of the code changes in your pull
|
4
|
+
request... were there any bugs you had fixed? If so, mention them. If
|
5
|
+
these bugs have open GitHub issues, be sure to tag them here as well,
|
6
|
+
to keep the conversation linked together.
|
7
|
+
|
8
|
+
|
9
|
+
### Other Information
|
10
|
+
|
11
|
+
If there's anything else that's important and relevant to your pull
|
12
|
+
request, mention that information here. This could include
|
13
|
+
benchmarks, or other information.
|
14
|
+
|
15
|
+
Thanks for contributing to Dradis!
|
16
|
+
|
17
|
+
|
18
|
+
### Copyright assignment
|
19
|
+
|
20
|
+
Collaboration is difficult with commercial closed source but we want
|
21
|
+
to keep as much of the OSS ethos as possible available to users
|
22
|
+
who want to fix it themselves.
|
23
|
+
|
24
|
+
In order to unambiguously own and sell Dradis Framework commercial
|
25
|
+
products, we must have the copyright associated with the entire
|
26
|
+
codebase. Any code you create which is merged must be owned by us.
|
27
|
+
That's not us trying to be a jerks, that's just the way it works.
|
28
|
+
|
29
|
+
Please review the [CONTRIBUTING.md](https://github.com/dradis/dradis-ce/blob/master/CONTRIBUTING.md)
|
30
|
+
file for the details.
|
31
|
+
|
32
|
+
You can delete this section, but the following sentence needs to
|
33
|
+
remain in the PR's description:
|
34
|
+
|
35
|
+
> I assign all rights, including copyright, to any future Dradis
|
36
|
+
> work by myself to Security Roots.
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,26 @@
|
|
1
|
-
## Dradis Framework 3.
|
1
|
+
## Dradis Framework 3.17 (May, 2020) ##
|
2
2
|
|
3
|
-
*
|
3
|
+
* No changes.
|
4
|
+
|
5
|
+
## Dradis Framework 3.16 (February, 2020) ##
|
6
|
+
|
7
|
+
* Update severity fixture for specs.
|
8
|
+
|
9
|
+
## Dradis Framework 3.15 (November, 2019) ##
|
10
|
+
|
11
|
+
* Make `issue.severity` available at the Issue level.
|
12
|
+
|
13
|
+
## Dradis Framework 3.14 (August, 2019) ##
|
14
|
+
|
15
|
+
* No changes.
|
16
|
+
|
17
|
+
## Dradis Framework 3.13 (June, 2019) ##
|
18
|
+
|
19
|
+
* Include parsing Burp Html output.
|
20
|
+
|
21
|
+
## Dradis Framework 3.12 (March, 2019) ##
|
22
|
+
|
23
|
+
* Make `issue.detail` available at the Evidence level.
|
4
24
|
|
5
25
|
## Dradis Framework 3.11 (November, 2018) ##
|
6
26
|
|
@@ -8,17 +28,17 @@
|
|
8
28
|
|
9
29
|
## Dradis Framework 3.10 (August, 2018) ##
|
10
30
|
|
11
|
-
* Adds `references` and `vulnerability_classifications` as available fields
|
31
|
+
* Adds `references` and `vulnerability_classifications` as available fields.
|
12
32
|
|
13
|
-
* Adds `hostname` as a Node property
|
33
|
+
* Adds `hostname` as a Node property.
|
14
34
|
|
15
|
-
* Fixes formatting errors including `<p>`, `<a href="">`, and `<table>` tags
|
35
|
+
* Fixes formatting errors including `<p>`, `<a href="">`, and `<table>` tags.
|
16
36
|
|
17
|
-
* Findings with <type>134217728</type> are not bundled together into one Issue
|
37
|
+
* Findings with <type>134217728</type> are not bundled together into one Issue.
|
18
38
|
|
19
39
|
## Dradis Framework 3.9 (January, 2018) ##
|
20
40
|
|
21
|
-
* Encode content with UTF-8 to avoid incompatible db errors (v3.8.1)
|
41
|
+
* Encode content with UTF-8 to avoid incompatible db errors (v3.8.1).
|
22
42
|
|
23
43
|
## Dradis Framework 3.8 (September, 2017) ##
|
24
44
|
|
data/dradis-burp.gemspec
CHANGED
@@ -27,7 +27,7 @@ Gem::Specification.new do |spec|
|
|
27
27
|
spec.add_dependency 'dradis-plugins', '~> 3.6'
|
28
28
|
spec.add_dependency 'nokogiri', '~> 1.3'
|
29
29
|
|
30
|
-
spec.add_development_dependency 'bundler'
|
30
|
+
spec.add_development_dependency 'bundler'
|
31
31
|
spec.add_development_dependency 'rake', '~> 10.0'
|
32
32
|
spec.add_development_dependency 'rspec-rails'
|
33
33
|
spec.add_development_dependency 'combustion', '~> 0.5.2'
|
@@ -0,0 +1,157 @@
|
|
1
|
+
module Burp
|
2
|
+
module Html
|
3
|
+
# This class represents each of the issue elements in the Burp
|
4
|
+
# Scanner HTML document: all elemennts from a span.BODH0 until the next
|
5
|
+
# span.BODH0 (the next one excluded).
|
6
|
+
#
|
7
|
+
# It provides a convenient way to access the information scattered all over
|
8
|
+
# the HTML.
|
9
|
+
class Issue < ::Burp::Issue
|
10
|
+
# Accepts a Nokogiri::XML::NodeSet
|
11
|
+
def initialize(html)
|
12
|
+
@html = Nokogiri::HTML(html.to_s)
|
13
|
+
end
|
14
|
+
|
15
|
+
# List of supported tags
|
16
|
+
def supported_tags
|
17
|
+
[
|
18
|
+
# tags with contents retrieved from inside the span header
|
19
|
+
:name, :type,
|
20
|
+
|
21
|
+
# tags with contents retrieved following the span header
|
22
|
+
:background, :detail,
|
23
|
+
:references, :remediation_background, :remediation_detail,
|
24
|
+
:request, :request_1, :request_2, :request_3,
|
25
|
+
:response, :response_1, :response_2, :response_3,
|
26
|
+
:vulnerability_classifications
|
27
|
+
] + summary_table_tags
|
28
|
+
end
|
29
|
+
|
30
|
+
def header
|
31
|
+
@header ||= @html.at_css('span')
|
32
|
+
end
|
33
|
+
|
34
|
+
def name
|
35
|
+
@name ||= header.text.gsub(/^\d+\.\S/, '')
|
36
|
+
end
|
37
|
+
|
38
|
+
# Link looks like: https://portswigger.net/kb/issues/00200400_flash-cross-domain-policy
|
39
|
+
# We use that 00200400 as type since in that page it calls it 'Type index'
|
40
|
+
def type
|
41
|
+
@type ||=
|
42
|
+
if header_link = header.at_css('a')
|
43
|
+
header_link.attr('href').to_s[/\/([0-9a-f]+)_.*/, 1].to_i(16)
|
44
|
+
else
|
45
|
+
nil
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# This method is invoked by Ruby when a method that is not defined in this
|
50
|
+
# instance is called.
|
51
|
+
#
|
52
|
+
# In our case we inspect the @method@ parameter and try to find the
|
53
|
+
# corresponding header in our HTML, then return the following text.
|
54
|
+
def method_missing(method, *args)
|
55
|
+
# We could remove this check and return nil for any non-recognized tag.
|
56
|
+
# The problem would be that it would make tricky to debug problems with
|
57
|
+
# typos. For instance: <>.potr would return nil instead of raising an
|
58
|
+
# exception
|
59
|
+
unless supported_tags.include?(method)
|
60
|
+
super
|
61
|
+
return
|
62
|
+
end
|
63
|
+
|
64
|
+
# First we try the h2 headers.
|
65
|
+
translations_table = {
|
66
|
+
background: ['Issue background', 'Issue description'],
|
67
|
+
detail: 'Issue detail',
|
68
|
+
references: 'References',
|
69
|
+
remediation_background: ['Remediation background', 'Issue remediation'],
|
70
|
+
remediation_detail: 'Remediation detail',
|
71
|
+
request: 'Request',
|
72
|
+
request_1: 'Request 1',
|
73
|
+
request_2: 'Request 2',
|
74
|
+
request_3: 'Request 3',
|
75
|
+
response: 'Response',
|
76
|
+
response_1: 'Response 1',
|
77
|
+
response_2: 'Response 2',
|
78
|
+
response_3: 'Response 3',
|
79
|
+
serial_number: 'Serial number',
|
80
|
+
vulnerability_classifications: 'Vulnerability classifications'
|
81
|
+
}
|
82
|
+
|
83
|
+
# look for the h2 headers in the html fragment
|
84
|
+
method_names = translations_table.fetch(method, method.to_s)
|
85
|
+
method_names = [method_names].flatten
|
86
|
+
|
87
|
+
h2 = nil
|
88
|
+
method_names.each do |method_name|
|
89
|
+
h2 = @html.xpath("//h2[text()='#{method_name}']").first
|
90
|
+
break if h2
|
91
|
+
end
|
92
|
+
|
93
|
+
if h2
|
94
|
+
content =
|
95
|
+
if h2.text =~ /^(Request|Response)/
|
96
|
+
cleanup_request_response_html(h2.next_element.inner_html)
|
97
|
+
else
|
98
|
+
cleanup_html(h2.next_element.inner_html)
|
99
|
+
end
|
100
|
+
|
101
|
+
return content
|
102
|
+
end
|
103
|
+
|
104
|
+
# look inside the summary table in the html fragment
|
105
|
+
summary[method]
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
|
110
|
+
# In Request/Response html snippets we don't want to cleanup the whole
|
111
|
+
# html as we ususally do. The snippets may contain html code to be displayed,
|
112
|
+
# and we don't want to convert that to textile.
|
113
|
+
def cleanup_request_response_html(source)
|
114
|
+
result = source.dup
|
115
|
+
|
116
|
+
result.gsub!(/<b>(.*?)<\/b>/, '\1')
|
117
|
+
result.gsub!(/<br>|<\/br>/){"\n"}
|
118
|
+
result.gsub!(/<span.*?>/, '')
|
119
|
+
result.gsub!(/<\/span>/, '')
|
120
|
+
|
121
|
+
result.gsub!(/"/, '"')
|
122
|
+
result.gsub!(/&/, '&')
|
123
|
+
result.gsub!(/</, '<')
|
124
|
+
result.gsub!(/>/, '>')
|
125
|
+
result.gsub!(/ /, ' ')
|
126
|
+
|
127
|
+
result
|
128
|
+
end
|
129
|
+
|
130
|
+
# Returns the summary table in the HTML fragment as a Hash
|
131
|
+
def summary
|
132
|
+
@summary ||= begin
|
133
|
+
@summary = {}
|
134
|
+
h2 = @html.search("h2[text()='Summary']").first
|
135
|
+
return @summary if h2.nil?
|
136
|
+
|
137
|
+
table = h2.next_element
|
138
|
+
|
139
|
+
summary_table_tags.each do |tag|
|
140
|
+
td = table.search("td:starts-with('#{tag.to_s.capitalize}:')").first
|
141
|
+
@summary[tag] = td.next_element.text
|
142
|
+
end
|
143
|
+
|
144
|
+
@summary
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# List of supported tags to obtain from the summary html table
|
149
|
+
def summary_table_tags
|
150
|
+
[
|
151
|
+
:confidence, :host, :path, :severity
|
152
|
+
]
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
data/lib/burp/issue.rb
CHANGED
@@ -2,37 +2,8 @@ module Burp
|
|
2
2
|
# We use this string to replace invalid UTF-8 bytes with.
|
3
3
|
INVALID_UTF_REPLACE = '<?>'
|
4
4
|
|
5
|
-
# This class represents each of the /issues/issue elements in the Burp
|
6
|
-
# Scanner XML document.
|
7
|
-
#
|
8
|
-
# It provides a convenient way to access the information scattered all over
|
9
|
-
# the XML in attributes and nested tags.
|
10
|
-
#
|
11
|
-
# Instead of providing separate methods for each supported property we rely
|
12
|
-
# on Ruby's #method_missing to do most of the work.
|
13
5
|
class Issue
|
14
6
|
|
15
|
-
# Accepts an XML node from Nokogiri::XML.
|
16
|
-
def initialize(xml_node)
|
17
|
-
@xml = xml_node
|
18
|
-
end
|
19
|
-
|
20
|
-
# List of supported tags. They can be attributes, simple descendants or
|
21
|
-
# collections (e.g. <references/>, <tags/>)
|
22
|
-
def supported_tags
|
23
|
-
[
|
24
|
-
# attributes
|
25
|
-
|
26
|
-
# simple tags
|
27
|
-
:serial_number, :type, :name, :host, :path, :location, :severity,
|
28
|
-
:confidence, :background, :remediation_background, :detail,
|
29
|
-
:remediation_detail, :references, :vulnerability_classifications,
|
30
|
-
|
31
|
-
# nested tags
|
32
|
-
:request, :response
|
33
|
-
]
|
34
|
-
end
|
35
|
-
|
36
7
|
# This allows external callers (and specs) to check for implemented
|
37
8
|
# properties
|
38
9
|
def respond_to?(method, include_private=false)
|
@@ -40,57 +11,6 @@ module Burp
|
|
40
11
|
super
|
41
12
|
end
|
42
13
|
|
43
|
-
# This method is invoked by Ruby when a method that is not defined in this
|
44
|
-
# instance is called.
|
45
|
-
#
|
46
|
-
# In our case we inspect the @method@ parameter and try to find the
|
47
|
-
# attribute, simple descendent or collection that it maps to in the XML
|
48
|
-
# tree.
|
49
|
-
def method_missing(method, *args)
|
50
|
-
|
51
|
-
# We could remove this check and return nil for any non-recognized tag.
|
52
|
-
# The problem would be that it would make tricky to debug problems with
|
53
|
-
# typos. For instance: <>.potr would return nil instead of raising an
|
54
|
-
# exception
|
55
|
-
unless supported_tags.include?(method)
|
56
|
-
super
|
57
|
-
return
|
58
|
-
end
|
59
|
-
|
60
|
-
# First we try the attributes. In Ruby we use snake_case, but in XML
|
61
|
-
# CamelCase is used for some attributes
|
62
|
-
translations_table = {
|
63
|
-
:background => 'issueBackground',
|
64
|
-
:detail => 'issueDetail',
|
65
|
-
:remediation_background => 'remediationBackground',
|
66
|
-
:remediation_detail => 'remediationDetail',
|
67
|
-
:vulnerability_classifications => 'vulnerabilityClassifications',
|
68
|
-
:serial_number => 'serialNumber'
|
69
|
-
}
|
70
|
-
|
71
|
-
method_name = translations_table.fetch(method, method.to_s)
|
72
|
-
|
73
|
-
# no attributes in the <issue> node
|
74
|
-
# return @xml.attributes[method_name].value if @xml.attributes.key?(method_name)
|
75
|
-
|
76
|
-
# Then we try simple children tags: name, type, ...
|
77
|
-
tag = @xml.xpath("./#{method_name}").first
|
78
|
-
if tag && !tag.text.blank?
|
79
|
-
if tags_with_html_content.include?(method)
|
80
|
-
return cleanup_html(tag.text)
|
81
|
-
else
|
82
|
-
return tag.text
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
if (['request', 'response'].include?(method_name))
|
87
|
-
requestresponse_child(method_name)
|
88
|
-
else
|
89
|
-
# nothing found, the tag is valid but not present in this ReportItem
|
90
|
-
return nil
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
14
|
private
|
95
15
|
|
96
16
|
def cleanup_html(source)
|
@@ -111,7 +31,7 @@ module Burp
|
|
111
31
|
|
112
32
|
result.gsub!(/<ul>(.*?)<\/ul>/m){|m| "#{ $1 }\n"}
|
113
33
|
result.gsub!(/<li>(.*?)<\/li>/m){|m| "\n* #{ $1 }"}
|
114
|
-
result.gsub!(/<a href=\"(.*?)\">(.*?)<\/a>/
|
34
|
+
result.gsub!(/<a href=\"(.*?)\">(.*?)<\/a>/im) { "\"#{$2.strip}\":#{$1.strip}" }
|
115
35
|
|
116
36
|
result.gsub!(/<table>(.*?)<\/table>/m){|m| "\n\n#{ $1 }\n\n" }
|
117
37
|
result.gsub!(/<tr>(.*?)<\/tr>/m){|m| "|#{ $1 }\n" }
|
@@ -119,42 +39,5 @@ module Burp
|
|
119
39
|
|
120
40
|
result
|
121
41
|
end
|
122
|
-
|
123
|
-
# Some of the values have embedded HTML content that we need to strip
|
124
|
-
def tags_with_html_content
|
125
|
-
[:background, :detail, :remediation_background, :remediation_detail, :references, :vulnerability_classifications]
|
126
|
-
end
|
127
|
-
|
128
|
-
def requestresponse_child(field)
|
129
|
-
return 'n/a' unless @xml.at('requestresponse') && @xml.at("requestresponse/#{field}")
|
130
|
-
|
131
|
-
xml_node = @xml.at("requestresponse/#{field}")
|
132
|
-
result = "[unprocessable #{field}]"
|
133
|
-
|
134
|
-
if xml_node['base64'] == 'true'
|
135
|
-
result = Base64::strict_decode64(xml_node.text)
|
136
|
-
|
137
|
-
# don't pass binary data to the DB.
|
138
|
-
if result =~ /\0/
|
139
|
-
header, _ = result.split("\r\n\r\n")
|
140
|
-
result = header << "\r\n\r\n" << '[Binary Data Not Displayed]'
|
141
|
-
end
|
142
|
-
else
|
143
|
-
result = xml_node.text
|
144
|
-
end
|
145
|
-
|
146
|
-
# Just in case a null byte was left by Burp
|
147
|
-
result.gsub!(/\0/,'�')
|
148
|
-
|
149
|
-
# We truncate the request/response because it can be pretty big.
|
150
|
-
# If it is > 1M MySQL will die when trying to INSERT
|
151
|
-
#
|
152
|
-
# TODO: maybe add a reference to this node's XPATH so the user can go
|
153
|
-
# back to the burp scanner file and look up the original request/response
|
154
|
-
result.truncate(50000, omission: '... (truncated)')
|
155
|
-
|
156
|
-
# Encode the string to UTF-8 to catch invalid bytes.
|
157
|
-
result.encode('utf-8', invalid: :replace, undef: :replace, replace: ::Burp::INVALID_UTF_REPLACE)
|
158
|
-
end
|
159
42
|
end
|
160
43
|
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
module Burp
|
2
|
+
module Xml
|
3
|
+
|
4
|
+
# This class represents each of the /issues/issue elements in the Burp
|
5
|
+
# Scanner XML document.
|
6
|
+
#
|
7
|
+
# It provides a convenient way to access the information scattered all over
|
8
|
+
# the XML in attributes and nested tags.
|
9
|
+
#
|
10
|
+
# Instead of providing separate methods for each supported property we rely
|
11
|
+
# on Ruby's #method_missing to do most of the work.
|
12
|
+
class Issue < ::Burp::Issue
|
13
|
+
|
14
|
+
# Accepts an XML node from Nokogiri::XML.
|
15
|
+
def initialize(xml_node)
|
16
|
+
@xml = xml_node
|
17
|
+
end
|
18
|
+
|
19
|
+
# List of supported tags. They can be attributes, simple descendants or
|
20
|
+
# collections (e.g. <references/>, <tags/>)
|
21
|
+
def supported_tags
|
22
|
+
[
|
23
|
+
# attributes
|
24
|
+
|
25
|
+
# simple tags
|
26
|
+
:background, :confidence, :detail, :host, :location, :name, :path,
|
27
|
+
:references, :remediation_background, :remediation_detail,
|
28
|
+
:serial_number, :severity, :type,
|
29
|
+
:vulnerability_classifications,
|
30
|
+
|
31
|
+
# nested tags
|
32
|
+
:request, :response
|
33
|
+
]
|
34
|
+
end
|
35
|
+
|
36
|
+
# This method is invoked by Ruby when a method that is not defined in this
|
37
|
+
# instance is called.
|
38
|
+
#
|
39
|
+
# In our case we inspect the @method@ parameter and try to find the
|
40
|
+
# attribute, simple descendent or collection that it maps to in the XML
|
41
|
+
# tree.
|
42
|
+
def method_missing(method, *args)
|
43
|
+
|
44
|
+
# We could remove this check and return nil for any non-recognized tag.
|
45
|
+
# The problem would be that it would make tricky to debug problems with
|
46
|
+
# typos. For instance: <>.potr would return nil instead of raising an
|
47
|
+
# exception
|
48
|
+
unless supported_tags.include?(method)
|
49
|
+
super
|
50
|
+
return
|
51
|
+
end
|
52
|
+
|
53
|
+
# First we try the attributes. In Ruby we use snake_case, but in XML
|
54
|
+
# CamelCase is used for some attributes
|
55
|
+
translations_table = {
|
56
|
+
background: 'issueBackground',
|
57
|
+
detail: 'issueDetail',
|
58
|
+
remediation_background: 'remediationBackground',
|
59
|
+
remediation_detail: 'remediationDetail',
|
60
|
+
vulnerability_classifications: 'vulnerabilityClassifications',
|
61
|
+
serial_number: 'serialNumber'
|
62
|
+
}
|
63
|
+
|
64
|
+
method_name = translations_table.fetch(method, method.to_s)
|
65
|
+
|
66
|
+
# no attributes in the <issue> node
|
67
|
+
# return @xml.attributes[method_name].value if @xml.attributes.key?(method_name)
|
68
|
+
|
69
|
+
# Then we try simple children tags: name, type, ...
|
70
|
+
tag = @xml.xpath("./#{method_name}").first
|
71
|
+
if tag && !tag.text.blank?
|
72
|
+
if tags_with_html_content.include?(method)
|
73
|
+
return cleanup_html(tag.text)
|
74
|
+
else
|
75
|
+
return tag.text
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
if (['request', 'response'].include?(method_name))
|
80
|
+
requestresponse_child(method_name)
|
81
|
+
else
|
82
|
+
# nothing found, the tag is valid but not present in this ReportItem
|
83
|
+
return nil
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
# Some of the values have embedded HTML content that we need to strip
|
90
|
+
def tags_with_html_content
|
91
|
+
[:background, :detail, :remediation_background, :remediation_detail, :references, :vulnerability_classifications]
|
92
|
+
end
|
93
|
+
|
94
|
+
def requestresponse_child(field)
|
95
|
+
return 'n/a' unless @xml.at('requestresponse') && @xml.at("requestresponse/#{field}")
|
96
|
+
|
97
|
+
xml_node = @xml.at("requestresponse/#{field}")
|
98
|
+
result = "[unprocessable #{field}]"
|
99
|
+
|
100
|
+
if xml_node['base64'] == 'true'
|
101
|
+
result = Base64::strict_decode64(xml_node.text)
|
102
|
+
|
103
|
+
# don't pass binary data to the DB.
|
104
|
+
if result =~ /\0/
|
105
|
+
header, _ = result.split("\r\n\r\n")
|
106
|
+
result = header << "\r\n\r\n" << '[Binary Data Not Displayed]'
|
107
|
+
end
|
108
|
+
else
|
109
|
+
result = xml_node.text
|
110
|
+
end
|
111
|
+
|
112
|
+
# Just in case a null byte was left by Burp
|
113
|
+
result.gsub!(/\0/,'�')
|
114
|
+
|
115
|
+
# We truncate the request/response because it can be pretty big.
|
116
|
+
# If it is > 1M MySQL will die when trying to INSERT
|
117
|
+
#
|
118
|
+
# TODO: maybe add a reference to this node's XPATH so the user can go
|
119
|
+
# back to the burp scanner file and look up the original request/response
|
120
|
+
result.truncate(50000, omission: '... (truncated)')
|
121
|
+
|
122
|
+
# Encode the string to UTF-8 to catch invalid bytes.
|
123
|
+
result.encode('utf-8', invalid: :replace, undef: :replace, replace: ::Burp::INVALID_UTF_REPLACE)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|