ronin-vulns 0.1.3 → 0.1.5

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: b260c485d9272af5724bed43fc2959995463f8b78e276bf669d1bb98740e917c
4
- data.tar.gz: de99077b9d9fe73bd167309af9c7c6d7688bd03a02d2af9bd2fc8eae133aa43a
3
+ metadata.gz: 782fb72c980f9466dd49b736e941d1d4bf092066bdb2894c776f7610bb0ee049
4
+ data.tar.gz: 732c6cf18098e86aa1d600e7607fb8110a903ea76391901977574faff167b550
5
5
  SHA512:
6
- metadata.gz: 1f4ce00d82035a11ade026eb6deee9be1244b499d692e47d4961be3cfc2a2dd9d8c609b6c11c5fab72e454f5ccc60adf9dd6ab7e4ceced5b0df9ea27fc18ec27
7
- data.tar.gz: fb41c677b9eaf56c3cc3fabc028db365061ed98e745dfc3bf942238ebd6c2b642716a2e5dc7f010bb9fa2249112bf4ab66db715d35221783104a3702c694aeea
6
+ metadata.gz: a636b00ea3642dadf7ee2f1c1b4a498f5b8e107d46c7ed64aac115cb1788b395de343c5ac7683eef0b3556128e9466e8228782ae453d337cae46ef0c280369fa
7
+ data.tar.gz: e610ebe869ae47cc6ea5ab6c6cd548838da9873943f3d64317ff4682d36bfa172de79df5fff4a53a8d37936a83ada614d4fdc4c1d374eed08cb51a3f9ab421a0
@@ -12,11 +12,12 @@ jobs:
12
12
  - '3.0'
13
13
  - '3.1'
14
14
  - '3.2'
15
+ - '3.3'
15
16
  # - jruby
16
17
  - truffleruby
17
18
  name: Ruby ${{ matrix.ruby }}
18
19
  steps:
19
- - uses: actions/checkout@v2
20
+ - uses: actions/checkout@v4
20
21
  - name: Set up Ruby
21
22
  uses: ruby/setup-ruby@v1
22
23
  with:
@@ -35,7 +36,7 @@ jobs:
35
36
  rubocop:
36
37
  runs-on: ubuntu-latest
37
38
  steps:
38
- - uses: actions/checkout@v2
39
+ - uses: actions/checkout@v4
39
40
  - name: Set up Ruby
40
41
  uses: ruby/setup-ruby@v1
41
42
  with:
data/ChangeLog.md CHANGED
@@ -1,3 +1,25 @@
1
+ ### 0.1.5 / 2024-06-19
2
+
3
+ * Improve the accuracy of {Ronin::Vulns::OpenRedirect#vulnerable?} when
4
+ detecting open redirects in meta-refresh HTML tags.
5
+ * Match the test URL when it ends with `?...`, `&...`, or `&...`.
6
+ * Detect when the test URL has an additional string appended to it
7
+ (ex: `.html`). The appended string can easily be bypassed by adding a
8
+ `?`, `&`, or `#` character to the end of the test URL.
9
+
10
+ ### 0.1.4 / 2023-09-19
11
+
12
+ #### CLI
13
+
14
+ * Improved the performance of `ronin-vulns` commands when scanning multiple URLs
15
+ or a file of URLs by not rebuilding an identical
16
+ {Ronin::Vulns::CLI::WebVulnCommand#scan_kwargs} for each URL.
17
+ * Allow the `--cookie "..."` option to be repeated multiple times and merge the
18
+ cookie strings together.
19
+ * Allow the `--cookie-param NAME=VALUE` option to be used with the
20
+ `--cookie "..."` option and merge the cookie values together.
21
+ * Print vulnerable param names in single quotes.
22
+
1
23
  ### 0.1.3 / 2023-07-07
2
24
 
3
25
  * Fixed a bug in {Ronin::Vulns::SSTI.scan} where when called without `escape:`
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
  #
@@ -80,7 +80,7 @@ module Ronin
80
80
  when '301', '302', '303', '307', '308'
81
81
  if (locations = response.get_fields('Location'))
82
82
  escaped_test_url = Regexp.escape(@test_url)
83
- regexp = /\A#{escaped_test_url}(?:[\?&].+)?\z/
83
+ regexp = /\A#{escaped_test_url}.*\z/
84
84
 
85
85
  locations.last =~ regexp
86
86
  end
@@ -95,10 +95,34 @@ module Ronin
95
95
  http-equiv\s*=\s*(?: "refresh" | 'refresh' | refresh )\s+
96
96
  content\s*=\s*
97
97
  (?:
98
- "\s*\d+\s*;\s*url\s*=\s*'\s*#{escaped_test_url}\s*'\s*"|
99
- '\s*\d+\s*;\s*url\s*=\s*"\s*#{escaped_test_url}\s*"\s*'|
100
- \s*\d+;url=(?: "#{escaped_test_url}" | '#{escaped_test_url}' )
101
- )\s*
98
+ # content="..."
99
+ "\s*\d+\s*;\s*url\s*=\s*
100
+ (?:
101
+ # content="0; url='...'"
102
+ '\s*#{escaped_test_url}[^'"]*' |
103
+ # content="0; url=..."
104
+ #{escaped_test_url}[^"]*
105
+ )\s*" |
106
+ # content='...'
107
+ '\s*\d+\s*;\s*url\s*=\s*
108
+ (?:
109
+ # content='0; url="..."'
110
+ "\s*#{escaped_test_url}[^"']*" |
111
+ # content='0; url=...'
112
+ #{escaped_test_url}[^']*
113
+ )\s*' |
114
+ # content=...
115
+ \s*\d+;url=(?:
116
+ # content=0;url="..."
117
+ "\s*#{escaped_test_url}[^\s"]*" |
118
+ # content=0;url='...'
119
+ '\s*#{escaped_test_url}[^\s']*' |
120
+ # content=0;url=...
121
+ #{escaped_test_url}[^\s/>]*
122
+ )
123
+ )
124
+ \s*
125
+ # /> or / >
102
126
  (?:/\s*)?>
