ronin-vulns 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c80dfbe1e5e0f67d7f6ae908b5514f937004354a809a4e408025ad47f96bf8e7
4
- data.tar.gz: 7af7ed3b5e0abed7e2f0bdf0fc4b774ed568412369f4db44971fd2520d663bd5
3
+ metadata.gz: a034edd07851be44f796a03f47cc5583969734943d5ec23c0073e9dc92f62bd7
4
+ data.tar.gz: 223f844d4ead3779a13d981a6998c46a5cf7f445d5b95044ae30997f546642e5
5
5
  SHA512:
6
- metadata.gz: b06b563a221760c4f58fb55394ccdf01b510ed240b78d51f12dfd7bf122513f42d512f17bf3d5eb0857f61eda1b3db981c2d4583d9bedbb186c108216eec709f
7
- data.tar.gz: 905e0de6182206b232358dab499af99f7849513bb09585e9242445505791dcc8a6c23a381be314f9078cf20848f388ca0c277b6d1647c845c7a56a9c6e10fcec
6
+ metadata.gz: 0db7e162bc9e7294be2d5a89660c3fd3b5892d4e2595b56704bcd8725bccb3041b38a8621c1daab77471236d2a17c1075bdf8ce7f4f233afee43d7277b6afc94
7
+ data.tar.gz: 9a5e1f7513231f294ca5f328f79921dc66c1072b301ccfbf3ac72844b75b492a0ccd76a171d507d82b002824522f79cf6d9e08e7bf99c7624e47375993064176
data/.document CHANGED
@@ -2,4 +2,3 @@ lib/**/*.rb
2
2
  -
3
3
  ChangeLog.md
4
4
  COPYING.txt
