ronin-vulns 0.1.2 → 0.1.4

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
  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