ronin-vulns 0.1.0 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +14 -0
- data/.rubocop.yml +28 -0
- data/ChangeLog.md +17 -1
- data/Gemfile +6 -2
- data/README.md +1 -1
- data/Rakefile +2 -2
- data/bin/ronin-vulns +6 -7
- data/gemspec.yml +1 -1
- data/lib/ronin/vulns/cli/commands/open_redirect.rb +1 -0
- data/lib/ronin/vulns/cli/commands/rfi.rb +1 -1
- data/lib/ronin/vulns/cli/commands/scan.rb +6 -6
- data/lib/ronin/vulns/cli/commands/ssti.rb +2 -1
- data/lib/ronin/vulns/cli/logging.rb +3 -0
- data/lib/ronin/vulns/cli/web_vuln_command.rb +50 -12
- data/lib/ronin/vulns/lfi/test_file.rb +1 -1
- data/lib/ronin/vulns/lfi.rb +6 -7
- data/lib/ronin/vulns/open_redirect.rb +14 -3
- data/lib/ronin/vulns/reflected_xss/context.rb +8 -9
- data/lib/ronin/vulns/reflected_xss/test_string.rb +2 -3
- data/lib/ronin/vulns/reflected_xss.rb +3 -4
- data/lib/ronin/vulns/rfi.rb +2 -2
- data/lib/ronin/vulns/sqli/error_pattern.rb +1 -1
- data/lib/ronin/vulns/sqli.rb +10 -10
- data/lib/ronin/vulns/ssti/test_expression.rb +2 -2
- data/lib/ronin/vulns/ssti.rb +4 -4
- data/lib/ronin/vulns/url_scanner.rb +3 -0
- data/lib/ronin/vulns/version.rb +1 -1
- data/lib/ronin/vulns/vuln.rb +1 -1
- data/lib/ronin/vulns/web_vuln/http_request.rb +3 -3
- data/lib/ronin/vulns/web_vuln.rb +2 -2
- data/ronin-vulns.gemspec +4 -2
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c80dfbe1e5e0f67d7f6ae908b5514f937004354a809a4e408025ad47f96bf8e7
|
4
|
+
data.tar.gz: 7af7ed3b5e0abed7e2f0bdf0fc4b774ed568412369f4db44971fd2520d663bd5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b06b563a221760c4f58fb55394ccdf01b510ed240b78d51f12dfd7bf122513f42d512f17bf3d5eb0857f61eda1b3db981c2d4583d9bedbb186c108216eec709f
|
7
|
+
data.tar.gz: 905e0de6182206b232358dab499af99f7849513bb09585e9242445505791dcc8a6c23a381be314f9078cf20848f388ca0c277b6d1647c845c7a56a9c6e10fcec
|
data/.github/workflows/ruby.yml
CHANGED
@@ -30,3 +30,17 @@ jobs:
|
|
30
30
|
run: bundle install --jobs 4 --retry 3
|
31
31
|
- name: Run tests
|
32
32
|
run: bundle exec rake test
|
33
|
+
|
34
|
+
# rubocop linting
|
35
|
+
rubocop:
|
36
|
+
runs-on: ubuntu-latest
|
37
|
+
steps:
|
38
|
+
- uses: actions/checkout@v2
|
39
|
+
- name: Set up Ruby
|
40
|
+
uses: ruby/setup-ruby@v1
|
41
|
+
with:
|
42
|
+
ruby-version: 3.0
|
43
|
+
- name: Install dependencies
|
44
|
+
run: bundle install --jobs 4 --retry 3
|
45
|
+
- name: Run rubocop
|
46
|
+
run: bundle exec rubocop --parallel
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
AllCops:
|
2
|
+
NewCops: enable
|
3
|
+
SuggestExtensions: false
|
4
|
+
TargetRubyVersion: 3.1
|
5
|
+
|
6
|
+
inherit_gem:
|
7
|
+
rubocop-ronin: rubocop.yml
|
8
|
+
|
9
|
+
# we need to make the branching logic extremely explicit here
|
10
|
+
Lint/DuplicateBranch:
|
11
|
+
Exclude:
|
12
|
+
- 'lib/ronin/vulns/lfi.rb'
|
13
|
+
|
14
|
+
# we need to use eval() in the specs to test the SSTI test expression
|
15
|
+
Security/Eval:
|
16
|
+
Exclude:
|
17
|
+
- 'spec/ssti_spec.rb'
|
18
|
+
|
19
|
+
# we need to call URLScanner.scan with a block
|
20
|
+
Lint/EmptyBlock:
|
21
|
+
Exclude:
|
22
|
+
- 'spec/reflected_xss_spec.rb'
|
23
|
+
- 'spec/url_scanner_spec.rb'
|
24
|
+
|
25
|
+
# Ronin::Vulns::Vuln does not define an #initialize method
|
26
|
+
Lint/MissingSuper:
|
27
|
+
Exclude:
|
28
|
+
- 'lib/ronin/vulns/web_vuln.rb'
|
data/ChangeLog.md
CHANGED
@@ -1,4 +1,20 @@
|
|
1
|
-
### 0.1.
|
1
|
+
### 0.1.2 / 2023-03-01
|
2
|
+
|
3
|
+
* Require `ronin-support` ~> 1.0, >= 1.0.1
|
4
|
+
|
5
|
+
#### CLI
|
6
|
+
|
7
|
+
* Validate that given URLs start with either `http://` or `https://`, and print
|
8
|
+
an error message otherwise.
|
9
|
+
* Print a `No vulnerabilities found` message when no vulnerabilities were
|
10
|
+
discovered.
|
11
|
+
|
12
|
+
### 0.1.1 / 2023-02-02
|
13
|
+
|
14
|
+
* Fixed typo in {Ronin::Vulns::CLI::WebVulnCommand#process_url} which effected
|
15
|
+
the `ronin-vulns lfi` command and others.
|
16
|
+
|
17
|
+
### 0.1.0 / 2023-02-01
|
2
18
|
|
3
19
|
* Initial release:
|
4
20
|
* Require `ruby` >= 3.0.0.
|
data/Gemfile
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
source 'https://rubygems.org'
|
2
4
|
|
3
5
|
gemspec
|
@@ -29,6 +31,8 @@ group :development do
|
|
29
31
|
gem 'yard-spellcheck', require: false
|
30
32
|
|
31
33
|
gem 'dead_end', require: false
|
32
|
-
gem 'sord', require: false
|
33
|
-
gem 'stackprof', require: false
|
34
|
+
gem 'sord', require: false, platform: :mri
|
35
|
+
gem 'stackprof', require: false, platform: :mri
|
36
|
+
gem 'rubocop', require: false, platform: :mri
|
37
|
+
gem 'rubocop-ronin', require: false, platform: :mri
|
34
38
|
end
|
data/README.md
CHANGED
@@ -307,7 +307,7 @@ gem.add_dependency 'ronin-vulns', '~> 0.1'
|
|
307
307
|
|
308
308
|
## License
|
309
309
|
|
310
|
-
Copyright (c) 2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
310
|
+
Copyright (c) 2022-2023 Hal Brodigan (postmodern.mod3 at gmail.com)
|
311
311
|
|
312
312
|
ronin-vulns is free software: you can redistribute it and/or modify
|
313
313
|
it under the terms of the GNU Lesser General Public License as published
|
data/Rakefile
CHANGED
data/bin/ronin-vulns
CHANGED
@@ -1,17 +1,16 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require 'rubygems'
|
4
5
|
|
5
6
|
root = File.expand_path(File.join(File.dirname(__FILE__),'..'))
|
6
7
|
if File.file?(File.join(root,'Gemfile.lock'))
|
7
8
|
Dir.chdir(root) do
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
exit -1
|
14
|
-
end
|
9
|
+
require 'bundler/setup'
|
10
|
+
rescue LoadError => e
|
11
|
+
warn e.message
|
12
|
+
warn "Run `gem install bundler` to install Bundler"
|
13
|
+
exit(-1)
|
15
14
|
end
|
16
15
|
end
|
17
16
|
|
data/gemspec.yml
CHANGED
@@ -98,7 +98,7 @@ module Ronin
|
|
98
98
|
'double-encode' => :double_encode,
|
99
99
|
'suffix-escape' => :suffix_escape,
|
100
100
|
'null-byte' => :null_byte
|
101
|
-
}
|
101
|
+
}
|
102
102
|
},
|
103
103
|
desc: 'Optional filter-bypass strategy to use'
|
104
104
|
|
@@ -127,7 +127,7 @@ module Ronin
|
|
127
127
|
option :sqli_terminate, desc: 'Terminates the SQL expression with a --'
|
128
128
|
|
129
129
|
option :ssti_test_expr, value: {
|
130
|
-
type:
|
130
|
+
type: %r{\A\d+\s*[\*/\+\-]\s*\d+\z},
|
131
131
|
usage: '{X*Y | X/Z | X+Y | X-Y}'
|
132
132
|
},
|
133
133
|
desc: 'Optional numeric test to use' do |expr|
|
@@ -260,10 +260,10 @@ module Ronin
|
|
260
260
|
def scan_kwargs
|
261
261
|
kwargs = super()
|
262
262
|
|
263
|
-
kwargs[:lfi]
|
264
|
-
kwargs[:rfi]
|
265
|
-
kwargs[:sqli]
|
266
|
-
kwargs[:ssti]
|
263
|
+
kwargs[:lfi] = lfi_kwargs
|
264
|
+
kwargs[:rfi] = rfi_kwargs
|
265
|
+
kwargs[:sqli] = sqli_kwargs
|
266
|
+
kwargs[:ssti] = ssti_kwargs
|
267
267
|
kwargs[:open_redirect] = open_redirect_kwargs
|
268
268
|
kwargs[:reflected_xss] = reflected_xss_kwargs
|
269
269
|
|
@@ -63,7 +63,7 @@ module Ronin
|
|
63
63
|
|
64
64
|
option :test_expr, short: '-T',
|
65
65
|
value: {
|
66
|
-
type:
|
66
|
+
type: %r{\A\d+\s*[\*/\+\-]\s*\d+\z},
|
67
67
|
usage: '{X*Y | X/Z | X+Y | X-Y}'
|
68
68
|
},
|
69
69
|
desc: 'Optional numeric test to use' do |expr|
|
@@ -86,6 +86,7 @@ module Ronin
|
|
86
86
|
#
|
87
87
|
def scan_kwargs
|
88
88
|
kwargs = super()
|
89
|
+
|
89
90
|
kwargs[:test_expr] = @test_expr if @test_expr
|
90
91
|
return kwargs
|
91
92
|
end
|
@@ -53,7 +53,9 @@ 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
|
56
57
|
@headers ||= {}
|
58
|
+
|
57
59
|
@headers[name] = value
|
58
60
|
end
|
59
61
|
|
@@ -74,14 +76,16 @@ module Ronin
|
|
74
76
|
desc: 'Sets an additional cookie param' do |param|
|
75
77
|
name, value = param.split('=',2)
|
76
78
|
|
79
|
+
# lazy initialize the cookie
|
77
80
|
@cookie ||= Support::Network::HTTP::Cookie.new
|
81
|
+
|
78
82
|
@cookie[name] = value
|
79
83
|
end
|
80
84
|
|
81
85
|
option :referer, short: '-R',
|
82
86
|
value: {
|
83
87
|
type: String,
|
84
|
-
usage: 'URL'
|
88
|
+
usage: 'URL'
|
85
89
|
},
|
86
90
|
desc: 'Sets the Referer header' do |referer|
|
87
91
|
@referer = referer
|
@@ -95,7 +99,9 @@ module Ronin
|
|
95
99
|
desc: 'Sets an additional form param' do |param|
|
96
100
|
name, value = param.split('=',2)
|
97
101
|
|
102
|
+
# lazy initialize the form data
|
98
103
|
@form_data ||= {}
|
104
|
+
|
99
105
|
@form_data[name] = value
|
100
106
|
end
|
101
107
|
|
@@ -104,7 +110,9 @@ module Ronin
|
|
104
110
|
usage: 'NAME'
|
105
111
|
},
|
106
112
|
desc: 'Tests the URL query param name' do |name|
|
113
|
+
# lazy initialize the test query params
|
107
114
|
@test_query_params ||= Set.new
|
115
|
+
|
108
116
|
@test_query_params << name
|
109
117
|
end
|
110
118
|
|
@@ -117,7 +125,9 @@ module Ronin
|
|
117
125
|
usage: 'NAME'
|
118
126
|
},
|
119
127
|
desc: 'Tests the HTTP Header name' do |name|
|
128
|
+
# lazy initialize the test heade rnames
|
120
129
|
@test_header_names ||= Set.new
|
130
|
+
|
121
131
|
@test_header_names << name
|
122
132
|
end
|
123
133
|
|
@@ -126,7 +136,9 @@ module Ronin
|
|
126
136
|
usage: 'NAME'
|
127
137
|
},
|
128
138
|
desc: 'Tests the HTTP Cookie name' do |name|
|
139
|
+
# lazy initialize the test cookie params
|
129
140
|
@test_cookie_params ||= Set.new
|
141
|
+
|
130
142
|
@test_cookie_params << name
|
131
143
|
end
|
132
144
|
|
@@ -135,11 +147,13 @@ module Ronin
|
|
135
147
|
end
|
136
148
|
|
137
149
|
option :test_form_param, value: {
|
138
|
-
|
150
|
+
type: String,
|
139
151
|
usage: 'NAME'
|
140
|
-
|
152
|
+
},
|
141
153
|
desc: 'Tests the form param name' do |name|
|
154
|
+
# lazy initialize the test form params
|
142
155
|
@test_form_params ||= Set.new
|
156
|
+
|
143
157
|
@test_form_params << name
|
144
158
|
end
|
145
159
|
|
@@ -235,19 +249,27 @@ module Ronin
|
|
235
249
|
# The URL(s) to scan.
|
236
250
|
#
|
237
251
|
def run(*urls)
|
252
|
+
unless (options[:input] || !urls.empty?)
|
253
|
+
print_error "must specify URL(s) or --input"
|
254
|
+
exit(-1)
|
255
|
+
end
|
256
|
+
|
257
|
+
vulns_discovered = false
|
258
|
+
|
238
259
|
if options[:input]
|
239
260
|
File.open(options[:input]) do |file|
|
240
261
|
file.each_line(chomp: true) do |url|
|
241
|
-
process_url(url)
|
262
|
+
vulns_discovered ||= process_url(url)
|
242
263
|
end
|
243
264
|
end
|
244
265
|
elsif !urls.empty?
|
245
266
|
urls.each do |url|
|
246
|
-
process_url(url)
|
267
|
+
vulns_discovered ||= process_url(url)
|
247
268
|
end
|
248
|
-
|
249
|
-
|
250
|
-
|
269
|
+
end
|
270
|
+
|
271
|
+
unless vulns_discovered
|
272
|
+
puts colors.green("No vulnerabilities found")
|
251
273
|
end
|
252
274
|
end
|
253
275
|
|
@@ -257,16 +279,32 @@ module Ronin
|
|
257
279
|
# @param [String] url
|
258
280
|
# A URL to scan.
|
259
281
|
#
|
282
|
+
# @return [Boolean]
|
283
|
+
# Indicates whether a vulnerability was discovered in the URL.
|
284
|
+
#
|
260
285
|
def process_url(url)
|
286
|
+
unless url.start_with?('http://') || url.start_with?('https://')
|
287
|
+
print_error("URL must start with http:// or https://: #{url.inspect}")
|
288
|
+
exit(-1)
|
289
|
+
end
|
290
|
+
|
291
|
+
vuln_discovered = false
|
292
|
+
|
261
293
|
if @scan_mode == :first
|
262
294
|
if (first_vuln = test_url(url))
|
263
|
-
|
295
|
+
log_vuln(first_vuln)
|
296
|
+
|
297
|
+
vuln_discovered = true
|
264
298
|
end
|
265
299
|
else
|
266
300
|
scan_url(url) do |vuln|
|
267
|
-
|
301
|
+
log_vuln(vuln)
|
302
|
+
|
303
|
+
vuln_discovered = true
|
268
304
|
end
|
269
305
|
end
|
306
|
+
|
307
|
+
return vuln_discovered
|
270
308
|
end
|
271
309
|
|
272
310
|
#
|
@@ -295,7 +333,7 @@ module Ronin
|
|
295
333
|
kwargs[:query_params] = true
|
296
334
|
end
|
297
335
|
|
298
|
-
kwargs[:header_names]
|
336
|
+
kwargs[:header_names] = @test_header_names if @test_header_names
|
299
337
|
|
300
338
|
if @test_cookie_params
|
301
339
|
kwargs[:cookie_params] = @test_cookie_params
|
@@ -303,7 +341,7 @@ module Ronin
|
|
303
341
|
kwargs[:cookie_params] = true
|
304
342
|
end
|
305
343
|
|
306
|
-
kwargs[:form_params]
|
344
|
+
kwargs[:form_params] = @test_form_params if @test_form_params
|
307
345
|
|
308
346
|
return kwargs
|
309
347
|
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
#
|
3
3
|
# ronin-vulns - A Ruby library to blind vulnerability testing.
|
4
4
|
#
|
5
|
-
# Copyright (c) 2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
5
|
+
# Copyright (c) 2022-2023 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
6
|
#
|
7
7
|
# ronin-vulns is free software: you can redistribute it and/or modify
|
8
8
|
# it under the terms of the GNU Lesser General Public License as published
|
data/lib/ronin/vulns/lfi.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
#
|
3
3
|
# ronin-vulns - A Ruby library for blind vulnerability testing.
|
4
4
|
#
|
5
|
-
# Copyright (c) 2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
5
|
+
# Copyright (c) 2022-2023 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
6
|
#
|
7
7
|
# ronin-vulns is free software: you can redistribute it and/or modify
|
8
8
|
# it under the terms of the GNU Lesser General Public License as published
|
@@ -57,7 +57,7 @@ module Ronin
|
|
57
57
|
attr_reader :os
|
58
58
|
|
59
59
|
# Optional filter bypass technique to use.
|
60
|
-
#
|
60
|
+
#
|
61
61
|
# @return [:null_byte, :base64, :rot13, :zlib, nil]
|
62
62
|
attr_reader :filter_bypass
|
63
63
|
|
@@ -176,7 +176,7 @@ module Ronin
|
|
176
176
|
"#{@escape_path}#{path[3..]}"
|
177
177
|
elsif @os == :windows && path =~ /\A[A-Z]:/
|
178
178
|
# pass through absolute Windows paths to other drives
|
179
|
-
|
179
|
+
path
|
180
180
|
elsif path.start_with?(@separator)
|
181
181
|
# escape absolute paths
|
182
182
|
"#{@escape_path}#{path[1..]}"
|
@@ -234,10 +234,9 @@ module Ronin
|
|
234
234
|
Crypto.rot(body,-13) =~ @test_file
|
235
235
|
when :zlib
|
236
236
|
body.scan(Text::Patterns::BASE64).any? do |string|
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
end
|
237
|
+
Compression.zlib_inflate(Base64.decode64(string)) =~ @test_file
|
238
|
+
rescue Zlib::DataError
|
239
|
+
# not zlib compressed Base64, ignore
|
241
240
|
end
|
242
241
|
else
|
243
242
|
body =~ @test_file
|
@@ -2,7 +2,7 @@
|
|
2
2
|
#
|
3
3
|
# ronin-vulns - A Ruby library for blind vulnerability testing.
|
4
4
|
#
|
5
|
-
# Copyright (c) 2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
5
|
+
# Copyright (c) 2022-2023 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
6
|
#
|
7
7
|
# ronin-vulns is free software: you can redistribute it and/or modify
|
8
8
|
# it under the terms of the GNU Lesser General Public License as published
|
@@ -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
|
83
|
+
regexp = /\A#{escaped_test_url}(?:[\?&].+)?\z/
|
84
84
|
|
85
85
|
locations.last =~ regexp
|
86
86
|
end
|
@@ -89,7 +89,18 @@ module Ronin
|
|
89
89
|
|
90
90
|
if content_type && content_type.include?('text/html')
|
91
91
|
escaped_test_url = Regexp.escape(CGI.escapeHTML(@test_url))
|
92
|
-
|
92
|
+
|
93
|
+
regexp = %r{
|
94
|
+
<meta\s+
|
95
|
+
http-equiv\s*=\s*(?: "refresh" | 'refresh' | refresh )\s+
|
96
|
+
content\s*=\s*
|
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*
|
102
|
+
(?:/\s*)?>
|
103
|
+
}xi
|
93
104
|
|
94
105
|
response.body =~ regexp
|
95
106
|
end
|
@@ -1,9 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
# frozen_string_literal: true
|
3
2
|
#
|
4
3
|
# ronin-vulns - A Ruby library for blind vulnerability testing.
|
5
4
|
#
|
6
|
-
# Copyright (c) 2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
5
|
+
# Copyright (c) 2022-2023 Hal Brodigan (postmodern.mod3 at gmail.com)
|
7
6
|
#
|
8
7
|
# ronin-vulns is free software: you can redistribute it and/or modify
|
9
8
|
# it under the terms of the GNU Lesser General Public License as published
|
@@ -115,33 +114,33 @@ module Ronin
|
|
115
114
|
# value.
|
116
115
|
#
|
117
116
|
# @api private
|
118
|
-
IN_DOUBLE_QUOTED_ATTR_VALUE =
|
117
|
+
IN_DOUBLE_QUOTED_ATTR_VALUE = /<(#{TAG_NAME})#{ATTR_LIST}\s+(#{ATTR_NAME})\s*=\s*"[^"]+\z/
|
119
118
|
|
120
119
|
# Regexp matching when an XSS occurs within a single-quoted attribute
|
121
120
|
# value.
|
122
121
|
#
|
123
122
|
# @api private
|
124
|
-
IN_SINGLE_QUOTED_ATTR_VALUE =
|
123
|
+
IN_SINGLE_QUOTED_ATTR_VALUE = /<(#{TAG_NAME})#{ATTR_LIST}\s+(#{ATTR_NAME})\s*=\s*'[^']+\z/
|
125
124
|
|
126
125
|
# Regexp matching when an XSS occurs within an unquoted attribute value.
|
127
126
|
#
|
128
127
|
# @api private
|
129
|
-
IN_UNQUOTED_ATTR_VALUE =
|
128
|
+
IN_UNQUOTED_ATTR_VALUE = /<(#{TAG_NAME})#{ATTR_LIST}\s+(#{ATTR_NAME})=[^"'\s]+\z/
|
130
129
|
|
131
130
|
# Regexp matching when an XSS occurs within an attribute's name.
|
132
131
|
#
|
133
132
|
# @api private
|
134
|
-
IN_ATTR_NAME =
|
133
|
+
IN_ATTR_NAME = /<(#{TAG_NAME})#{ATTR_LIST}\s+(#{ATTR_NAME})\z/
|
135
134
|
|
136
135
|
# Regexp matching when an XSS occurs within a tag's attribute list.
|
137
136
|
#
|
138
137
|
# @api private
|
139
|
-
IN_ATTR_LIST =
|
138
|
+
IN_ATTR_LIST = /<(#{TAG_NAME})#{ATTR_LIST}\s+\z/
|
140
139
|
|
141
140
|
# Regexp matching when an XSS occurs within a tag's name.
|
142
141
|
#
|
143
142
|
# @api private
|
144
|
-
IN_TAG_NAME =
|
143
|
+
IN_TAG_NAME = /<(#{TAG_NAME})\z/
|
145
144
|
|
146
145
|
#
|
147
146
|
# Determine the context of the XSS by checking the characters that come
|
@@ -161,7 +160,7 @@ module Ronin
|
|
161
160
|
def self.identify(body,index)
|
162
161
|
prefix = body[0,index]
|
163
162
|
|
164
|
-
if
|
163
|
+
if (match = prefix.match(IN_TAG_BODY))
|
165
164
|
new(:tag_body, tag: match[1])
|
166
165
|
elsif (match = prefix.match(IN_DOUBLE_QUOTED_ATTR_VALUE))
|
167
166
|
new(:double_quoted_attr_value, tag: match[1], attr: match[2])
|
@@ -1,9 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
# frozen_string_literal: true
|
3
2
|
#
|
4
3
|
# ronin-vulns - A Ruby library for blind vulnerability testing.
|
5
4
|
#
|
6
|
-
# Copyright (c) 2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
5
|
+
# Copyright (c) 2022-2023 Hal Brodigan (postmodern.mod3 at gmail.com)
|
7
6
|
#
|
8
7
|
# ronin-vulns is free software: you can redistribute it and/or modify
|
9
8
|
# it under the terms of the GNU Lesser General Public License as published
|
@@ -67,7 +66,7 @@ module Ronin
|
|
67
66
|
'/' => ['%2F'],
|
68
67
|
'<' => ['%3C', '<'],
|
69
68
|
'>' => ['%3E', '>'],
|
70
|
-
'&' => ['%26', '&']
|
69
|
+
'&' => ['%26', '&']
|
71
70
|
}
|
72
71
|
|
73
72
|
#
|
@@ -1,9 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
# frozen_string_literal: true
|
3
2
|
#
|
4
3
|
# ronin-vulns - A Ruby library for blind vulnerability testing.
|
5
4
|
#
|
6
|
-
# Copyright (c) 2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
5
|
+
# Copyright (c) 2022-2023 Hal Brodigan (postmodern.mod3 at gmail.com)
|
7
6
|
#
|
8
7
|
# ronin-vulns is free software: you can redistribute it and/or modify
|
9
8
|
# it under the terms of the GNU Lesser General Public License as published
|
@@ -91,7 +90,7 @@ module Ronin
|
|
91
90
|
# The test string to send.
|
92
91
|
#
|
93
92
|
# @yield [body, match]
|
94
|
-
# If a block is given, it will be passed the response body and the
|
93
|
+
# If a block is given, it will be passed the response body and the
|
95
94
|
# regular expression match data, if the response contains the test
|
96
95
|
# string.
|
97
96
|
#
|
@@ -119,7 +118,7 @@ module Ronin
|
|
119
118
|
# Tests which HTML characters are accepted or escaped/filtered.
|
120
119
|
#
|
121
120
|
# @yield [body, match]
|
122
|
-
# If a block is given, it will be passed the response body and the
|
121
|
+
# If a block is given, it will be passed the response body and the
|
123
122
|
# regular expression match data, if the response contains the test
|
124
123
|
# string.
|
125
124
|
#
|
data/lib/ronin/vulns/rfi.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
#
|
3
3
|
# ronin-vulns - A Ruby library for blind vulnerability testing.
|
4
4
|
#
|
5
|
-
# Copyright (c) 2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
5
|
+
# Copyright (c) 2022-2023 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
6
|
#
|
7
7
|
# ronin-vulns is free software: you can redistribute it and/or modify
|
8
8
|
# it under the terms of the GNU Lesser General Public License as published
|
@@ -65,7 +65,7 @@ module Ronin
|
|
65
65
|
attr_reader :filter_bypass
|
66
66
|
|
67
67
|
# URL of the Remote File Inclusion (RFI) Test script
|
68
|
-
#
|
68
|
+
#
|
69
69
|
# @return [URI::HTTP, String]
|
70
70
|
attr_reader :test_script_url
|
71
71
|
|
@@ -2,7 +2,7 @@
|
|
2
2
|
#
|
3
3
|
# ronin-vulns - A Ruby library for blind vulnerability testing.
|
4
4
|
#
|
5
|
-
# Copyright (c) 2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
5
|
+
# Copyright (c) 2022-2023 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
6
|
#
|
7
7
|
# ronin-vulns is free software: you can redistribute it and/or modify
|
8
8
|
# it under the terms of the GNU Lesser General Public License as published
|
data/lib/ronin/vulns/sqli.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
# frozen_string_literal: true
|
3
2
|
#
|
4
3
|
# ronin-vulns - A Ruby library for blind vulnerability testing.
|
5
4
|
#
|
6
|
-
# Copyright (c) 2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
5
|
+
# Copyright (c) 2022-2023 Hal Brodigan (postmodern.mod3 at gmail.com)
|
7
6
|
#
|
8
7
|
# ronin-vulns is free software: you can redistribute it and/or modify
|
9
8
|
# it under the terms of the GNU Lesser General Public License as published
|
@@ -42,7 +41,7 @@ module Ronin
|
|
42
41
|
attr_reader :escape_quote
|
43
42
|
|
44
43
|
# Specifies whether to escape parenthesis.
|
45
|
-
#
|
44
|
+
#
|
46
45
|
# @return [Boolean]
|
47
46
|
attr_reader :escape_parens
|
48
47
|
|
@@ -205,7 +204,7 @@ module Ronin
|
|
205
204
|
/ERROR: parser: parse error at or near/,
|
206
205
|
/PostgreSQL query failed/,
|
207
206
|
/org\.postgresql\.jdbc/,
|
208
|
-
|
207
|
+
%r{Pdo[\./_\\]Pgsql},
|
209
208
|
/PSQLException/
|
210
209
|
],
|
211
210
|
|
@@ -219,12 +218,12 @@ module Ronin
|
|
219
218
|
/MySqlClient\./,
|
220
219
|
/com\.mysql\.jdbc/,
|
221
220
|
/Zend_Db_(?:Adapter|Statement)_Mysqli_Exception/,
|
222
|
-
|
221
|
+
%r{Pdo[\./_\\]Mysql},
|
223
222
|
/MySqlException/
|
224
223
|
],
|
225
224
|
|
226
225
|
sqlite: ErrorPattern[
|
227
|
-
/
|
226
|
+
%r{SQLite/JDBCDriver},
|
228
227
|
/SQLite\.Exception/,
|
229
228
|
/(Microsoft|System)\.Data\.SQLite\.SQLiteException/,
|
230
229
|
/Warning.*\W(?:sqlite_|SQLite3::)/,
|
@@ -233,7 +232,7 @@ module Ronin
|
|
233
232
|
/sqlite3\.OperationalError:/,
|
234
233
|
/SQLite3::SQLException/,
|
235
234
|
/org\.sqlite\.JDBC/,
|
236
|
-
|
235
|
+
%r{Pdo[\./_\\]Sqlite},
|
237
236
|
/SQLiteException/
|
238
237
|
],
|
239
238
|
|
@@ -254,7 +253,7 @@ module Ronin
|
|
254
253
|
/macromedia\.jdbc\.sqlserver/,
|
255
254
|
/Zend_Db_(?:Adapter|Statement)_Sqlsrv_Exception/,
|
256
255
|
/com\.microsoft\.sqlserver\.jdbc/,
|
257
|
-
|
256
|
+
%r{Pdo[\./_\\](?:Mssql|SqlSrv)},
|
258
257
|
/SQL(?:Srv|Server)Exception/
|
259
258
|
],
|
260
259
|
|
@@ -268,7 +267,7 @@ module Ronin
|
|
268
267
|
/macromedia\.jdbc\.oracle/,
|
269
268
|
/oracle\.jdbc/,
|
270
269
|
/Zend_Db_(?:Adapter|Statement)_Oracle_Exception/,
|
271
|
-
|
270
|
+
%r{Pdo[\./_\\](?:Oracle|OCI)},
|
272
271
|
/OracleException/
|
273
272
|
]
|
274
273
|
}
|
@@ -304,7 +303,7 @@ module Ronin
|
|
304
303
|
# @api private
|
305
304
|
#
|
306
305
|
def random_id
|
307
|
-
rand(8_999)
|
306
|
+
rand(8_999..9999)
|
308
307
|
end
|
309
308
|
|
310
309
|
#
|
@@ -317,6 +316,7 @@ module Ronin
|
|
317
316
|
#
|
318
317
|
def test_or_true_and_false
|
319
318
|
id = random_id
|
319
|
+
|
320
320
|
response1 = exploit("OR #{id}=#{id}")
|
321
321
|
response2 = exploit("AND #{random_id}=#{random_id}")
|
322
322
|
|
@@ -2,7 +2,7 @@
|
|
2
2
|
#
|
3
3
|
# ronin-vulns - A Ruby library for blind vulnerability testing.
|
4
4
|
#
|
5
|
-
# Copyright (c) 2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
5
|
+
# Copyright (c) 2022-2023 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
6
|
#
|
7
7
|
# ronin-vulns is free software: you can redistribute it and/or modify
|
8
8
|
# it under the terms of the GNU Lesser General Public License as published
|
@@ -68,7 +68,7 @@ module Ronin
|
|
68
68
|
# Could not parse the test expression.
|
69
69
|
#
|
70
70
|
def self.parse(string)
|
71
|
-
unless (match = string.match(
|
71
|
+
unless (match = string.match(%r{\A(\d+)\s*([\*/\+\-])\s*(\d+)\z}))
|
72
72
|
raise(ArgumentError,"could not parse the expression: #{string.inspect}")
|
73
73
|
end
|
74
74
|
|
data/lib/ronin/vulns/ssti.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
#
|
3
3
|
# ronin-vulns - A Ruby library for blind vulnerability testing.
|
4
4
|
#
|
5
|
-
# Copyright (c) 2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
5
|
+
# Copyright (c) 2022-2023 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
6
|
#
|
7
7
|
# ronin-vulns is free software: you can redistribute it and/or modify
|
8
8
|
# it under the terms of the GNU Lesser General Public License as published
|
@@ -87,8 +87,8 @@ module Ronin
|
|
87
87
|
# A random test expression.
|
88
88
|
#
|
89
89
|
def self.random_test
|
90
|
-
int1 = rand(
|
91
|
-
int2 = rand(
|
90
|
+
int1 = rand(1_000..1_999)
|
91
|
+
int2 = rand(1_000..1_999)
|
92
92
|
|
93
93
|
string = "#{int1}*#{int2}"
|
94
94
|
result = (int1 * int2).to_s
|
@@ -108,7 +108,7 @@ module Ronin
|
|
108
108
|
# @option kwargs [Proc, nil] :escape
|
109
109
|
# The escape method to use. If `escape:` is not given, then all escapes
|
110
110
|
# in {ESCAPES} will be tested..
|
111
|
-
#
|
111
|
+
#
|
112
112
|
# @option kwargs [Array<Symbol, String>, Symbol, String, true, nil] :query_params
|
113
113
|
# The query param name(s) to test.
|
114
114
|
#
|
data/lib/ronin/vulns/version.rb
CHANGED
data/lib/ronin/vulns/vuln.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
#
|
3
3
|
# ronin-vulns - A Ruby library for blind vulnerability testing.
|
4
4
|
#
|
5
|
-
# Copyright (c) 2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
5
|
+
# Copyright (c) 2022-2023 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
6
|
#
|
7
7
|
# ronin-vulns is free software: you can redistribute it and/or modify
|
8
8
|
# it under the terms of the GNU Lesser General Public License as published
|
@@ -1,9 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
# frozen_string_literal: true
|
3
2
|
#
|
4
3
|
# ronin-vulns - A Ruby library for blind vulnerability testing.
|
5
4
|
#
|
6
|
-
# Copyright (c) 2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
5
|
+
# Copyright (c) 2022-2023 Hal Brodigan (postmodern.mod3 at gmail.com)
|
7
6
|
#
|
8
7
|
# ronin-vulns is free software: you can redistribute it and/or modify
|
9
8
|
# it under the terms of the GNU Lesser General Public License as published
|
@@ -119,9 +118,10 @@ module Ronin
|
|
119
118
|
cookie: nil,
|
120
119
|
form_data: nil)
|
121
120
|
@url = url
|
122
|
-
|
121
|
+
|
123
122
|
if query_params && !query_params.empty?
|
124
123
|
@url = url.dup
|
124
|
+
|
125
125
|
@url.query_params = query_params
|
126
126
|
end
|
127
127
|
|
data/lib/ronin/vulns/web_vuln.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
#
|
3
3
|
# ronin-vulns - A Ruby library for blind vulnerability testing.
|
4
4
|
#
|
5
|
-
# Copyright (c) 2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
5
|
+
# Copyright (c) 2022-2023 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
6
|
#
|
7
7
|
# ronin-vulns is free software: you can redistribute it and/or modify
|
8
8
|
# it under the terms of the GNU Lesser General Public License as published
|
@@ -292,7 +292,7 @@ module Ronin
|
|
292
292
|
url = URI(url)
|
293
293
|
http ||= Support::Network::HTTP.connect_uri(url)
|
294
294
|
|
295
|
-
unless cookie_params
|
295
|
+
unless cookie_params
|
296
296
|
cookie_params = Set.new
|
297
297
|
|
298
298
|
http.get_cookies(url.request_uri).each do |set_cookie|
|
data/ronin-vulns.gemspec
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'yaml'
|
2
4
|
|
3
5
|
Gem::Specification.new do |gem|
|
@@ -20,7 +22,7 @@ Gem::Specification.new do |gem|
|
|
20
22
|
gem.homepage = gemspec['homepage']
|
21
23
|
gem.metadata = gemspec['metadata'] if gemspec['metadata']
|
22
24
|
|
23
|
-
glob =
|
25
|
+
glob = ->(patterns) { gem.files & Dir[*patterns] }
|
24
26
|
|
25
27
|
gem.files = `git ls-files`.split($/)
|
26
28
|
gem.files = glob[gemspec['files']] if gemspec['files']
|
@@ -44,7 +46,7 @@ Gem::Specification.new do |gem|
|
|
44
46
|
gem.required_rubygems_version = gemspec['required_rubygems_version']
|
45
47
|
gem.post_install_message = gemspec['post_install_message']
|
46
48
|
|
47
|
-
split =
|
49
|
+
split = ->(string) { string.split(/,\s*/) }
|
48
50
|
|
49
51
|
if gemspec['dependencies']
|
50
52
|
gemspec['dependencies'].each do |name,versions|
|
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.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Postmodern
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-02
|
11
|
+
date: 2023-03-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ronin-support
|
@@ -17,6 +17,9 @@ dependencies:
|
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.0'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.0.1
|
20
23
|
type: :runtime
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -24,6 +27,9 @@ dependencies:
|
|
24
27
|
- - "~>"
|
25
28
|
- !ruby/object:Gem::Version
|
26
29
|
version: '1.0'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.0.1
|
27
33
|
- !ruby/object:Gem::Dependency
|
28
34
|
name: ronin-core
|
29
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -70,6 +76,7 @@ files:
|
|
70
76
|
- ".github/workflows/ruby.yml"
|
71
77
|
- ".gitignore"
|
72
78
|
- ".rspec"
|
79
|
+
- ".rubocop.yml"
|
73
80
|
- ".ruby-version"
|
74
81
|
- ".yardopts"
|
75
82
|
- COPYING.txt
|