5
- man/*.md
data/ChangeLog.md CHANGED
@@ -1,3 +1,26 @@
1
+ ### 0.1.4 / 2023-09-19
2
+
3
+ #### CLI
4
+
5
+ * Improved the performance of `ronin-vulns` commands when scanning multiple URLs
6
+ or a file of URLs by not rebuilding an identical
7
+ {Ronin::Vulns::CLI::WebVulnCommand#scan_kwargs} for each URL.
8
+ * Allow the `--cookie "..."` option to be repeated multiple times and merge the
9
+ cookie strings together.
10
+ * Allow the `--cookie-param NAME=VALUE` option to be used with the
11
+ `--cookie "..."` option and merge the cookie values together.
12
+ * Print vulnerable param names in single quotes.
13
+
14
+ ### 0.1.3 / 2023-07-07
15
+
16
+ * Fixed a bug in {Ronin::Vulns::SSTI.scan} where when called without `escape:`
17
+ it would not return all found vulnerabilities.
18
+ * Fixed a bug in {Ronin::Vulns::SQLI.scan} where repeat requests would be sent
19
+ even if `escape_quote:`, `escape_parens:`, or `terminate:` keyword arguments
20
+ are given.
21
+ * Improved {Ronin::Vulns::ReflectedXSS::Context} to detect when the XSS occurs
22
+ after or *inside of* an HTML comment.
23
+
1
24
  ### 0.1.2 / 2023-03-01
2
25
 
3
26
  * Require `ronin-support` ~> 1.0, >= 1.0.1
data/Gemfile CHANGED
@@ -10,9 +10,9 @@ gem 'jruby-openssl', '~> 0.7', platforms: :jruby
10
10
  # branch: '0.4.0'
11
11
 
12
12
  # Ronin dependencies
13
- # gem 'ronin-support', '~> 1.0', github: "ronin-rb/ronin-support",
13
+ # gem 'ronin-support', '~> 1.0', github: 'ronin-rb/ronin-support',
14
14
  # branch: 'main'
15
- # gem 'ronin-core', '~> 0.1', github: "ronin-rb/ronin-core",
15
+ # gem 'ronin-core', '~> 0.1', github: 'ronin-rb/ronin-core',
16
16
  # branch: 'main'
17
17
 
18
18
  group :development do
data/README.md CHANGED
@@ -9,7 +9,6 @@
9
9
  * [Issues](https://github.com/ronin-rb/ronin-vulns/issues)
10
10
  * [Documentation](https://ronin-rb.dev/docs/ronin-vulns/frames)
11
11
  * [Discord](https://discord.gg/6WAb3PsVX9) |
12
- [Twitter](https://twitter.com/ronin_rb) |
13
12
  [Mastodon](https://infosec.exchange/@ronin_rb)
14
13
 
15
14
  ## Description
@@ -66,14 +66,18 @@ module Ronin
66
66
  value: {
67
67
  type: [:unix, :windows]
68
68
  },
69
- desc: 'Sets the OS to test for'
69
+ desc: 'Sets the OS to test for' do |os|
70
+ scan_kwargs[:os] = os
71
+ end
70
72
 
71
73
  option :depth, short: '-D',
72
74
  value: {
73
75
  type: Integer,
74
76
  usage: 'COUNT'
75
77
  },
76
- desc: 'Sets the directory depth to escape up'
78
+ desc: 'Sets the directory depth to escape up' do |depth|
79
+ scan_kwargs[:depth] = depth
80
+ end
77
81
 
78
82
  option :filter_bypass, short: '-B',
79
83
  value: {
@@ -85,30 +89,14 @@ module Ronin
85
89
  :zlib
86
90
  ]
87
91
  },
88
- desc: 'Sets the filter bypass strategy to use'
92
+ desc: 'Sets the filter bypass strategy to use' do |filter_bypass|
93
+ scan_kwargs[:filter_bypass] = filter_bypass
94
+ end
89
95
 
90
96
  description 'Scans URL(s) for Local File Inclusion (LFI) vulnerabilities'
91
97
 
92
98
  man_page 'ronin-vulns-lfi.1'
93
99
 
94
- #
95
- # Keyword arguments for `Vulns::LFI.scan` and `Vulns::LFI.test`.
96
- #
97
- # @return [Hash{Symbol => Object}]
98
- #
99
- def scan_kwargs
100
- kwargs = super()
101
-
102
- kwargs[:os] = options[:os] if options[:os]
103
- kwargs[:depth] = options[:depth] if options[:depth]
104
-
105
- if options[:filter_bypass]
106
- kwargs[:filter_bypass] = options[:filter_bypass]
107
- end
108
-
109
- return kwargs
110
- end
111
-
112
100
  #
113
101
  # Scans a URL for LFI vulnerabilities.
114
102
  #
@@ -64,25 +64,14 @@ module Ronin
64
64
  type: String,
65
65
  usage: 'URL'
66
66
  },
67
- desc: 'Optional test URL to try to redirect to'
67
+ desc: 'Optional test URL to try to redirect to' do |test_url|
68
+ scan_kwargs[:test_url] = test_url
69
+ end
68
70
 
69
71
  description 'Scans URL(s) for Open Redirect vulnerabilities'
70
72
 
71
73
  man_page 'ronin-vulns-open-redirect.1'
72
74
 
73
- #
74
- # Keyword arguments for `Vulns::OpenRedirect.scan` and
75
- # `Vulns::OpenRedirect.test`.
76
- #
77
- # @return [Hash{Symbol => Object}]
78
- #
79
- def scan_kwargs
80
- kwargs = super()
81
-
82
- kwargs[:test_url] = options[:test_url] if options[:test_url]
83
- return kwargs
84
- end
85
-
86
75
  #
87
76
  # Scans a URL for Open Redirect vulnerabilities.
88
77
  #
@@ -71,7 +71,9 @@ module Ronin
71
71
  'null-byte' => :null_byte
72
72
  }
73
73
  },
74
- desc: 'Optional filter-bypass strategy to use'
74
+ desc: 'Optional filter-bypass strategy to use' do |filter_bypass|
75
+ scan_kwargs[:filter_bypass] = filter_bypass
76
+ end
75
77
 
76
78
  option :script_lang, short: '-S',
77
79
  value: {
@@ -84,42 +86,23 @@ module Ronin
84
86
  'perl' => :perl
85
87
  }
86
88
  },
87
- desc: 'Explicitly specify the scripting language to test for'
89
+ desc: 'Explicitly specify the scripting language to test for' do |script_lang|
90
+ scan_kwargs[:script_lang] = script_lang
91
+ end
88
92
 
89
93
  option :test_script_url, short: '-T',
90
94
  value: {
91
95
  type: String,
92
96
  usage: 'URL'
93
97
  },
94
- desc: 'Use an alternative test script URL'
98
+ desc: 'Use an alternative test script URL' do |test_script_url|
99
+ scan_kwargs[:test_script_url] = test_script_url
100
+ end
95
101
 
96
102
  description 'Scans URL(s) for Remote File Inclusion (RFI) vulnerabilities'
97
103
 
98
104
  man_page 'ronin-vulns-rfi.1'
99
105
 
100
- #
101
- # Keyword arguments for `Vulns::RFI.scan` and `Vulns::RFI.test`.
102
- #
103
- # @return [Hash{Symbol => Object}]
104
- #
105
- def scan_kwargs
106
- kwargs = super()
107
-
108
- if options[:filter_bypass]
109
- kwargs[:filter_bypass] = options[:filter_bypass]
110
- end
111
-
112
- if options[:script_lang]
113
- kwargs[:script_lang] = options[:script_lang]
114
- end
115
-
116
- if options[:test_script_url]
117
- kwargs[:test_script_url] = options[:test_script_url]
118
- end
119
-
120
- return kwargs
121
- end
122
-
123
106
  #
124
107
  # Scans a URL for RFI vulnerabilities.
125
108
  #
@@ -74,13 +74,17 @@ module Ronin
74
74
  option :lfi_os, value: {
75
75
  type: [:unix, :windows]
76
76
  },
77
- desc: 'Sets the OS to test for'
77
+ desc: 'Sets the OS to test for' do |os|
78
+ lfi_kwargs[:os] = os
79
+ end
78
80
 
79
81
  option :lfi_depth, value: {
80
82
  type: Integer,
81
83
  usage: 'COUNT'
82
84
  },
83
- desc: 'Sets the directory depth to escape up'
85
+ desc: 'Sets the directory depth to escape up' do |depth|
86
+ lfi_kwargs[:depth] = depth
87
+ end
84
88
 
85
89
  option :lfi_filter_bypass, value: {
86
90
  type: [
@@ -91,7 +95,9 @@ module Ronin
91
95
  :zlib
92
96
  ]
93
97
  },
94
- desc: 'Sets the filter bypass strategy to use'
98
+ desc: 'Sets the filter bypass strategy to use' do |filter_bypass|
99
+ lfi_kwargs[:filter_bypass] = filter_bypass
100
+ end
95
101
 
96
102
  option :rfi_filter_bypass, value: {
97
103
  type: {
@@ -100,7 +106,9 @@ module Ronin
100
106
  'null-byte' => :null_byte
101
107
  }
102
108
  },
103
- desc: 'Optional filter-bypass strategy to use'
109
+ desc: 'Optional filter-bypass strategy to use' do |filter_bypass|
110
+ rfi_kwargs[:filter_bypass] = filter_bypass
111
+ end
104
112
 
105
113
  option :rfi_script_lang, value: {
106
114
  type: {
@@ -112,33 +120,45 @@ module Ronin
112
120
  'perl' => :perl
113
121
  }
114
122
  },
115
- desc: 'Explicitly specify the scripting language to test for'
123
+ desc: 'Explicitly specify the scripting language to test for' do |script_lang|
124
+ rfi_kwargs[:script_lang] = script_lang
125
+ end
116
126
 
117
127
  option :rfi_test_script_url, value: {
118
128
  type: String,
119
129
  usage: 'URL'
120
130
  },
121
- desc: 'Use an alternative test script URL'
131
+ desc: 'Use an alternative test script URL' do |test_script_url|
132
+ rfi_kwargs[:test_script_url] = test_script_url
133
+ end
122
134
 
123
- option :sqli_escape_quote, desc: 'Escapes quotation marks'
135
+ option :sqli_escape_quote, desc: 'Escapes quotation marks' do
136
+ sqli_kwargs[:escape_quote] = true
137
+ end
124
138
 
125
- option :sqli_escape_parens, desc: 'Escapes parenthesis'
139
+ option :sqli_escape_parens, desc: 'Escapes parenthesis' do
140
+ sqli_kwargs[:escape_parens] = true
141
+ end
126
142
 
127
- option :sqli_terminate, desc: 'Terminates the SQL expression with a --'
143
+ option :sqli_terminate, desc: 'Terminates the SQL expression with a --' do
144
+ sqli_kwargs[:terminate] = true
145
+ end
128
146
 
129
147
  option :ssti_test_expr, value: {
130
148
  type: %r{\A\d+\s*[\*/\+\-]\s*\d+\z},
