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