103
127
  }xi
104
128
 
@@ -296,7 +296,7 @@ module Ronin
296
296
  #
297
297
  def check_for_sql_errors(response)
298
298
  if response.code == '500'
299
- ERROR_PATTERNS.each do |database,error_pattern|
299
+ ERROR_PATTERNS.each_value do |error_pattern|
300
300
  if error_pattern =~ response.body
301
301
  return true
302
302
  end
@@ -30,6 +30,16 @@ module Ronin
30
30
  #
31
31
  # Top-level module which scans a URL for all web vulnerabilities.
32
32
  #
33
+ # ## Examples
34
+ #
35
+ # require 'ronin/vulns/url_scanner'
36
+ #
37
+ # Ronin::Vulns::URLScanner.scan(url) do |vuln|
38
+ # # ...
39
+ # end
40
+ #
41
+ # vuln = Ronin::Vulns::URLScanner.test(url)
42
+ #
33
43
  module URLScanner
34
44
  #
35
45
  # Scans a URL for web vulnerabilities.
@@ -21,6 +21,6 @@
21
21
  module Ronin
22
22
  module Vulns
23
23
  # The ronin-vulns version
24
- VERSION = '0.1.3'
24
+ VERSION = '0.1.5'
25
25
  end
26
26
  end
@@ -1,10 +1,10 @@
1
- .\" Generated by kramdown-man 0.1.8
1
+ .\" Generated by kramdown-man 0.1.9
2
2
  .\" https://github.com/postmodern/kramdown-man#readme
3
3
  .TH ronin-vulns-lfi 1 "May 2022" Ronin "User Manuals"
4
4
  .LP
5
5
  .SH SYNOPSIS
6
6
  .LP
7
- .HP
7
+ .PP
8
8
  \fBronin-vulns lfi\fR \[lB]\fIoptions\fP\[rB] \[lC]\fIURL\fP \.\.\. \[or] \fB--input\fR \fIFILE\fP\[rC]
9
9
  .LP
10
10
  .SH DESCRIPTION
@@ -1,10 +1,10 @@
1
- .\" Generated by kramdown-man 0.1.8
1
+ .\" Generated by kramdown-man 0.1.9
2
2
  .\" https://github.com/postmodern/kramdown-man#readme
3
3
  .TH ronin-vulns-open-redirect 1 "May 2022" Ronin "User Manuals"
4
4
  .LP
5
5
  .SH SYNOPSIS
6
6
  .LP
7
- .HP
7
+ .PP
8
8
  \fBronin-vulns open-redirect\fR \[lB]\fIoptions\fP\[rB] \[lC]\fIURL\fP \.\.\. \[or] \fB--input\fR \fIFILE\fP\[rC]
9
9
  .LP
10
10
  .SH DESCRIPTION
@@ -1,10 +1,10 @@
1
- .\" Generated by kramdown-man 0.1.8
1
+ .\" Generated by kramdown-man 0.1.9
2
2
  .\" https://github.com/postmodern/kramdown-man#readme
3
3
  .TH ronin-vulns-reflected-xss 1 "May 2022" Ronin "User Manuals"
4
4
  .LP
5
5
  .SH SYNOPSIS
6
6
  .LP
7
- .HP
7
+ .PP
8
8
  \fBronin-vulns reflected-xss\fR \[lB]\fIoptions\fP\[rB] \[lC]\fIURL\fP \.\.\. \[or] \fB--input\fR \fIFILE\fP\[rC]
9
9
  .LP
10
10
  .SH DESCRIPTION
@@ -1,10 +1,10 @@
1
- .\" Generated by kramdown-man 0.1.8
1
+ .\" Generated by kramdown-man 0.1.9
2
2
  .\" https://github.com/postmodern/kramdown-man#readme
3
3
  .TH ronin-vulns-rfi 1 "May 2022" Ronin "User Manuals"
4
4
  .LP