131
149
  usage: '{X*Y | X/Z | X+Y | X-Y}'
132
150
  },
133
151
  desc: 'Optional numeric test to use' do |expr|
134
- @ssti_test_expr = Vulns::SSTI::TestExpression.parse(expr)
152
+ ssti_kwargs[:test_expr] = Vulns::SSTI::TestExpression.parse(expr)
135
153
  end
136
154
 
137
155
  option :open_redirect_url, value: {
138
156
  type: String,
139
157
  usage: 'URL'
140
158
  },
141
- desc: 'Optional test URL to try to redirect to'
159
+ desc: 'Optional test URL to try to redirect to' do |test_url|
160
+ open_redirect_kwargs[:test_url] = test_url
161
+ end
142
162
 
143
163
  description 'Scans URL(s) for web vulnerabilities'
144
164
 
@@ -151,16 +171,7 @@ module Ronin
151
171
  # @return [Hash{Symbol => Object}]
152
172
  #
153
173
  def lfi_kwargs
154
- kwargs = {}
155
-
156
- kwargs[:os] = options[:lfi_os] if options[:lfi_os]
157
- kwargs[:depth] = options[:lfi_depth] if options[:lfi_depth]
158
-
159
- if options[:lfi_filter_bypass]
160
- kwargs[:filter_bypass] = options[:lfi_filter_bypass]
161
- end
162
-
163
- return kwargs
174
+ scan_kwargs[:lfi] ||= {}
164
175
  end
165
176
 
166
177
  #
@@ -170,21 +181,7 @@ module Ronin
170
181
  # @return [Hash{Symbol => Object}]
171
182
  #
172
183
  def rfi_kwargs
173
- kwargs = {}
174
-
175
- if options[:rfi_filter_bypass]
176
- kwargs[:filter_bypass] = options[:rfi_filter_bypass]
177
- end
178
-
179
- if options[:rfi_script_lang]
180
- kwargs[:script_lang] = options[:rfi_script_lang]
181
- end
182
-
183
- if options[:rfi_test_script_url]
184
- kwargs[:test_script_url] = options[:rfi_test_script_url]
185
- end
186
-
187
- return kwargs
184
+ scan_kwargs[:rfi] ||= {}
188
185
  end
189
186
 
190
187
  #
@@ -194,21 +191,7 @@ module Ronin
194
191
  # @return [Hash{Symbol => Object}]
195
192
  #
196
193
  def sqli_kwargs
197
- kwargs = {}
198
-
199
- if options[:sqli_escape_quote]
200
- kwargs[:escape_quote] = options[:sqli_escape_quote]
201
- end
202
-
203
- if options[:sqli_escape_parens]
204
- kwargs[:escape_parens] = options[:sqli_escape_parens]
205
- end
206
-
207
- if options[:sqli_terminate]
208
- kwargs[:terminate] = options[:sqli_terminate]
209
- end
210
-
211
- return kwargs
194
+ scan_kwargs[:sqli] ||= {}
212
195
  end
