dradis-burp 3.12.0 → 3.13.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
  SHA1:
3
- metadata.gz: 4b47e6172ec23713350dd1f19ac3881833a7b8c6
4
- data.tar.gz: 8823c7a403ed67a43e92f0a2fcff544ec059ebfc
3
+ metadata.gz: a8034f8e440c364e55c983a3d413fe7111b5d7e1
4
+ data.tar.gz: 0daba2fe9ef55228264d5f3e83d6a88d0ddad849
5
5
  SHA512:
6
- metadata.gz: 2b383351569604421cbbda13575bf89b8b005955cc23ca4335529aff8dc917a78212b5f3bb8b15c18f5cb8d546ee5556f339e77f8ec3cbd3137101ab8570afbd
7
- data.tar.gz: e366429358af292c92675d8bda229e6e8ce1592bd8f37219d2e48eee359ba5ddd701f6ff4a55f4677c9de08f2093d7e6d60db8c6751a1c21949b52233159129c
6
+ metadata.gz: f0960ebadfdbb8096f1bf841fc707cc78290d1feaf8cb619ced75999ff0f41c66ca1b332bd9691a16a5f5683d76d8f234d829bfeaa8c59ebc5383afd5eacf2b1
7
+ data.tar.gz: 68f6554c4c1772bfaa8c0e2ab1d35cd3ddd679bd30dbee7269299fa2242c8ab9f5cf085f3bad2578f4ffb2e38b55ae253b52c880c8f781a52a55f339746c34eb
@@ -1,4 +1,8 @@
1
- ## Dradis Framework 3.12 (XXXX, 2019) ##
1
+ ## Dradis Framework 3.13 (XXX, 2019) ##
2
+
3
+ * Include parsing Burp Html output
4
+
5
+ ## Dradis Framework 3.12 (March, 2019) ##
2
6
 
3
7
  * Make `issue.detail` available at the Evidence level
4
8
 
@@ -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', '~> 1.6'
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!(/&quot;/, '"')
122
+ result.gsub!(/&amp;/, '&')
123
+ result.gsub!(/&lt;/, '<')
124
+ result.gsub!(/&gt;/, '>')
125
+ result.gsub!(/&nbsp;/, ' ')
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
@@ -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>/i) { "\"#{$2.strip}\":#{$1.strip}" }
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/,'&#00;')
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/,'&#00;')
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