ronin-vulns 0.1.0.beta1
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 +7 -0
- data/.document +5 -0
- data/.github/workflows/ruby.yml +31 -0
- data/.gitignore +13 -0
- data/.rspec +1 -0
- data/.ruby-version +1 -0
- data/.yardopts +1 -0
- data/COPYING.txt +165 -0
- data/ChangeLog.md +22 -0
- data/Gemfile +34 -0
- data/README.md +328 -0
- data/Rakefile +34 -0
- data/bin/ronin-vulns +19 -0
- data/data/rfi_test.asp +21 -0
- data/data/rfi_test.aspx +25 -0
- data/data/rfi_test.cfm +27 -0
- data/data/rfi_test.jsp +19 -0
- data/data/rfi_test.php +24 -0
- data/data/rfi_test.pl +25 -0
- data/gemspec.yml +41 -0
- data/lib/ronin/vulns/cli/command.rb +39 -0
- data/lib/ronin/vulns/cli/commands/lfi.rb +145 -0
- data/lib/ronin/vulns/cli/commands/open_redirect.rb +119 -0
- data/lib/ronin/vulns/cli/commands/reflected_xss.rb +99 -0
- data/lib/ronin/vulns/cli/commands/rfi.rb +156 -0
- data/lib/ronin/vulns/cli/commands/scan.rb +316 -0
- data/lib/ronin/vulns/cli/commands/sqli.rb +133 -0
- data/lib/ronin/vulns/cli/commands/ssti.rb +126 -0
- data/lib/ronin/vulns/cli/logging.rb +78 -0
- data/lib/ronin/vulns/cli/web_vuln_command.rb +347 -0
- data/lib/ronin/vulns/cli.rb +45 -0
- data/lib/ronin/vulns/lfi/test_file.rb +91 -0
- data/lib/ronin/vulns/lfi.rb +266 -0
- data/lib/ronin/vulns/open_redirect.rb +118 -0
- data/lib/ronin/vulns/reflected_xss/context.rb +224 -0
- data/lib/ronin/vulns/reflected_xss/test_string.rb +149 -0
- data/lib/ronin/vulns/reflected_xss.rb +184 -0
- data/lib/ronin/vulns/rfi.rb +224 -0
- data/lib/ronin/vulns/root.rb +28 -0
- data/lib/ronin/vulns/sqli/error_pattern.rb +89 -0
- data/lib/ronin/vulns/sqli.rb +397 -0
- data/lib/ronin/vulns/ssti/test_expression.rb +104 -0
- data/lib/ronin/vulns/ssti.rb +203 -0
- data/lib/ronin/vulns/url_scanner.rb +218 -0
- data/lib/ronin/vulns/version.rb +26 -0
- data/lib/ronin/vulns/vuln.rb +49 -0
- data/lib/ronin/vulns/web_vuln/http_request.rb +223 -0
- data/lib/ronin/vulns/web_vuln.rb +774 -0
- data/man/ronin-vulns-lfi.1 +107 -0
- data/man/ronin-vulns-lfi.1.md +80 -0
- data/man/ronin-vulns-open-redirect.1 +98 -0
- data/man/ronin-vulns-open-redirect.1.md +73 -0
- data/man/ronin-vulns-reflected-xss.1 +95 -0
- data/man/ronin-vulns-reflected-xss.1.md +71 -0
- data/man/ronin-vulns-rfi.1 +107 -0
- data/man/ronin-vulns-rfi.1.md +80 -0
- data/man/ronin-vulns-scan.1 +138 -0
- data/man/ronin-vulns-scan.1.md +103 -0
- data/man/ronin-vulns-sqli.1 +107 -0
- data/man/ronin-vulns-sqli.1.md +80 -0
- data/man/ronin-vulns-ssti.1 +99 -0
- data/man/ronin-vulns-ssti.1.md +74 -0
- data/ronin-vulns.gemspec +60 -0
- metadata +161 -0
@@ -0,0 +1,774 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-vulns - A Ruby library for blind vulnerability testing.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-vulns is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# ronin-vulns is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with ronin-vulns. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/vulns/vuln'
|
22
|
+
require 'ronin/vulns/web_vuln/http_request'
|
23
|
+
require 'ronin/support/network/http'
|
24
|
+
|
25
|
+
require 'chars'
|
26
|
+
|
27
|
+
module Ronin
|
28
|
+
module Vulns
|
29
|
+
#
|
30
|
+
# The base class for all web vulnerabilities.
|
31
|
+
#
|
32
|
+
class WebVuln < Vuln
|
33
|
+
|
34
|
+
# The URL to test or exploit.
|
35
|
+
#
|
36
|
+
# @return [URI::HTTP]
|
37
|
+
attr_reader :url
|
38
|
+
|
39
|
+
# The query param to test or exploit.
|
40
|
+
#
|
41
|
+
# @return [String, Symbol, nil]
|
42
|
+
attr_reader :query_param
|
43
|
+
|
44
|
+
# The HTTP Header name to test or exploit.
|
45
|
+
#
|
46
|
+
# @return [String, Symbol, nil]
|
47
|
+
attr_reader :header_name
|
48
|
+
|
49
|
+
# The `Cookie:` param name to test or exploit.
|
50
|
+
#
|
51
|
+
# @return [String, Symbol, nil]
|
52
|
+
attr_reader :cookie_param
|
53
|
+
|
54
|
+
# The form param name to test or exploit.
|
55
|
+
#
|
56
|
+
# @return [String, Symbol, nil]
|
57
|
+
attr_reader :form_param
|
58
|
+
|
59
|
+
# An HTTP session to use for testing the URL.
|
60
|
+
#
|
61
|
+
# @return [Ronin::Support::Network::HTTP, nil]
|
62
|
+
attr_reader :http
|
63
|
+
|
64
|
+
# The HTTP request method for each request.
|
65
|
+
#
|
66
|
+
# @return [:copy, :delete, :get, :head, :lock, :mkcol, :move,
|
67
|
+
# :options, :patch, :post, :propfind, :proppatch, :put,
|
68
|
+
# :trace, :unlock]
|
69
|
+
attr_reader :request_method
|
70
|
+
|
71
|
+
# The query params to send with each request.
|
72
|
+
#
|
73
|
+
# @return [Hash{String,Symbol => String}]
|
74
|
+
attr_reader :query_params
|
75
|
+
|
76
|
+
# The user to authenticate as.
|
77
|
+
#
|
78
|
+
# @return [String, nil]
|
79
|
+
attr_reader :user
|
80
|
+
|
81
|
+
# The password to authenticate with.
|
82
|
+
#
|
83
|
+
# @return [String, nil]
|
84
|
+
attr_reader :password
|
85
|
+
|
86
|
+
# Additional HTTP header names and values to add to the request.
|
87
|
+
#
|
88
|
+
# @return [Hash{Symbol,String => String}, nil]
|
89
|
+
attr_reader :headers
|
90
|
+
|
91
|
+
# Additional `Cookie` header. If a `Hash` is given, it will be converted
|
92
|
+
# to a `String` using `Ronin::Support::Network::HTTP::Cookie`.
|
93
|
+
#
|
94
|
+
# @return [Hash{String => String}, nil]
|
95
|
+
attr_reader :cookie
|
96
|
+
|
97
|
+
# The form data that may be sent in the body of the request.
|
98
|
+
#
|
99
|
+
# @return [Hash, nil]
|
100
|
+
attr_reader :form_data
|
101
|
+
|
102
|
+
# The optional HTTP `Referer` header to send with each request.
|
103
|
+
#
|
104
|
+
# @return [String, nil]
|
105
|
+
attr_reader :referer
|
106
|
+
|
107
|
+
#
|
108
|
+
# Initializes the web vulnerability.
|
109
|
+
#
|
110
|
+
# @param [URI::HTTP, String] url
|
111
|
+
# The URL to test or exploit.
|
112
|
+
#
|
113
|
+
# @param [String, Symbol, nil] query_param
|
114
|
+
# The query param to test or exploit.
|
115
|
+
#
|
116
|
+
# @param [String, Symbol, nil] header_name
|
117
|
+
# The HTTP Header name to test or exploit.
|
118
|
+
#
|
119
|
+
# @param [String, Symbol, nil] cookie_param
|
120
|
+
# The `Cookie:` param name to test or exploit.
|
121
|
+
#
|
122
|
+
# @param [String, Symbol, nil] form_param
|
123
|
+
# The form param name to test or exploit.
|
124
|
+
#
|
125
|
+
# @param [Ronin::Support::Network::HTTP, nil] http
|
126
|
+
# An HTTP session to use for testing the URL.
|
127
|
+
#
|
128
|
+
# @param [:copy, :delete, :get, :head, :lock, :mkcol, :move,
|
129
|
+
# :options, :patch, :post, :propfind, :proppatch, :put,
|
130
|
+
# :trace, :unlock] request_method
|
131
|
+
# The HTTP request mehtod for each request.
|
132
|
+
#
|
133
|
+
# @param [String, nil] user
|
134
|
+
# The user to authenticate as.
|
135
|
+
#
|
136
|
+
# @param [String, nil] password
|
137
|
+
# The password to authenticate with.
|
138
|
+
#
|
139
|
+
# @param [Hash{Symbol,String => String}, nil] headers
|
140
|
+
# Additional HTTP header names and values to add to the request.
|
141
|
+
#
|
142
|
+
# @param [Hash{String => String}, nil] cookie
|
143
|
+
# Additional `Cookie` header. If a `Hash` is given, it will be
|
144
|
+
# converted to a `String` using `Ronin::Support::Network::HTTP::Cookie`.
|
145
|
+
#
|
146
|
+
# @param [Hash, nil] form_data
|
147
|
+
# The form data that may be sent in the body of the request.
|
148
|
+
#
|
149
|
+
# @param [String, nil] referer
|
150
|
+
# The optional HTTP `Referer` header to send with each request.
|
151
|
+
#
|
152
|
+
def initialize(url, query_param: nil,
|
153
|
+
header_name: nil,
|
154
|
+
cookie_param: nil,
|
155
|
+
form_param: nil,
|
156
|
+
# http keyword arguments
|
157
|
+
http: nil,
|
158
|
+
request_method: :get,
|
159
|
+
user: nil,
|
160
|
+
password: nil,
|
161
|
+
headers: nil,
|
162
|
+
cookie: nil,
|
163
|
+
form_data: nil,
|
164
|
+
referer: nil)
|
165
|
+
@url = URI(url)
|
166
|
+
|
167
|
+
@query_param = String(query_param) if query_param
|
168
|
+
@header_name = String(header_name) if header_name
|
169
|
+
@cookie_param = String(cookie_param) if cookie_param
|
170
|
+
@form_param = String(form_param) if form_param
|
171
|
+
|
172
|
+
@http = http || Support::Network::HTTP.connect_uri(@url)
|
173
|
+
|
174
|
+
@request_method = request_method
|
175
|
+
@query_params = @url.query_params
|
176
|
+
@user = user
|
177
|
+
@password = password
|
178
|
+
@headers = headers
|
179
|
+
@cookie = cookie
|
180
|
+
@form_data = form_data
|
181
|
+
@referer = referer
|
182
|
+
end
|
183
|
+
|
184
|
+
#
|
185
|
+
# Scans the query parameters of the URL.
|
186
|
+
#
|
187
|
+
# @param [URI::HTTP, String] url
|
188
|
+
# The URL to scan.
|
189
|
+
#
|
190
|
+
# @param [Array<Symbol, String>, nil] query_params
|
191
|
+
# The query param name(s) to test. If no query param(s) are given,
|
192
|
+
# then all query params in the URL will be scanned.
|
193
|
+
#
|
194
|
+
# @param [Ronin::Support::Network::HTTP, nil] http
|
195
|
+
# An HTTP session to use when testing for web vulnerabilities.
|
196
|
+
#
|
197
|
+
# @yield [vuln]
|
198
|
+
# If a block is given it will be yielded each discovered web
|
199
|
+
# vulnerability.
|
200
|
+
#
|
201
|
+
# @yieldparam [Web] vuln
|
202
|
+
# A discovered web vulnerability in the URL's query params.
|
203
|
+
#
|
204
|
+
# @return [Array<Web>]
|
205
|
+
# All discovered web vulnerabilities.
|
206
|
+
#
|
207
|
+
def self.scan_query_params(url,query_params=nil, http: nil, **kwargs)
|
208
|
+
url = URI(url)
|
209
|
+
http ||= Support::Network::HTTP.connect_uri(url)
|
210
|
+
|
211
|
+
query_params ||= url.query_params.keys
|
212
|
+
vulns = []
|
213
|
+
|
214
|
+
query_params.each do |param|
|
215
|
+
vuln = new(url, query_param: param, http: http, **kwargs)
|
216
|
+
|
217
|
+
if vuln.vulnerable?
|
218
|
+
yield vuln if block_given?
|
219
|
+
vulns << vuln
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
return vulns
|
224
|
+
end
|
225
|
+
|
226
|
+
#
|
227
|
+
# Scans the URL and request headers.
|
228
|
+
#
|
229
|
+
# @param [URI::HTTP, String] url
|
230
|
+
# The URL to scan.
|
231
|
+
#
|
232
|
+
# @param [Array<String, Symbol>] header_names
|
233
|
+
# The header name(s) to test.
|
234
|
+
#
|
235
|
+
# @param [Ronin::Support::Network::HTTP, nil] http
|
236
|
+
# An HTTP session to use when testing for web vulnerabilities.
|
237
|
+
#
|
238
|
+
# @yield [vuln]
|
239
|
+
# If a block is given it will be yielded each discovered web
|
240
|
+
# vulnerability.
|
241
|
+
#
|
242
|
+
# @yieldparam [Web] vuln
|
243
|
+
# A discovered web vulnerability in the URL and one of the header names.
|
244
|
+
#
|
245
|
+
# @return [Array<Web>]
|
246
|
+
# All discovered web vulnerabilities.
|
247
|
+
#
|
248
|
+
def self.scan_headers(url,header_names, http: nil, **kwargs)
|
249
|
+
url = URI(url)
|
250
|
+
http ||= Support::Network::HTTP.connect_uri(url)
|
251
|
+
|
252
|
+
vulns = []
|
253
|
+
|
254
|
+
header_names.each do |header_name|
|
255
|
+
vuln = new(url, header_name: header_name, http: http, **kwargs)
|
256
|
+
|
257
|
+
if vuln.vulnerable?
|
258
|
+
yield vuln if block_given?
|
259
|
+
vulns << vuln
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
return vulns
|
264
|
+
end
|
265
|
+
|
266
|
+
#
|
267
|
+
# Scans the URL and the `Cookie` header params.
|
268
|
+
#
|
269
|
+
# @param [URI::HTTP, String] url
|
270
|
+
# The URL to scan.
|
271
|
+
#
|
272
|
+
# @param [Array<Symbol, String>, nil] cookie_params
|
273
|
+
# The cookie param name(s) to test. If not given, then the URL will be
|
274
|
+
# requested and the `Set-Cookie` params from the response will be
|
275
|
+
# tested instead.
|
276
|
+
#
|
277
|
+
# @param [Ronin::Support::Network::HTTP, nil] http
|
278
|
+
# An HTTP session to use when testing for web vulnerabilities.
|
279
|
+
#
|
280
|
+
# @yield [vuln]
|
281
|
+
# If a block is given it will be yielded each discovered web
|
282
|
+
# vulnerability.
|
283
|
+
#
|
284
|
+
# @yieldparam [Web] vuln
|
285
|
+
# A discovered web vulnerability in the URL and one of the `Cookie`
|
286
|
+
# header params.
|
287
|
+
#
|
288
|
+
# @return [Array<Web>]
|
289
|
+
# All discovered web vulnerabilities.
|
290
|
+
#
|
291
|
+
def self.scan_cookie_params(url,cookie_params=nil, http: nil, **kwargs)
|
292
|
+
url = URI(url)
|
293
|
+
http ||= Support::Network::HTTP.connect_uri(url)
|
294
|
+
|
295
|
+
unless cookie_params
|
296
|
+
cookie_params = Set.new
|
297
|
+
|
298
|
+
http.get_cookies(url.request_uri).each do |set_cookie|
|
299
|
+
cookie_params.merge(set_cookie.params.keys)
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
vulns = []
|
304
|
+
|
305
|
+
cookie_params.each do |cookie_param|
|
306
|
+
vuln = new(url, cookie_param: cookie_param, http: http, **kwargs)
|
307
|
+
|
308
|
+
if vuln.vulnerable?
|
309
|
+
yield vuln if block_given?
|
310
|
+
vulns << vuln
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
return vulns
|
315
|
+
end
|
316
|
+
|
317
|
+
#
|
318
|
+
# Scans the URL and the form params.
|
319
|
+
#
|
320
|
+
# @param [URI::HTTP, String] url
|
321
|
+
# The URL to scan.
|
322
|
+
#
|
323
|
+
# @param [Array<Symbol, String>, nil] form_params
|
324
|
+
# The form param name(s) to test.
|
325
|
+
#
|
326
|
+
# @param [Ronin::Support::Network::HTTP, nil] http
|
327
|
+
# An HTTP session to use when testing for web vulnerabilities.
|
328
|
+
#
|
329
|
+
# @yield [vuln]
|
330
|
+
# If a block is given it will be yielded each discovered web
|
331
|
+
# vulnerability.
|
332
|
+
#
|
333
|
+
# @yieldparam [Web] vuln
|
334
|
+
# A discovered web vulnerability in the URL and one of the form params.
|
335
|
+
#
|
336
|
+
# @return [Array<Web>]
|
337
|
+
# All discovered web vulnerabilities.
|
338
|
+
#
|
339
|
+
def self.scan_form_params(url,form_params, http: nil, **kwargs)
|
340
|
+
url = URI(url)
|
341
|
+
http ||= Support::Network::HTTP.connect_uri(url)
|
342
|
+
|
343
|
+
vulns = []
|
344
|
+
|
345
|
+
form_params.each do |form_param|
|
346
|
+
vuln = new(url, form_param: form_param, http: http, **kwargs)
|
347
|
+
|
348
|
+
if vuln.vulnerable?
|
349
|
+
yield vuln if block_given?
|
350
|
+
vulns << vuln
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
return vulns
|
355
|
+
end
|
356
|
+
|
357
|
+
#
|
358
|
+
# Scans the URL for web vulnerabilities.
|
359
|
+
#
|
360
|
+
# @param [URI::HTTP, String] url
|
361
|
+
# The URL to scan.
|
362
|
+
#
|
363
|
+
# @param [Array<Symbol, String>, true, nil] query_params
|
364
|
+
# The query param name(s) to test.
|
365
|
+
#
|
366
|
+
# @param [Array<Symbol, String>, nil] header_names
|
367
|
+
# The header name(s) to test.
|
368
|
+
#
|
369
|
+
# @param [Array<Symbol, String>, true, nil] cookie_params
|
370
|
+
# The cookie param name(s) to test.
|
371
|
+
#
|
372
|
+
# @param [Array<Symbol, String>, nil] form_params
|
373
|
+
# The form param name(s) to test.
|
374
|
+
#
|
375
|
+
# @param [Ronin::Support::Network::HTTP, nil] http
|
376
|
+
# An HTTP session to use for testing the LFI.
|
377
|
+
#
|
378
|
+
# @param [Hash{Symbol => Object}] kwargs
|
379
|
+
# Additional keyword arguments for {#initialize}.
|
380
|
+
#
|
381
|
+
# @option kwargs [:copy, :delete, :get, :head, :lock, :mkcol, :move,
|
382
|
+
# :options, :patch, :post, :propfind, :proppatch, :put,
|
383
|
+
# :trace, :unlock] :request_method
|
384
|
+
# The HTTP request mehtod for each request.
|
385
|
+
#
|
386
|
+
# @option kwargs [String, nil] :user
|
387
|
+
# The user to authenticate as.
|
388
|
+
#
|
389
|
+
# @option kwargs [String, nil] :password
|
390
|
+
# The password to authenticate with.
|
391
|
+
#
|
392
|
+
# @option kwargs [Hash{String => String}, nil] :headers
|
393
|
+
# Additional headers to send with requests.
|
394
|
+
#
|
395
|
+
# @option kwargs [Hash{String => String}, Ronin::Support::Network::HTTP::Cookie, nil] :cookie
|
396
|
+
# Additional cookie params to send with requests.
|
397
|
+
#
|
398
|
+
# @option kwargs [String, nil] :referer
|
399
|
+
# Optional `Referer` header to send with requests.
|
400
|
+
#
|
401
|
+
# @option kwargs [Hash{String => String}, nil] :form_data
|
402
|
+
# Additional form data to send with requests.
|
403
|
+
#
|
404
|
+
# @yield [vuln]
|
405
|
+
# If a block is given it will be yielded each discovered web
|
406
|
+
# vulnerability.
|
407
|
+
#
|
408
|
+
# @yieldparam [WebVuln] vuln
|
409
|
+
# A discovered web vulnerability in the URL.
|
410
|
+
#
|
411
|
+
# @return [Array<WebVuln>]
|
412
|
+
# All discovered web vulnerabilities.
|
413
|
+
#
|
414
|
+
def self.scan(url, query_params: nil,
|
415
|
+
header_names: nil,
|
416
|
+
cookie_params: nil,
|
417
|
+
form_params: nil,
|
418
|
+
http: nil,
|
419
|
+
**kwargs,
|
420
|
+
&block)
|
421
|
+
url = URI(url)
|
422
|
+
http ||= Support::Network::HTTP.connect_uri(url)
|
423
|
+
vulns = []
|
424
|
+
|
425
|
+
if (query_params.nil? && header_names.nil? && cookie_params.nil? && form_params.nil?)
|
426
|
+
vulns.concat(scan_query_params(url, http: http, **kwargs,&block))
|
427
|
+
else
|
428
|
+
if query_params
|
429
|
+
vulns.concat(
|
430
|
+
case query_params
|
431
|
+
when true
|
432
|
+
scan_query_params(url, http: http, **kwargs,&block)
|
433
|
+
else
|
434
|
+
scan_query_params(url,query_params, http: http, **kwargs,&block)
|
435
|
+
end
|
436
|
+
)
|
437
|
+
end
|
438
|
+
|
439
|
+
if header_names
|
440
|
+
vulns.concat(
|
441
|
+
scan_headers(url,header_names, http: http, **kwargs,&block)
|
442
|
+
)
|
443
|
+
end
|
444
|
+
|
445
|
+
if cookie_params
|
446
|
+
vulns.concat(
|
447
|
+
case cookie_params
|
448
|
+
when true
|
449
|
+
scan_cookie_params(url, http: http, **kwargs,&block)
|
450
|
+
else
|
451
|
+
scan_cookie_params(url,cookie_params, http: http, **kwargs,&block)
|
452
|
+
end
|
453
|
+
)
|
454
|
+
end
|
455
|
+
|
456
|
+
if form_params
|
457
|
+
vulns.concat(
|
458
|
+
scan_form_params(url,form_params, http: http, **kwargs,&block)
|
459
|
+
)
|
460
|
+
end
|
461
|
+
end
|
462
|
+
|
463
|
+
return vulns
|
464
|
+
end
|
465
|
+
|
466
|
+
#
|
467
|
+
# Tests the URL for a web vulnerability and returns the first found
|
468
|
+
# vulnerability.
|
469
|
+
#
|
470
|
+
# @param [URI::HTTP, String] url
|
471
|
+
# The URL to test.
|
472
|
+
#
|
473
|
+
# @param [Hash{Symbol => Object}] kwargs
|
474
|
+
# Additional keyword arguments for {scan}.
|
475
|
+
#
|
476
|
+
# @option kwargs [Array<Symbol, String>, true, nil] :query_params
|
477
|
+
# The query param name(s) to test.
|
478
|
+
#
|
479
|
+
# @option kwargs [Array<Symbol, String>, nil] :header_names
|
480
|
+
# The header name(s) to test.
|
481
|
+
#
|
482
|
+
# @option kwargs [Array<Symbol, String>, true, nil] :cookie_params
|
483
|
+
# The cookie param name(s) to test.
|
484
|
+
#
|
485
|
+
# @option kwargs [Array<Symbol, String>, nil] :form_params
|
486
|
+
# The form param name(s) to test.
|
487
|
+
#
|
488
|
+
# @option kwargs [Ronin::Support::Network::HTTP, nil] :http
|
489
|
+
# An HTTP session to use for testing the LFI.
|
490
|
+
#
|
491
|
+
# @option kwargs [:copy, :delete, :get, :head, :lock, :mkcol, :move,
|
492
|
+
# :options, :patch, :post, :propfind, :proppatch, :put,
|
493
|
+
# :trace, :unlock] :request_method
|
494
|
+
# The HTTP request mehtod for each request.
|
495
|
+
#
|
496
|
+
# @option kwargs [String, nil] :user
|
497
|
+
# The user to authenticate as.
|
498
|
+
#
|
499
|
+
# @option kwargs [String, nil] :password
|
500
|
+
# The password to authenticate with.
|
501
|
+
#
|
502
|
+
# @option kwargs [Hash{String => String}, nil] :headers
|
503
|
+
# Additional headers to send with requests.
|
504
|
+
#
|
505
|
+
# @option kwargs [Hash{String => String}, Ronin::Support::Network::HTTP::Cookie, nil] :cookie
|
506
|
+
# Additional cookie params to send with requests.
|
507
|
+
#
|
508
|
+
# @option kwargs [String, nil] :referer
|
509
|
+
# Optional `Referer` header to send with requests.
|
510
|
+
#
|
511
|
+
# @option kwargs [Hash{String => String}, nil] :form_data
|
512
|
+
# Additional form data to send with requests.
|
513
|
+
#
|
514
|
+
# @return [WebVuln, nil]
|
515
|
+
# The first discovered web vulnerability or `nil` if no vulnerabilities
|
516
|
+
# were discovered.
|
517
|
+
#
|
518
|
+
def self.test(url,**kwargs)
|
519
|
+
scan(url,**kwargs) do |vuln|
|
520
|
+
return vuln
|
521
|
+
end
|
522
|
+
|
523
|
+
return nil
|
524
|
+
end
|
525
|
+
|
526
|
+
#
|
527
|
+
# Performs a normal request for the URL to test.
|
528
|
+
#
|
529
|
+
# @param [Hash{Symbol => Object}] kwargs
|
530
|
+
# Additional keyword arguments for
|
531
|
+
# `Ronin::Support::Network::HTTP#request`.
|
532
|
+
#
|
533
|
+
# @return [Net::HTTPResponse]
|
534
|
+
#
|
535
|
+
def request(**kwargs)
|
536
|
+
@http.request(
|
537
|
+
@request_method, @url.path, user: @user,
|
538
|
+
password: @password,
|
539
|
+
query_params: @query_params,
|
540
|
+
cookie: @cookie,
|
541
|
+
referer: @referer,
|
542
|
+
headers: @headers,
|
543
|
+
form_data: @form_data,
|
544
|
+
**kwargs
|
545
|
+
)
|
546
|
+
end
|
547
|
+
|
548
|
+
#
|
549
|
+
# The exploit query params with the payload injected.
|
550
|
+
#
|
551
|
+
# @param [#to_s] payload
|
552
|
+
# The payload to use for the exploit.
|
553
|
+
#
|
554
|
+
# @return [Hash{String,Symbol => String}]
|
555
|
+
# The {#query_params} with the payload injected. If {#query_param} is
|
556
|
+
# not set, then the unmodified {#query_params} will be returned.
|
557
|
+
#
|
558
|
+
def exploit_query_params(payload)
|
559
|
+
if @query_param
|
560
|
+
if @query_params
|
561
|
+
@query_params.merge(@query_param.to_s => payload)
|
562
|
+
else
|
563
|
+
{@query_param.to_s => payload}
|
564
|
+
end
|
565
|
+
else
|
566
|
+
@query_params
|
567
|
+
end
|
568
|
+
end
|
569
|
+
|
570
|
+
#
|
571
|
+
# The exploit headers with the payload injected.
|
572
|
+
#
|
573
|
+
# @param [#to_s] payload
|
574
|
+
# The payload to use for the exploit.
|
575
|
+
#
|
576
|
+
# @return [Hash{String,Symbol => String}, nil]
|
577
|
+
# The {#headers} with the payload injected. If {#header_name} is not
|
578
|
+
# set, then the unmodified {#headers} will be returned.
|
579
|
+
#
|
580
|
+
def exploit_headers(payload)
|
581
|
+
if @header_name
|
582
|
+
if @headers
|
583
|
+
@headers.merge(@header_name.to_s => payload)
|
584
|
+
else
|
585
|
+
{@header_name.to_s => payload}
|
586
|
+
end
|
587
|
+
else
|
588
|
+
@headers
|
589
|
+
end
|
590
|
+
end
|
591
|
+
|
592
|
+
#
|
593
|
+
# The exploit cookie params with the payload injected.
|
594
|
+
#
|
595
|
+
# @param [#to_s] payload
|
596
|
+
# The payload to use for the exploit.
|
597
|
+
#
|
598
|
+
# @return [Hash{String,Symbol => String}, Ronin::Support::Network::HTTP::Cookie, nil]
|
599
|
+
# The {#cookie} with the payload injected. If {#cookie_param} is not
|
600
|
+
# set, then the unmodified {#cookie} will be returned.
|
601
|
+
#
|
602
|
+
def exploit_cookie(payload)
|
603
|
+
if @cookie_param
|
604
|
+
if @cookie
|
605
|
+
@cookie.merge(@cookie_param.to_s => payload)
|
606
|
+
else
|
607
|
+
{@cookie_param.to_s => payload}
|
608
|
+
end
|
609
|
+
else
|
610
|
+
@cookie
|
611
|
+
end
|
612
|
+
end
|
613
|
+
|
614
|
+
#
|
615
|
+
# The exploit form data with the payload injected.
|
616
|
+
#
|
617
|
+
# @param [#to_s] payload
|
618
|
+
# The payload to use for the exploit.
|
619
|
+
#
|
620
|
+
# @return [Hash{String,Symbol => String}, nil]
|
621
|
+
# The {#form_data} with the payload injected. If {#form_param} is not
|
622
|
+
# set, then the unmodified {#form_data} will be returned.
|
623
|
+
#
|
624
|
+
def exploit_form_data(payload)
|
625
|
+
if @form_param
|
626
|
+
if @form_data
|
627
|
+
@form_data.merge(@form_param.to_s => payload)
|
628
|
+
else
|
629
|
+
{@form_param.to_s => payload}
|
630
|
+
end
|
631
|
+
else
|
632
|
+
@form_data
|
633
|
+
end
|
634
|
+
end
|
635
|
+
|
636
|
+
#
|
637
|
+
# Place holder method for applying additional encoding to the payload.
|
638
|
+
#
|
639
|
+
# @param [#to_s] payload
|
640
|
+
# The payload to encode.
|
641
|
+
#
|
642
|
+
# @return [String]
|
643
|
+
# The encoded payload.
|
644
|
+
#
|
645
|
+
def encode_payload(payload)
|
646
|
+
payload.to_s
|
647
|
+
end
|
648
|
+
|
649
|
+
#
|
650
|
+
# Exploits the web vulnerability by sending an HTTP request.
|
651
|
+
#
|
652
|
+
# @param [String] payload
|
653
|
+
# The payload for the web vulnerability.
|
654
|
+
#
|
655
|
+
# @param [Hash{Symbol => Object}] kwargs
|
656
|
+
# Additional keyword arguments for
|
657
|
+
# `Ronin::Support::Network::HTTP#request`.
|
658
|
+
#
|
659
|
+
# @return [Net::HTTPResponse]
|
660
|
+
#
|
661
|
+
def exploit(payload,**kwargs)
|
662
|
+
payload = encode_payload(payload)
|
663
|
+
|
664
|
+
request(
|
665
|
+
query_params: exploit_query_params(payload),
|
666
|
+
cookie: exploit_cookie(payload),
|
667
|
+
headers: exploit_headers(payload),
|
668
|
+
form_data: exploit_form_data(payload),
|
669
|
+
**kwargs
|
670
|
+
)
|
671
|
+
end
|
672
|
+
|
673
|
+
#
|
674
|
+
# The original value of the vulnerable query param, header, cookie param,
|
675
|
+
# or form param.
|
676
|
+
#
|
677
|
+
# @return [String, nil]
|
678
|
+
#
|
679
|
+
def original_value
|
680
|
+
if @query_param
|
681
|
+
@url.query_params[@query_param]
|
682
|
+
elsif @header_name
|
683
|
+
@headers[@header_name] if @headers
|
684
|
+
elsif @cookie_param
|
685
|
+
@cookie[@cookie_param] if @cookie
|
686
|
+
elsif @form_param
|
687
|
+
@form_data[@form_param] if @form_data
|
688
|
+
end
|
689
|
+
end
|
690
|
+
|
691
|
+
#
|
692
|
+
# Returns a random value.
|
693
|
+
#
|
694
|
+
# @param [Integer] length
|
695
|
+
# The desired length of the String.
|
696
|
+
#
|
697
|
+
# @return [String]
|
698
|
+
# The random value.
|
699
|
+
#
|
700
|
+
def random_value(length=4)
|
701
|
+
Chars::ALPHA.random_string(length)
|
702
|
+
end
|
703
|
+
|
704
|
+
#
|
705
|
+
# Determines if the {#url} is vulnerable.
|
706
|
+
#
|
707
|
+
# @return [Boolean]
|
708
|
+
# Indicates whether the URL is vulnerable.
|
709
|
+
#
|
710
|
+
# @abstract
|
711
|
+
#
|
712
|
+
def vulnerable?
|
713
|
+
raise(NotImplementedError,"#{self.inspect} did not implement ##{__method__}")
|
714
|
+
end
|
715
|
+
|
716
|
+
#
|
717
|
+
# Converts the web vulnerability into a String.
|
718
|
+
#
|
719
|
+
# @return [String]
|
720
|
+
# The String form of {#url}.
|
721
|
+
#
|
722
|
+
def to_s
|
723
|
+
@url.to_s
|
724
|
+
end
|
725
|
+
|
726
|
+
#
|
727
|
+
# Converts the HTTP request to a `curl` command.
|
728
|
+
#
|
729
|
+
# @param [#to_s] payload
|
730
|
+
# The optional payload to include in the `curl` command.
|
731
|
+
#
|
732
|
+
# @return [String]
|
733
|
+
#
|
734
|
+
def to_curl(payload='PAYLOAD')
|
735
|
+
payload = encode_payload(payload)
|
736
|
+
|
737
|
+
HTTPRequest.new(
|
738
|
+
@url, request_method: @request_method,
|
739
|
+
user: @user,
|
740
|
+
password: @password,
|
741
|
+
referer: @referer,
|
742
|
+
query_params: exploit_query_params(payload),
|
743
|
+
cookie: exploit_cookie(payload),
|
744
|
+
headers: exploit_headers(payload),
|
745
|
+
form_data: exploit_form_data(payload)
|
746
|
+
).to_curl
|
747
|
+
end
|
748
|
+
|
749
|
+
#
|
750
|
+
# Converts the HTTP request to a raw HTTP request.
|
751
|
+
#
|
752
|
+
# @param [#to_s] payload
|
753
|
+
# The optional payload to include in the HTTP request.
|
754
|
+
#
|
755
|
+
# @return [String]
|
756
|
+
#
|
757
|
+
def to_http(payload='PAYLOAD')
|
758
|
+
payload = encode_payload(payload)
|
759
|
+
|
760
|
+
HTTPRequest.new(
|
761
|
+
@url, request_method: @request_method,
|
762
|
+
user: @user,
|
763
|
+
password: @password,
|
764
|
+
referer: @referer,
|
765
|
+
query_params: exploit_query_params(payload),
|
766
|
+
cookie: exploit_cookie(payload),
|
767
|
+
headers: exploit_headers(payload),
|
768
|
+
form_data: exploit_form_data(payload)
|
769
|
+
).to_http
|
770
|
+
end
|
771
|
+
|
772
|
+
end
|
773
|
+
end
|
774
|
+
end
|