213
196
 
214
197
  #
@@ -218,11 +201,7 @@ module Ronin
218
201
  # @return [Hash{Symbol => Object}]
219
202
  #
220
203
  def ssti_kwargs
221
- kwargs = {}
222
-
223
- kwargs[:test_expr] = @ssti_test_expr if @ssti_test_expr
224
-
225
- return kwargs
204
+ scan_kwargs[:ssti] ||= {}
226
205
  end
227
206
 
228
207
  #
@@ -232,13 +211,7 @@ module Ronin
232
211
  # @return [Hash{Symbol => Object}]
233
212
  #
234
213
  def open_redirect_kwargs
235
- kwargs = {}
236
-
237
- if options[:open_redirect_url]
238
- kwargs[:test_url] = options[:open_redirect_url]
239
- end
240
-
241
- return kwargs
214
+ scan_kwargs[:open_redirect] ||= {}
242
215
  end
243
216
 
244
217
  #
@@ -248,26 +221,7 @@ module Ronin
248
221
  # @return [Hash{Symbol => Object}]
249
222
  #
250
223
  def reflected_xss_kwargs
251
- {}
252
- end
253
-
254
- #
255
- # Keyword arguments for `Vulns::URLScanner.scan` and
256
- # `Vulns::URLScanner.test`.
257
- #
258
- # @return [Hash{Symbol => Object}]
259
- #
260
- def scan_kwargs
261
- kwargs = super()
262
-
263
- kwargs[:lfi] = lfi_kwargs
264
- kwargs[:rfi] = rfi_kwargs
265
- kwargs[:sqli] = sqli_kwargs
266
- kwargs[:ssti] = ssti_kwargs
267
- kwargs[:open_redirect] = open_redirect_kwargs
268
- kwargs[:reflected_xss] = reflected_xss_kwargs
269
-
270
- return kwargs
224
+ scan_kwargs[:reflected_xss] ||= {}
271
225
  end
272
226
 
273
227
  #
@@ -61,42 +61,22 @@ module Ronin
61
61
 
62
62
  usage '[options] {URL ... | --input FILE}'
63
63
 
64
- option :escape_quote, short: '-Q',
65
- desc: 'Escapes quotation marks'
64
+ option :escape_quote, short: '-Q', desc: 'Escapes quotation marks' do
65
+ scan_kwargs[:escape_quote] = true
66
+ end
66
67
 
67
- option :escape_parens, short: '-P',
68
- desc: 'Escapes parenthesis'
68
+ option :escape_parens, short: '-P', desc: 'Escapes parenthesis' do
69
+ scan_kwargs[:escape_parens] = true
70
+ end
69
71
 
70
- option :terminate, short: '-T',
71
- desc: 'Terminates the SQL expression with a --'
72
+ option :terminate, short: '-T', desc: 'Terminates the SQL expression with a --' do
73
+ scan_kwargs[:terminate] = true
74
+ end
72
75
 
73
76
  description 'Scans URL(s) for SQL injection (SQLi) vulnerabilities'
74
77
 
75
78
  man_page 'ronin-vulns-sqli.1'
76
79
 
77
- #
78
- # Keyword arguments for `Vulns::SQLI.scan` and `Vulns::SQLI.test`.
79
- #
80
- # @return [Hash{Symbol => Object}]
81
- #
82
- def scan_kwargs
83
- kwargs = super()
84
-
85
- if options[:escape_quote]
86
- kwargs[:escape_quote] = options[:escape_quote]
87
- end
88
-
89
- if options[:escape_parens]
90
- kwargs[:escape_parens] = options[:escape_parens]
91
- end
92
-
93
- if options[:terminate]
94
- kwargs[:terminate] = options[:terminate]
95
- end
96
-
97
- return kwargs
98
- end
99
-
100
80
  #
101
81
  # Scans a URL for SQLi vulnerabilities.
102
82
  #
@@ -67,30 +67,13 @@ module Ronin
67
67
  usage: '{X*Y | X/Z | X+Y | X-Y}'
68
68
  },
69
69
  desc: 'Optional numeric test to use' do |expr|
70
- @test_expr = Vulns::SSTI::TestExpression.parse(expr)
70
+ scan_kwargs[:test_expr] = Vulns::SSTI::TestExpression.parse(expr)
71
71
  end
72
72
 
73
73
  description 'Scans URL(s) for Server Side Template Injection (SSTI) vulnerabilities'
74
74
 
75
75
  man_page 'ronin-vulns-ssti.1'
76
76
 
77
- # The expression to use to test for SSTI.
78
- #
79
- # @return [Vulns::SSTI::TestExpression, nil]
80
- attr_reader :test_expr
81
-
82
- #
83
- # Keyword arguments for `Vulns::SSTI.scan` and `Vulns::SSTI.test`.
84
- #
85
- # @return [Hash{Symbol => Object}]
86
- #
87
- def scan_kwargs
88
- kwargs = super()
89
-
90
- kwargs[:test_expr] = @test_expr if @test_expr
91
- return kwargs
92
- end
93
-
94
77
  #
95
78
  # Scans a URL for SSTI vulnerabilities.
96
79
  #