5
5
  .SH SYNOPSIS
6
6
  .LP
7
- .HP
7
+ .PP
8
8
  \fBronin-vulns rfi\fR \[lB]\fIoptions\fP\[rB] \[lC]\fIURL\fP \.\.\. \[or] \fB--input\fR \fIFILE\fP\[rC]
9
9
  .LP
10
10
  .SH DESCRIPTION
@@ -82,7 +82,7 @@ Reads URLs from the given \fIFILE\fP\.
82
82
  \fB-B\fR, \fB--filter-bypass\fR \fBdouble-encode\fR\[or]\fBsuffix-escape\fR\[or]\fBnull-byte\fR
83
83
  Optional filter\-bypass strategy to use\.
84
84
  .LP
85
- .HP
85
+ .PP
86
86
  \fB-S\fR, \fB--script-lang\fR \fBasp\|\fRasp\.net\fB\|\fRcoldfusion\fB\|\fRjsp\fB\|\fRphp\fB\|\fRperl\`
87
87
  Explicitly specify the scripting language to test for\.
88
88
  .LP
@@ -1,10 +1,10 @@
1
- .\" Generated by kramdown-man 0.1.8
1
+ .\" Generated by kramdown-man 0.1.9
2
2
  .\" https://github.com/postmodern/kramdown-man#readme
3
3
  .TH ronin-vulns-scan 1 "May 2022" Ronin "User Manuals"
4
4
  .LP
5
5
  .SH SYNOPSIS
6
6
  .LP
7
- .HP
7
+ .PP
8
8
  \fBronin-vulns scan\fR \[lB]\fIoptions\fP\[rB] \[lC]\fIURL\fP \.\.\. \[or] \fB--input\fR \fIFILE\fP\[rC]
9
9
  .LP
10
10
  .SH DESCRIPTION
@@ -113,7 +113,7 @@ Escapes parenthesis\.
113
113
  \fB--sqli-terminate\fR
114
114
  Terminates the SQL expression with a \fB--\fR\.
115
115
  .LP
116
- .HP
116
+ .PP
117
117
  \fB--ssti-test-expr\fR \[lC]\fIX\fP*\fIY\fP \[or] \fIX\fP\[sl]\fIZ\fP \[or] \fIX\fP\[pl]\fIY\fP \[or] \fIX\fP\-\fIY\fP\[rC]
118
118
  Optional numeric test to use\.
119
119
  .LP
@@ -1,10 +1,10 @@
1
- .\" Generated by kramdown-man 0.1.8
1
+ .\" Generated by kramdown-man 0.1.9
2
2
  .\" https://github.com/postmodern/kramdown-man#readme
3
3
  .TH ronin-vulns-sqli 1 "May 2022" Ronin "User Manuals"
4
4
  .LP
5
5
  .SH SYNOPSIS
6
6
  .LP
7
- .HP
7
+ .PP
8
8
  \fBronin-vulns sqli\fR \[lB]\fIoptions\fP\[rB] \[lC]\fIURL\fP \.\.\. \[or] \fB--input\fR \fIFILE\fP\[rC]
9
9
  .LP
10
10
  .SH DESCRIPTION
@@ -1,10 +1,10 @@
1
- .\" Generated by kramdown-man 0.1.8
1
+ .\" Generated by kramdown-man 0.1.9
2
2
  .\" https://github.com/postmodern/kramdown-man#readme
3
3
  .TH ronin-vulns-lfi 1 "May 2022" Ronin "User Manuals"
4
4
  .LP
5
5
  .SH SYNOPSIS
6
6
  .LP
7
- .HP
7
+ .PP
8
8
  \fBronin-vulns lfi\fR \[lB]\fIoptions\fP\[rB] \[lC]\fIURL\fP \.\.\. \[or] \fB--input\fR \fIFILE\fP\[rC]
9
9
  .LP
10
10
  .SH DESCRIPTION
@@ -78,7 +78,7 @@ Tests the form param name\.
78
78
  \fB-i\fR, \fB--input\fR \fIFILE\fP
79
79
  Reads URLs from the given \fIFILE\fP\.
80
80
  .LP
81
- .HP
81
+ .PP
82
82
  \fB-T\fR, \fB--test-expr\fR \[lC]\fIX*Y\fP \[or] \fIX\[sl]Z\fP \[or] \fIX\[pl]Y\fP \[or] \fIX\-Y\fP\[rC]
83
83
  Optional numeric test to use\.
84
84
  .LP
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.3
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Postmodern
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-07-08 00:00:00.000000000 Z
11
+ date: 2024-06-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ronin-support
@@ -159,7 +159,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
159
159
  - !ruby/object:Gem::Version
160
160
  version: '0'
161
161
  requirements: []
162
- rubygems_version: 3.3.26
162
+ rubygems_version: 3.3.27
163
163
  signing_key:
164
164
  specification_version: 4
165
165
  summary: Tests URLs for Local File Inclusion (LFI), Remove File Inclusion (RFI), SQL