ronin-vulns 0.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/.github/workflows/ruby.yml +31 -0
  4. data/.gitignore +13 -0
  5. data/.rspec +1 -0
  6. data/.ruby-version +1 -0
  7. data/.yardopts +1 -0
  8. data/COPYING.txt +165 -0
  9. data/ChangeLog.md +22 -0
  10. data/Gemfile +34 -0
  11. data/README.md +328 -0
  12. data/Rakefile +34 -0
  13. data/bin/ronin-vulns +19 -0
  14. data/data/rfi_test.asp +21 -0
  15. data/data/rfi_test.aspx +25 -0
  16. data/data/rfi_test.cfm +27 -0
  17. data/data/rfi_test.jsp +19 -0
  18. data/data/rfi_test.php +24 -0
  19. data/data/rfi_test.pl +25 -0
  20. data/gemspec.yml +41 -0
  21. data/lib/ronin/vulns/cli/command.rb +39 -0
  22. data/lib/ronin/vulns/cli/commands/lfi.rb +145 -0
  23. data/lib/ronin/vulns/cli/commands/open_redirect.rb +119 -0
  24. data/lib/ronin/vulns/cli/commands/reflected_xss.rb +99 -0
  25. data/lib/ronin/vulns/cli/commands/rfi.rb +156 -0
  26. data/lib/ronin/vulns/cli/commands/scan.rb +316 -0
  27. data/lib/ronin/vulns/cli/commands/sqli.rb +133 -0
  28. data/lib/ronin/vulns/cli/commands/ssti.rb +126 -0
  29. data/lib/ronin/vulns/cli/logging.rb +78 -0
  30. data/lib/ronin/vulns/cli/web_vuln_command.rb +347 -0
  31. data/lib/ronin/vulns/cli.rb +45 -0
  32. data/lib/ronin/vulns/lfi/test_file.rb +91 -0
  33. data/lib/ronin/vulns/lfi.rb +266 -0
  34. data/lib/ronin/vulns/open_redirect.rb +118 -0
  35. data/lib/ronin/vulns/reflected_xss/context.rb +224 -0
  36. data/lib/ronin/vulns/reflected_xss/test_string.rb +149 -0
  37. data/lib/ronin/vulns/reflected_xss.rb +184 -0
  38. data/lib/ronin/vulns/rfi.rb +224 -0
  39. data/lib/ronin/vulns/root.rb +28 -0
  40. data/lib/ronin/vulns/sqli/error_pattern.rb +89 -0
  41. data/lib/ronin/vulns/sqli.rb +397 -0
  42. data/lib/ronin/vulns/ssti/test_expression.rb +104 -0
  43. data/lib/ronin/vulns/ssti.rb +203 -0
  44. data/lib/ronin/vulns/url_scanner.rb +218 -0
  45. data/lib/ronin/vulns/version.rb +26 -0
  46. data/lib/ronin/vulns/vuln.rb +49 -0
  47. data/lib/ronin/vulns/web_vuln/http_request.rb +223 -0
  48. data/lib/ronin/vulns/web_vuln.rb +774 -0
  49. data/man/ronin-vulns-lfi.1 +107 -0
  50. data/man/ronin-vulns-lfi.1.md +80 -0
  51. data/man/ronin-vulns-open-redirect.1 +98 -0
  52. data/man/ronin-vulns-open-redirect.1.md +73 -0
  53. data/man/ronin-vulns-reflected-xss.1 +95 -0
  54. data/man/ronin-vulns-reflected-xss.1.md +71 -0
  55. data/man/ronin-vulns-rfi.1 +107 -0
  56. data/man/ronin-vulns-rfi.1.md +80 -0
  57. data/man/ronin-vulns-scan.1 +138 -0
  58. data/man/ronin-vulns-scan.1.md +103 -0
  59. data/man/ronin-vulns-sqli.1 +107 -0
  60. data/man/ronin-vulns-sqli.1.md +80 -0
  61. data/man/ronin-vulns-ssti.1 +99 -0
  62. data/man/ronin-vulns-ssti.1.md +74 -0
  63. data/ronin-vulns.gemspec +60 -0
  64. 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