@@ -60,13 +60,13 @@ module Ronin
60
60
  def log_vuln(vuln)
61
61
  vuln_name = vuln_type(vuln)
62
62
  location = if vuln.query_param
63
- "query param #{vuln.query_param}"
63
+ "query param '#{vuln.query_param}'"
64
64
  elsif vuln.header_name
65
- "Header #{vuln.header_name}"
65
+ "Header '#{vuln.header_name}'"
66
66
  elsif vuln.cookie_param
67
- "Cookie param #{vuln.cookie_param}"
67
+ "Cookie param '#{vuln.cookie_param}'"
68
68
  elsif vuln.form_param
69
- "form param #{vuln.form_param}"
69
+ "form param '#{vuln.form_param}'"
70
70
  end
71
71
 
72
72
  if location
@@ -53,10 +53,7 @@ module Ronin
53
53
  desc: 'Sets an additional header' do |header|
54
54
  name, value = header.split(/:\s*/,2)
55
55
 
56
- # lazy initialize the headers
57
- @headers ||= {}
58
-
59
- @headers[name] = value
56
+ self.headers[name] = value
60
57
  end
61
58
 
62
59
  option :cookie, short: '-C',
@@ -65,7 +62,9 @@ module Ronin
65
62
  usage: 'COOKIE'
66
63
  },
67
64
  desc: 'Sets the raw Cookie header' do |cookie|
68
- @raw_cookie = cookie
65
+ cookie = Support::Network::HTTP::Cookie.parse(cookie)
66
+
67
+ self.cookie.merge!(cookie)
69
68
  end
70
69
 
71
70
  option :cookie_param, short: '-c',
@@ -76,10 +75,7 @@ module Ronin
76
75
  desc: 'Sets an additional cookie param' do |param|
77
76
  name, value = param.split('=',2)
78
77
 
79
- # lazy initialize the cookie
80
- @cookie ||= Support::Network::HTTP::Cookie.new
81
-
82
- @cookie[name] = value
78
+ self.cookie[name] = value
83
79
  end
84
80
 
85
81
  option :referer, short: '-R',
@@ -88,7 +84,7 @@ module Ronin
88
84
  usage: 'URL'
89
85
  },
90
86
  desc: 'Sets the Referer header' do |referer|
91
- @referer = referer
87
+ self.referer = referer
92
88
  end
93
89
 
94
90
  option :form_param, short: '-F',
@@ -99,10 +95,7 @@ module Ronin
99
95
  desc: 'Sets an additional form param' do |param|
100
96
  name, value = param.split('=',2)
101
97
 
102
- # lazy initialize the form data
103
- @form_data ||= {}
104
-
105
- @form_data[name] = value
98
+ self.form_data[name] = value
106
99
  end
107
100
 
108
101
  option :test_query_param, value: {
@@ -110,14 +103,16 @@ module Ronin
110
103
  usage: 'NAME'
111
104
  },
112
105
  desc: 'Tests the URL query param name' do |name|
113
- # lazy initialize the test query params
114
- @test_query_params ||= Set.new
115
-
116
- @test_query_params << name
106
+ case (test_query_params = self.test_query_params)
107
+ when true
108
+ # no-op, test all query params
109
+ when Set
110
+ test_query_params << name
111
+ end
117
112
  end
118
113
 
119
114
  option :test_all_query_params, desc: 'Test all URL query param names' do
120
- @test_all_query_params = true
115
+ self.test_query_params = true
121
116
  end
122
117
 
123
118
  option :test_header_name, value: {
@@ -125,10 +120,7 @@ module Ronin
125
120
  usage: 'NAME'
126
121
  },
127
122
  desc: 'Tests the HTTP Header name' do |name|
128
- # lazy initialize the test heade rnames
129
- @test_header_names ||= Set.new
130
-
131
- @test_header_names << name
123
+ self.test_header_names << name
132
124
  end
133
125
 
134
126
  option :test_cookie_param, value: {
@@ -136,26 +128,25 @@ module Ronin
136
128
  usage: 'NAME'
137
129
  },
138
130
  desc: 'Tests the HTTP Cookie name' do |name|
139
- # lazy initialize the test cookie params
140
- @test_cookie_params ||= Set.new
141
-
142
- @test_cookie_params << name
131
+ case (test_cookie_params = self.test_cookie_params)
132
+ when true
133
+ # no-op, test all query params
134
+ when Set
135
+ test_cookie_params << name
136
+ end
143
137
  end
144
138
 
145
139
  option :test_all_cookie_params, desc: 'Test all Cookie param names' do
146
- @test_all_cookie_params = true
140
+ self.test_cookie_params = true
147
141
  end
148
142
 
149
143
  option :test_form_param, value: {
150
144
  type: String,
151
- usage: 'NAME'
145
+ usage: 'NAME'
152
146
  },
153
- desc: 'Tests the form param name' do |name|
154
- # lazy initialize the test form params
155
- @test_form_params ||= Set.new
156
-
157
- @test_form_params << name
158
- end
147
+ desc: 'Tests the form param name' do |name|
148
+ self.test_form_params << name
149
+ end
159
150
 
160
151
  option :input, short: '-i',
161
152
  value: {
@@ -175,60 +166,11 @@ module Ronin
175
166
  # * `:all` - Find all vulnerabilities for each URL.
176
167
  attr_reader :scan_mode
177
168
 
178
- # Additional headers.
179
- #
180
- # @return [Hash{String => String}, nil]
181
- attr_reader :headers
182
-
183
- # The raw `Cookie` header to send.
184
- #
185
- # @return [String, nil]
186
- attr_reader :raw_cookie
187
-
188
- # The optional `Cookie` header to send.
189
- #
190
- # @return [Ronin::Support::Network::HTTP::Cookie, nil]
191
- attr_reader :cookie
192
-
193
- # The optional `Referer` header to send.
194
- #
195
- # @return [String, nil]
196
- attr_reader :referer
197
-
198
- # Additional form params.
199
- #
200
- # @return [Hash{String => String}, nil]
201
- attr_reader :form_data
202
-
203
- # The URL query params to test.
204
- #
205
- # @return [Set<String>, nil]
206
- attr_reader :test_query_params
207
-
208
- # Indicates whether to test all of the query params of the URL.
209
- #
210
- # @return [Boolean, nil]
211
- attr_reader :test_all_query_params
212
-
213
- # The HTTP Header names to test.
214
- #
215
- # @return [Set<String>, nil]
216
- attr_reader :test_header_names
217
-
218
- # The HTTP Cookie to test.
219
- #
220
- # @return [Set<String>, nil]
221
- attr_reader :test_cookie_params
222
-
223
- # Indicates whether to test all `Cookie` params for the URL.
169
+ # Keywrod arguments that will be used in {#scan_url} and {#test_url} to
170
+ # call {WebVuln.scan} or {WebVuln.test}.
224
171
  #
225
- # @return [Boolean, nil]
226
- attr_reader :test_all_cookie_params
227
-
228
- # The form params to test.
229
- #
230
- # @return [Set<String>, nil]
231
- attr_reader :test_form_params
172
+ # @return [Hash{Symbol => Object}]
173
+ attr_reader :scan_kwargs
232
174
 
233
175
  #
234
176
  # Initializes the command.
@@ -239,7 +181,8 @@ module Ronin
239
181
  def initialize(**kwargs)
240
182
  super(**kwargs)
241
183
 
242
- @scan_mode = :first
184
+ @scan_mode = :first
185
+ @scan_kwargs = {}
243
186
  end
244
187
 
245
188
  #
@@ -308,42 +251,111 @@ module Ronin
308
251
  end
309
252
 
310
253
  #
311
- # The keyword arguments for {WebVuln.scan}.
254
+ # Additional headers.
312
255
  #
313
256
  # @return [Hash{String => String}]
314
- # The keyword arguments.
315
257
  #
316
- def scan_kwargs
317
- kwargs = {}
258
+ def headers
259
+ @scan_kwargs[:headers] ||= {}
260
+ end
261
+
262
+ #
263
+ # The optional `Cookie` header to send.
264
+ #
265
+ # @return [Ronin::Support::Network::HTTP::Cookie]
266
+ #
267
+ def cookie
268
+ @scan_kwargs[:cookie] ||= Support::Network::HTTP::Cookie.new
269
+ end
318
270
 
319
- kwargs[:headers] = @headers if @headers
271
+ #
272
+ # The optional HTTP `Referer` header to send.
273
+ #
274
+ # @return [String, nil]
275
+ #
276
+ def referer
277
+ @scan_kwargs[:referer]
278
+ end
320
279
 
321
- if @raw_cookie
322
- kwargs[:cookie] = @raw_cookie
323
- elsif @cookie
324
- kwargs[:cookie] = @cookie
325
- end
280
+ #
281
+ # Sets the HTTP `Referer` header to send.
282
+ #
283
+ # @param [String, nil] new_referer
284
+ # The new `Referer` header to send.
285
+ #
286
+ # @return [String, nil]
287
+ #
288
+ def referer=(new_referer)
289
+ @scan_kwargs[:referer] = new_referer
290
+ end
326
291
 
327
- kwargs[:referer] = @referer if @referer
328
- kwargs[:form_data] = @form_data if @form_data
292
+ #
293
+ # Additional form params.
294
+ #
295
+ # @return [Hash{String => String}, nil]
296
+ #
297
+ def form_data
298
+ @scan_kwargs[:form_data] ||= {}
299
+ end
329
300
 
330
- if @test_query_params
331
- kwargs[:query_params] = @test_query_params
332
- elsif @test_all_query_params
333
- kwargs[:query_params] = true
334
- end
301
+ #
302
+ # The URL query params to test.
303
+ #
304
+ # @return [Set<String>, true]
305
+ #
306
+ def test_query_params
307
+ @scan_kwargs[:query_params] ||= Set.new
308
+ end
309
+
310
+ #
311
+ # Sets the URL query params to test.
312
+ #
313
+ # @param [Set<String>, true] new_query_params
314
+ # The query params to test.
315
+ #
316
+ # @return [Set<String>, true]
317
+ #
318
+ def test_query_params=(new_query_params)
319
+ @scan_kwargs[:query_params] = new_query_params
320
+ end
335
321
 
336
- kwargs[:header_names] = @test_header_names if @test_header_names
322
+ #
323
+ # The HTTP Header names to test.
324
+ #
325
+ # @return [Set<String>]
326
+ #
327
+ def test_header_names
328
+ @scan_kwargs[:header_names] ||= Set.new
329
+ end
337
330
 
338
- if @test_cookie_params
339
- kwargs[:cookie_params] = @test_cookie_params
340
- elsif @test_all_cookie_params
341
- kwargs[:cookie_params] = true
342
- end
331
+ #
332
+ # The HTTP Cookie to test.
333
+ #
334
+ # @return [Set<String>, true]
335
+ #
336
+ def test_cookie_params
337
+ @scan_kwargs[:cookie_params] ||= Set.new
338
+ end
343
339
 
344
- kwargs[:form_params] = @test_form_params if @test_form_params
340
+ #
341
+ # Sets the HTTP Cookie to test.
342
+ #
343
+ # @param [Set<String>, true] new_cookie_params
344
+ # The new cookie param names to test.
345
+ #
346
+ # @return [Set<String>, true]
347
+ #
348
+ def test_cookie_params=(new_cookie_params)
349
+ @scan_kwargs[:cookie_params] = new_cookie_params
350
+ end
345
351
 
346
- return kwargs
352
+ #
353
+ # The form params to test.
354
+ #
355
+ # @return [Set<String>, nil]
356
+ #
357
+ def test_form_params
358
+ @scan_kwargs[:form_params] ||= Set.new
347
359
  end
348
360
 
349
361
  #
@@ -30,7 +30,7 @@ module Ronin
30
30
 
31
31
  # Where in the HTML the XSS occurs.
32
32
  #
33
- # @return [:double_quoted_attr_value, :single_quoted_attr_value, :unquoted_attr_value, :attr_name, :attr_list, :tag_name, :tag_body]
33
+ # @return [:double_quoted_attr_value, :single_quoted_attr_value, :unquoted_attr_value, :attr_name, :attr_list, :tag_name, :tag_body, :comment]
34
34
  # The context which the XSS occurs in.
35
35
  # * `:tag_body` occurred within a tag's body (ex: `<tag>XSS...</tag>`)
36
36
  # * `:double_quoted_attr_value` - occurred in a double quoted
@@ -44,13 +44,14 @@ module Ronin
44
44
  # * `:attr_list` - occurred in the attribute list
45
45
  # (ex: `<tag XSS>...</tag>`)
46
46
  # * `:tag_name` - occurred in the tag name (ex: `<tagXSS>...</tag>`)
47
+ # * `:comment` - occurred in a comment (ex: `<!-- XSS -->`)
47
48
  #
48
49
  # @api public
49
50
  attr_reader :location
50
51
 
51
52
  # The name of the parent tag which the XSS occurs in.
52
53
  #
53
- # @return [String]
54
+ # @return [String, nil]
54
55
  #
55
56
  # @api public
56
57
  attr_reader :tag
@@ -65,9 +66,9 @@ module Ronin
65
66
  #
66
67
  # Initializes the context.
67
68
  #
68
- # @param [:double_quoted_attr_value, :single_quoted_attr_value, :unquoted_attr_value, :attr_name, :attr_list, :tag_name, :tag_body] location
69
+ # @param [:double_quoted_attr_value, :single_quoted_attr_value, :unquoted_attr_value, :attr_name, :attr_list, :tag_name, :tag_body, :comment] location
69
70
  #
70
- # @param [String] tag
71
+ # @param [String, nil] tag
71
72
  #
72
73
  # @param [String, nil] attr
73
74
  #
@@ -100,6 +101,11 @@ module Ronin
100
101
  # @api private
101
102
  ATTR_LIST = /(?:\s+#{ATTR})*/
102
103
 
104
+ # HTML comment regexp.
105
+ #
106
+ # @api private
107
+ COMMENT = /<![^>]*>/
108
+
103
109
  # HTML tag name regexp.
104
110
  #
105
111
  # @api private
@@ -108,7 +114,7 @@ module Ronin
108
114
  # Regexp matching when an XSS occurs within a tag's inner HTML.
109
115
  #
110
116
  # @api private
111
- IN_TAG_BODY = %r{<(#{TAG_NAME})#{ATTR_LIST}\s*(?:>|/>)[^<>]*\z}
117
+ IN_TAG_BODY = %r{<(#{TAG_NAME})#{ATTR_LIST}\s*(?:>|/>)([^<>]|#{COMMENT})*\z}
112
118
 
113
119
  # Regexp matching when an XSS occurs within a double-quoted attribute
114
120
  # value.
@@ -142,6 +148,11 @@ module Ronin
142
148
  # @api private
143
149
  IN_TAG_NAME = /<(#{TAG_NAME})\z/
144
150
 
151
+ # Regexp matching when an XSS occurs within a comment.
152
+ #
153
+ # @api private
154
+ IN_COMMENT = /<![^>]*\z/
155
+
145
156
  #
146
157
  # Determine the context of the XSS by checking the characters that come
147
158
  # before the given index.
@@ -174,6 +185,8 @@ module Ronin
174
185
  new(:attr_list, tag: match[1])
175
186
  elsif (match = prefix.match(IN_TAG_NAME))
176
187
  new(:tag_name, tag: match[1])
188
+ elsif prefix.match?(IN_COMMENT)
189
+ new(:comment)
177
190
  end
178
191
  end
179
192
 
@@ -193,7 +206,8 @@ module Ronin
193
206
  attr_name: MINIMAL_REQUIRED_CHARS,
194
207
  attr_list: MINIMAL_REQUIRED_CHARS,
195
208
  tag_name: MINIMAL_REQUIRED_CHARS,
196
- tag_body: MINIMAL_REQUIRED_CHARS
209
+ tag_body: MINIMAL_REQUIRED_CHARS,
210
+ comment: MINIMAL_REQUIRED_CHARS
197
211
  }
198
212
 
199
213
  #
@@ -105,6 +105,18 @@ module Ronin
105
105
  # @param [URI::HTTP, String] url
106
106
  # The URL to test or exploit.
107
107
  #
108
+ # @param [Array<Boolean>, Boolean] escape_quote
109
+ # Controls whether to escape a quoted string value. If not specified,
110
+ # with and without quoted string escaping will be tested.
111
+ #
112
+ # @param [Array<Boolean>, Boolean] escape_parens
113
+ # Controls whether to escape parenthesis. If not specified, with and
114
+ # without parenthesis escaping will be tested.
115
+ #
116
+ # @param [Array<Boolean>, Boolean] terminate
117
+ # Controls whether to terminate the SQL statement with `--`.
118
+ # If not specified, with and without `--` terminate will be tested.
119
+ #
108
120
  # @param [Ronin::Support::Network::HTTP, nil] http
109
121
  # An HTTP session to use for testing the URL.
110
122
  #
@@ -115,28 +127,28 @@ module Ronin
115
127
  # If a block is given it will be yielded each discovered SQL injection
116
128
  # vulnerability.
117
129
  #
118
- # @yieldparam [SQLi] sqli
130
+ # @yieldparam [SQLI] sqli
119
131
  # A discovered SQL injection vulnerability in the URL.
120
132
  #
121
- # @return [Array<SQLi>]
133
+ # @return [Array<SQLI>]
122
134
  # All discovered SQL injection vulnerabilities.
123
135
  #
124
- def self.scan(url, http: nil, **kwargs, &block)
136
+ def self.scan(url, escape_quote: [false, true],
137
+ escape_parens: [false, true],
138
+ terminate: [false, true],
139
+ # WebVuln.scan keyword arguments
140
+ http: nil, **kwargs, &block)
125
141
  url = URI(url)
126
142
  http ||= Support::Network::HTTP.connect_uri(url)
127
143
 
128
- escape_quotes = [false, true]
129
- escape_parens = [false, true]
130
- terminations = [false, true]
131
-
132
144
  vulns = []
133
145
 
134
- escape_quotes.each do |escape_quote|
135
- escape_parens.each do |escape_paren|
136
- terminations.each do |terminate|
137
- vulns.concat(super(url, escape_quote: escape_quote,
138
- escape_parens: escape_paren,
139
- terminate: terminate,
146
+ Array(escape_quote).each do |escape_quote_value|
147
+ Array(escape_parens).each do |escape_parens_value|
148
+ Array(terminate).each do |terminate_value|
149
+ vulns.concat(super(url, escape_quote: escape_quote_value,
150
+ escape_parens: escape_parens_value,
151
+ terminate: terminate_value,
140
152
  http: http,
141
153
  **kwargs,
142
154
  &block))
@@ -102,13 +102,13 @@ module Ronin
102
102
  # @param [URI::HTTP, String] url
103
103
  # The URL to scan.
104
104
  #
105
- # @param [Hash{Symbol => Object}] kwargs
106
- # Additional keyword arguments for {#initialize}.
107
- #
108
- # @option kwargs [Proc, nil] :escape
105
+ # @param [Array<Proc>, Proc, nil] escape
109
106
  # The escape method to use. If `escape:` is not given, then all escapes
110
107
  # in {ESCAPES} will be tested..
111
108
  #
109
+ # @param [Hash{Symbol => Object}] kwargs
110
+ # Additional keyword arguments for {#initialize}.
111
+ #
112
112
  # @option kwargs [Array<Symbol, String>, Symbol, String, true, nil] :query_params
113
113
  # The query param name(s) to test.
114
114
  #
@@ -145,14 +145,14 @@ module Ronin
145
145
  # @return [Array<SSTI>]
146
146
  # All discovered SSTI vulnerabilities.
147
147
  #
148
- def self.scan(url, **kwargs,&block)
149
- if kwargs.has_key?(:escape)
150
- super(url, **kwargs, &block)
151
- else
152
- ESCAPES.each do |escape|
153
- super(url, escape: escape, **kwargs, &block)
154
- end
148
+ def self.scan(url, escape: ESCAPES, **kwargs,&block)
149
+ vulns = []
150
+
151
+ Array(escape).each do |escape_char|
152
+ vulns.concat(super(url, escape: escape_char, **kwargs, &block))
155
153
  end
154
+
155
+ return vulns
156
156
  end
157
157
 
158
158
  #
@@ -21,6 +21,6 @@
21
21
  module Ronin
22
22
  module Vulns
23
23
  # The ronin-vulns version
24
- VERSION = '0.1.2'
24
+ VERSION = '0.1.4'
25
25
  end
26
26
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ronin-vulns
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Postmodern
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-03-02 00:00:00.000000000 Z
11
+ date: 2023-09-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ronin-support