ronin-vulns 0.1.2 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.document +0 -1
- data/ChangeLog.md +23 -0
- data/Gemfile +2 -2
- data/README.md +0 -1
- data/lib/ronin/vulns/cli/commands/lfi.rb +9 -21
- data/lib/ronin/vulns/cli/commands/open_redirect.rb +3 -14
- data/lib/ronin/vulns/cli/commands/rfi.rb +9 -26
- data/lib/ronin/vulns/cli/commands/scan.rb +37 -83
- data/lib/ronin/vulns/cli/commands/sqli.rb +9 -29
- data/lib/ronin/vulns/cli/commands/ssti.rb +1 -18
- data/lib/ronin/vulns/cli/logging.rb +4 -4
- data/lib/ronin/vulns/cli/web_vuln_command.rb +126 -114
- data/lib/ronin/vulns/reflected_xss/context.rb +20 -6
- data/lib/ronin/vulns/sqli.rb +25 -13
- data/lib/ronin/vulns/ssti.rb +11 -11
- data/lib/ronin/vulns/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a034edd07851be44f796a03f47cc5583969734943d5ec23c0073e9dc92f62bd7
|
4
|
+
data.tar.gz: 223f844d4ead3779a13d981a6998c46a5cf7f445d5b95044ae30997f546642e5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0db7e162bc9e7294be2d5a89660c3fd3b5892d4e2595b56704bcd8725bccb3041b38a8621c1daab77471236d2a17c1075bdf8ce7f4f233afee43d7277b6afc94
|
7
|
+
data.tar.gz: 9a5e1f7513231f294ca5f328f79921dc66c1072b301ccfbf3ac72844b75b492a0ccd76a171d507d82b002824522f79cf6d9e08e7bf99c7624e47375993064176
|
data/.document
CHANGED
data/ChangeLog.md
CHANGED
@@ -1,3 +1,26 @@
|
|
1
|
+
### 0.1.4 / 2023-09-19
|
2
|
+
|
3
|
+
#### CLI
|
4
|
+
|
5
|
+
* Improved the performance of `ronin-vulns` commands when scanning multiple URLs
|
6
|
+
or a file of URLs by not rebuilding an identical
|
7
|
+
{Ronin::Vulns::CLI::WebVulnCommand#scan_kwargs} for each URL.
|
8
|
+
* Allow the `--cookie "..."` option to be repeated multiple times and merge the
|
9
|
+
cookie strings together.
|
10
|
+
* Allow the `--cookie-param NAME=VALUE` option to be used with the
|
11
|
+
`--cookie "..."` option and merge the cookie values together.
|
12
|
+
* Print vulnerable param names in single quotes.
|
13
|
+
|
14
|
+
### 0.1.3 / 2023-07-07
|
15
|
+
|
16
|
+
* Fixed a bug in {Ronin::Vulns::SSTI.scan} where when called without `escape:`
|
17
|
+
it would not return all found vulnerabilities.
|
18
|
+
* Fixed a bug in {Ronin::Vulns::SQLI.scan} where repeat requests would be sent
|
19
|
+
even if `escape_quote:`, `escape_parens:`, or `terminate:` keyword arguments
|
20
|
+
are given.
|
21
|
+
* Improved {Ronin::Vulns::ReflectedXSS::Context} to detect when the XSS occurs
|
22
|
+
after or *inside of* an HTML comment.
|
23
|
+
|
1
24
|
### 0.1.2 / 2023-03-01
|
2
25
|
|
3
26
|
* Require `ronin-support` ~> 1.0, >= 1.0.1
|
data/Gemfile
CHANGED
@@ -10,9 +10,9 @@ gem 'jruby-openssl', '~> 0.7', platforms: :jruby
|
|
10
10
|
# branch: '0.4.0'
|
11
11
|
|
12
12
|
# Ronin dependencies
|
13
|
-
# gem 'ronin-support', '~> 1.0', github:
|
13
|
+
# gem 'ronin-support', '~> 1.0', github: 'ronin-rb/ronin-support',
|
14
14
|
# branch: 'main'
|
15
|
-
# gem 'ronin-core', '~> 0.1', github:
|
15
|
+
# gem 'ronin-core', '~> 0.1', github: 'ronin-rb/ronin-core',
|
16
16
|
# branch: 'main'
|
17
17
|
|
18
18
|
group :development do
|
data/README.md
CHANGED
@@ -9,7 +9,6 @@
|
|
9
9
|
* [Issues](https://github.com/ronin-rb/ronin-vulns/issues)
|
10
10
|
* [Documentation](https://ronin-rb.dev/docs/ronin-vulns/frames)
|
11
11
|
* [Discord](https://discord.gg/6WAb3PsVX9) |
|
12
|
-
[Twitter](https://twitter.com/ronin_rb) |
|
13
12
|
[Mastodon](https://infosec.exchange/@ronin_rb)
|
14
13
|
|
15
14
|
## Description
|
@@ -66,14 +66,18 @@ module Ronin
|
|
66
66
|
value: {
|
67
67
|
type: [:unix, :windows]
|
68
68
|
},
|
69
|
-
desc: 'Sets the OS to test for'
|
69
|
+
desc: 'Sets the OS to test for' do |os|
|
70
|
+
scan_kwargs[:os] = os
|
71
|
+
end
|
70
72
|
|
71
73
|
option :depth, short: '-D',
|
72
74
|
value: {
|
73
75
|
type: Integer,
|
74
76
|
usage: 'COUNT'
|
75
77
|
},
|
76
|
-
desc: 'Sets the directory depth to escape up'
|
78
|
+
desc: 'Sets the directory depth to escape up' do |depth|
|
79
|
+
scan_kwargs[:depth] = depth
|
80
|
+
end
|
77
81
|
|
78
82
|
option :filter_bypass, short: '-B',
|
79
83
|
value: {
|
@@ -85,30 +89,14 @@ module Ronin
|
|
85
89
|
:zlib
|
86
90
|
]
|
87
91
|
},
|
88
|
-
desc: 'Sets the filter bypass strategy to use'
|
92
|
+
desc: 'Sets the filter bypass strategy to use' do |filter_bypass|
|
93
|
+
scan_kwargs[:filter_bypass] = filter_bypass
|
94
|
+
end
|
89
95
|
|
90
96
|
description 'Scans URL(s) for Local File Inclusion (LFI) vulnerabilities'
|
91
97
|
|
92
98
|
man_page 'ronin-vulns-lfi.1'
|
93
99
|
|
94
|
-
#
|
95
|
-
# Keyword arguments for `Vulns::LFI.scan` and `Vulns::LFI.test`.
|
96
|
-
#
|
97
|
-
# @return [Hash{Symbol => Object}]
|
98
|
-
#
|
99
|
-
def scan_kwargs
|
100
|
-
kwargs = super()
|
101
|
-
|
102
|
-
kwargs[:os] = options[:os] if options[:os]
|
103
|
-
kwargs[:depth] = options[:depth] if options[:depth]
|
104
|
-
|
105
|
-
if options[:filter_bypass]
|
106
|
-
kwargs[:filter_bypass] = options[:filter_bypass]
|
107
|
-
end
|
108
|
-
|
109
|
-
return kwargs
|
110
|
-
end
|
111
|
-
|
112
100
|
#
|
113
101
|
# Scans a URL for LFI vulnerabilities.
|
114
102
|
#
|
@@ -64,25 +64,14 @@ module Ronin
|
|
64
64
|
type: String,
|
65
65
|
usage: 'URL'
|
66
66
|
},
|
67
|
-
desc: 'Optional test URL to try to redirect to'
|
67
|
+
desc: 'Optional test URL to try to redirect to' do |test_url|
|
68
|
+
scan_kwargs[:test_url] = test_url
|
69
|
+
end
|
68
70
|
|
69
71
|
description 'Scans URL(s) for Open Redirect vulnerabilities'
|
70
72
|
|
71
73
|
man_page 'ronin-vulns-open-redirect.1'
|
72
74
|
|
73
|
-
#
|
74
|
-
# Keyword arguments for `Vulns::OpenRedirect.scan` and
|
75
|
-
# `Vulns::OpenRedirect.test`.
|
76
|
-
#
|
77
|
-
# @return [Hash{Symbol => Object}]
|
78
|
-
#
|
79
|
-
def scan_kwargs
|
80
|
-
kwargs = super()
|
81
|
-
|
82
|
-
kwargs[:test_url] = options[:test_url] if options[:test_url]
|
83
|
-
return kwargs
|
84
|
-
end
|
85
|
-
|
86
75
|
#
|
87
76
|
# Scans a URL for Open Redirect vulnerabilities.
|
88
77
|
#
|
@@ -71,7 +71,9 @@ module Ronin
|
|
71
71
|
'null-byte' => :null_byte
|
72
72
|
}
|
73
73
|
},
|
74
|
-
desc: 'Optional filter-bypass strategy to use'
|
74
|
+
desc: 'Optional filter-bypass strategy to use' do |filter_bypass|
|
75
|
+
scan_kwargs[:filter_bypass] = filter_bypass
|
76
|
+
end
|
75
77
|
|
76
78
|
option :script_lang, short: '-S',
|
77
79
|
value: {
|
@@ -84,42 +86,23 @@ module Ronin
|
|
84
86
|
'perl' => :perl
|
85
87
|
}
|
86
88
|
},
|
87
|
-
desc: 'Explicitly specify the scripting language to test for'
|
89
|
+
desc: 'Explicitly specify the scripting language to test for' do |script_lang|
|
90
|
+
scan_kwargs[:script_lang] = script_lang
|
91
|
+
end
|
88
92
|
|
89
93
|
option :test_script_url, short: '-T',
|
90
94
|
value: {
|
91
95
|
type: String,
|
92
96
|
usage: 'URL'
|
93
97
|
},
|
94
|
-
desc: 'Use an alternative test script URL'
|
98
|
+
desc: 'Use an alternative test script URL' do |test_script_url|
|
99
|
+
scan_kwargs[:test_script_url] = test_script_url
|
100
|
+
end
|
95
101
|
|
96
102
|
description 'Scans URL(s) for Remote File Inclusion (RFI) vulnerabilities'
|
97
103
|
|
98
104
|
man_page 'ronin-vulns-rfi.1'
|
99
105
|
|
100
|
-
#
|
101
|
-
# Keyword arguments for `Vulns::RFI.scan` and `Vulns::RFI.test`.
|
102
|
-
#
|
103
|
-
# @return [Hash{Symbol => Object}]
|
104
|
-
#
|
105
|
-
def scan_kwargs
|
106
|
-
kwargs = super()
|
107
|
-
|
108
|
-
if options[:filter_bypass]
|
109
|
-
kwargs[:filter_bypass] = options[:filter_bypass]
|
110
|
-
end
|
111
|
-
|
112
|
-
if options[:script_lang]
|
113
|
-
kwargs[:script_lang] = options[:script_lang]
|
114
|
-
end
|
115
|
-
|
116
|
-
if options[:test_script_url]
|
117
|
-
kwargs[:test_script_url] = options[:test_script_url]
|
118
|
-
end
|
119
|
-
|
120
|
-
return kwargs
|
121
|
-
end
|
122
|
-
|
123
106
|
#
|
124
107
|
# Scans a URL for RFI vulnerabilities.
|
125
108
|
#
|
@@ -74,13 +74,17 @@ module Ronin
|
|
74
74
|
option :lfi_os, value: {
|
75
75
|
type: [:unix, :windows]
|
76
76
|
},
|
77
|
-
desc: 'Sets the OS to test for'
|
77
|
+
desc: 'Sets the OS to test for' do |os|
|
78
|
+
lfi_kwargs[:os] = os
|
79
|
+
end
|
78
80
|
|
79
81
|
option :lfi_depth, value: {
|
80
82
|
type: Integer,
|
81
83
|
usage: 'COUNT'
|
82
84
|
},
|
83
|
-
desc: 'Sets the directory depth to escape up'
|
85
|
+
desc: 'Sets the directory depth to escape up' do |depth|
|
86
|
+
lfi_kwargs[:depth] = depth
|
87
|
+
end
|
84
88
|
|
85
89
|
option :lfi_filter_bypass, value: {
|
86
90
|
type: [
|
@@ -91,7 +95,9 @@ module Ronin
|
|
91
95
|
:zlib
|
92
96
|
]
|
93
97
|
},
|
94
|
-
desc: 'Sets the filter bypass strategy to use'
|
98
|
+
desc: 'Sets the filter bypass strategy to use' do |filter_bypass|
|
99
|
+
lfi_kwargs[:filter_bypass] = filter_bypass
|
100
|
+
end
|
95
101
|
|
96
102
|
option :rfi_filter_bypass, value: {
|
97
103
|
type: {
|
@@ -100,7 +106,9 @@ module Ronin
|
|
100
106
|
'null-byte' => :null_byte
|
101
107
|
}
|
102
108
|
},
|
103
|
-
desc: 'Optional filter-bypass strategy to use'
|
109
|
+
desc: 'Optional filter-bypass strategy to use' do |filter_bypass|
|
110
|
+
rfi_kwargs[:filter_bypass] = filter_bypass
|
111
|
+
end
|
104
112
|
|
105
113
|
option :rfi_script_lang, value: {
|
106
114
|
type: {
|
@@ -112,33 +120,45 @@ module Ronin
|
|
112
120
|
'perl' => :perl
|
113
121
|
}
|
114
122
|
},
|
115
|
-
desc: 'Explicitly specify the scripting language to test for'
|
123
|
+
desc: 'Explicitly specify the scripting language to test for' do |script_lang|
|
124
|
+
rfi_kwargs[:script_lang] = script_lang
|
125
|
+
end
|
116
126
|
|
117
127
|
option :rfi_test_script_url, value: {
|
118
128
|
type: String,
|
119
129
|
usage: 'URL'
|
120
130
|
},
|
121
|
-
desc: 'Use an alternative test script URL'
|
131
|
+
desc: 'Use an alternative test script URL' do |test_script_url|
|
132
|
+
rfi_kwargs[:test_script_url] = test_script_url
|
133
|
+
end
|
122
134
|
|
123
|
-
option :sqli_escape_quote, desc: 'Escapes quotation marks'
|
135
|
+
option :sqli_escape_quote, desc: 'Escapes quotation marks' do
|
136
|
+
sqli_kwargs[:escape_quote] = true
|
137
|
+
end
|
124
138
|
|
125
|
-
option :sqli_escape_parens, desc: 'Escapes parenthesis'
|
139
|
+
option :sqli_escape_parens, desc: 'Escapes parenthesis' do
|
140
|
+
sqli_kwargs[:escape_parens] = true
|
141
|
+
end
|
126
142
|
|
127
|
-
option :sqli_terminate, desc: 'Terminates the SQL expression with a --'
|
143
|
+
option :sqli_terminate, desc: 'Terminates the SQL expression with a --' do
|
144
|
+
sqli_kwargs[:terminate] = true
|
145
|
+
end
|
128
146
|
|
129
147
|
option :ssti_test_expr, value: {
|
130
148
|
type: %r{\A\d+\s*[\*/\+\-]\s*\d+\z},
|
131
149
|
usage: '{X*Y | X/Z | X+Y | X-Y}'
|
132
150
|
},
|
133
151
|
desc: 'Optional numeric test to use' do |expr|
|
134
|
-
|
152
|
+
ssti_kwargs[:test_expr] = Vulns::SSTI::TestExpression.parse(expr)
|
135
153
|
end
|
136
154
|
|
137
155
|
option :open_redirect_url, value: {
|
138
156
|
type: String,
|
139
157
|
usage: 'URL'
|
140
158
|
},
|
141
|
-
desc: 'Optional test URL to try to redirect to'
|
159
|
+
desc: 'Optional test URL to try to redirect to' do |test_url|
|
160
|
+
open_redirect_kwargs[:test_url] = test_url
|
161
|
+
end
|
142
162
|
|
143
163
|
description 'Scans URL(s) for web vulnerabilities'
|
144
164
|
|
@@ -151,16 +171,7 @@ module Ronin
|
|
151
171
|
# @return [Hash{Symbol => Object}]
|
152
172
|
#
|
153
173
|
def lfi_kwargs
|
154
|
-
|
155
|
-
|
156
|
-
kwargs[:os] = options[:lfi_os] if options[:lfi_os]
|
157
|
-
kwargs[:depth] = options[:lfi_depth] if options[:lfi_depth]
|
158
|
-
|
159
|
-
if options[:lfi_filter_bypass]
|
160
|
-
kwargs[:filter_bypass] = options[:lfi_filter_bypass]
|
161
|
-
end
|
162
|
-
|
163
|
-
return kwargs
|
174
|
+
scan_kwargs[:lfi] ||= {}
|
164
175
|
end
|
165
176
|
|
166
177
|
#
|
@@ -170,21 +181,7 @@ module Ronin
|
|
170
181
|
# @return [Hash{Symbol => Object}]
|
171
182
|
#
|
172
183
|
def rfi_kwargs
|
173
|
-
|
174
|
-
|
175
|
-
if options[:rfi_filter_bypass]
|
176
|
-
kwargs[:filter_bypass] = options[:rfi_filter_bypass]
|
177
|
-
end
|
178
|
-
|
179
|
-
if options[:rfi_script_lang]
|
180
|
-
kwargs[:script_lang] = options[:rfi_script_lang]
|
181
|
-
end
|
182
|
-
|
183
|
-
if options[:rfi_test_script_url]
|
184
|
-
kwargs[:test_script_url] = options[:rfi_test_script_url]
|
185
|
-
end
|
186
|
-
|
187
|
-
return kwargs
|
184
|
+
scan_kwargs[:rfi] ||= {}
|
188
185
|
end
|
189
186
|
|
190
187
|
#
|
@@ -194,21 +191,7 @@ module Ronin
|
|
194
191
|
# @return [Hash{Symbol => Object}]
|
195
192
|
#
|
196
193
|
def sqli_kwargs
|
197
|
-
|
198
|
-
|
199
|
-
if options[:sqli_escape_quote]
|
200
|
-
kwargs[:escape_quote] = options[:sqli_escape_quote]
|
201
|
-
end
|
202
|
-
|
203
|
-
if options[:sqli_escape_parens]
|
204
|
-
kwargs[:escape_parens] = options[:sqli_escape_parens]
|
205
|
-
end
|
206
|
-
|
207
|
-
if options[:sqli_terminate]
|
208
|
-
kwargs[:terminate] = options[:sqli_terminate]
|
209
|
-
end
|
210
|
-
|
211
|
-
return kwargs
|
194
|
+
scan_kwargs[:sqli] ||= {}
|
212
195
|
end
|
213
196
|
|
214
197
|
#
|
@@ -218,11 +201,7 @@ module Ronin
|
|
218
201
|
# @return [Hash{Symbol => Object}]
|
219
202
|
#
|
220
203
|
def ssti_kwargs
|
221
|
-
|
222
|
-
|
223
|
-
kwargs[:test_expr] = @ssti_test_expr if @ssti_test_expr
|
224
|
-
|
225
|
-
return kwargs
|
204
|
+
scan_kwargs[:ssti] ||= {}
|
226
205
|
end
|
227
206
|
|
228
207
|
#
|
@@ -232,13 +211,7 @@ module Ronin
|
|
232
211
|
# @return [Hash{Symbol => Object}]
|
233
212
|
#
|
234
213
|
def open_redirect_kwargs
|
235
|
-
|
236
|
-
|
237
|
-
if options[:open_redirect_url]
|
238
|
-
kwargs[:test_url] = options[:open_redirect_url]
|
239
|
-
end
|
240
|
-
|
241
|
-
return kwargs
|
214
|
+
scan_kwargs[:open_redirect] ||= {}
|
242
215
|
end
|
243
216
|
|
244
217
|
#
|
@@ -248,26 +221,7 @@ module Ronin
|
|
248
221
|
# @return [Hash{Symbol => Object}]
|
249
222
|
#
|
250
223
|
def reflected_xss_kwargs
|
251
|
-
{}
|
252
|
-
end
|
253
|
-
|
254
|
-
#
|
255
|
-
# Keyword arguments for `Vulns::URLScanner.scan` and
|
256
|
-
# `Vulns::URLScanner.test`.
|
257
|
-
#
|
258
|
-
# @return [Hash{Symbol => Object}]
|
259
|
-
#
|
260
|
-
def scan_kwargs
|
261
|
-
kwargs = super()
|
262
|
-
|
263
|
-
kwargs[:lfi] = lfi_kwargs
|
264
|
-
kwargs[:rfi] = rfi_kwargs
|
265
|
-
kwargs[:sqli] = sqli_kwargs
|
266
|
-
kwargs[:ssti] = ssti_kwargs
|
267
|
-
kwargs[:open_redirect] = open_redirect_kwargs
|
268
|
-
kwargs[:reflected_xss] = reflected_xss_kwargs
|
269
|
-
|
270
|
-
return kwargs
|
224
|
+
scan_kwargs[:reflected_xss] ||= {}
|
271
225
|
end
|
272
226
|
|
273
227
|
#
|
@@ -61,42 +61,22 @@ module Ronin
|
|
61
61
|
|
62
62
|
usage '[options] {URL ... | --input FILE}'
|
63
63
|
|
64
|
-
option :escape_quote, short: '-Q',
|
65
|
-
|
64
|
+
option :escape_quote, short: '-Q', desc: 'Escapes quotation marks' do
|
65
|
+
scan_kwargs[:escape_quote] = true
|
66
|
+
end
|
66
67
|
|
67
|
-
option :escape_parens, short: '-P',
|
68
|
-
|
68
|
+
option :escape_parens, short: '-P', desc: 'Escapes parenthesis' do
|
69
|
+
scan_kwargs[:escape_parens] = true
|
70
|
+
end
|
69
71
|
|
70
|
-
option :terminate, short: '-T',
|
71
|
-
|
72
|
+
option :terminate, short: '-T', desc: 'Terminates the SQL expression with a --' do
|
73
|
+
scan_kwargs[:terminate] = true
|
74
|
+
end
|
72
75
|
|
73
76
|
description 'Scans URL(s) for SQL injection (SQLi) vulnerabilities'
|
74
77
|
|
75
78
|
man_page 'ronin-vulns-sqli.1'
|
76
79
|
|
77
|
-
#
|
78
|
-
# Keyword arguments for `Vulns::SQLI.scan` and `Vulns::SQLI.test`.
|
79
|
-
#
|
80
|
-
# @return [Hash{Symbol => Object}]
|
81
|
-
#
|
82
|
-
def scan_kwargs
|
83
|
-
kwargs = super()
|
84
|
-
|
85
|
-
if options[:escape_quote]
|
86
|
-
kwargs[:escape_quote] = options[:escape_quote]
|
87
|
-
end
|
88
|
-
|
89
|
-
if options[:escape_parens]
|
90
|
-
kwargs[:escape_parens] = options[:escape_parens]
|
91
|
-
end
|
92
|
-
|
93
|
-
if options[:terminate]
|
94
|
-
kwargs[:terminate] = options[:terminate]
|
95
|
-
end
|
96
|
-
|
97
|
-
return kwargs
|
98
|
-
end
|
99
|
-
|
100
80
|
#
|
101
81
|
# Scans a URL for SQLi vulnerabilities.
|
102
82
|
#
|
@@ -67,30 +67,13 @@ module Ronin
|
|
67
67
|
usage: '{X*Y | X/Z | X+Y | X-Y}'
|
68
68
|
},
|
69
69
|
desc: 'Optional numeric test to use' do |expr|
|
70
|
-
|
70
|
+
scan_kwargs[:test_expr] = Vulns::SSTI::TestExpression.parse(expr)
|
71
71
|
end
|
72
72
|
|
73
73
|
description 'Scans URL(s) for Server Side Template Injection (SSTI) vulnerabilities'
|
74
74
|
|
75
75
|
man_page 'ronin-vulns-ssti.1'
|
76
76
|
|
77
|
-
# The expression to use to test for SSTI.
|
78
|
-
#
|
79
|
-
# @return [Vulns::SSTI::TestExpression, nil]
|
80
|
-
attr_reader :test_expr
|
81
|
-
|
82
|
-
#
|
83
|
-
# Keyword arguments for `Vulns::SSTI.scan` and `Vulns::SSTI.test`.
|
84
|
-
#
|
85
|
-
# @return [Hash{Symbol => Object}]
|
86
|
-
#
|
87
|
-
def scan_kwargs
|
88
|
-
kwargs = super()
|
89
|
-
|
90
|
-
kwargs[:test_expr] = @test_expr if @test_expr
|
91
|
-
return kwargs
|
92
|
-
end
|
93
|
-
|
94
77
|
#
|
95
78
|
# Scans a URL for SSTI vulnerabilities.
|
96
79
|
#
|
@@ -60,13 +60,13 @@ module Ronin
|
|
60
60
|
def log_vuln(vuln)
|
61
61
|
vuln_name = vuln_type(vuln)
|
62
62
|
location = if vuln.query_param
|
63
|
-
"query param #{vuln.query_param}"
|
63
|
+
"query param '#{vuln.query_param}'"
|
64
64
|
elsif vuln.header_name
|
65
|
-
"Header #{vuln.header_name}"
|
65
|
+
"Header '#{vuln.header_name}'"
|
66
66
|
elsif vuln.cookie_param
|
67
|
-
"Cookie param #{vuln.cookie_param}"
|
67
|
+
"Cookie param '#{vuln.cookie_param}'"
|
68
68
|
elsif vuln.form_param
|
69
|
-
"form param #{vuln.form_param}"
|
69
|
+
"form param '#{vuln.form_param}'"
|
70
70
|
end
|
71
71
|
|
72
72
|
if location
|
@@ -53,10 +53,7 @@ module Ronin
|
|
53
53
|
desc: 'Sets an additional header' do |header|
|
54
54
|
name, value = header.split(/:\s*/,2)
|
55
55
|
|
56
|
-
|
57
|
-
@headers ||= {}
|
58
|
-
|
59
|
-
@headers[name] = value
|
56
|
+
self.headers[name] = value
|
60
57
|
end
|
61
58
|
|
62
59
|
option :cookie, short: '-C',
|
@@ -65,7 +62,9 @@ module Ronin
|
|
65
62
|
usage: 'COOKIE'
|
66
63
|
},
|
67
64
|
desc: 'Sets the raw Cookie header' do |cookie|
|
68
|
-
|
65
|
+
cookie = Support::Network::HTTP::Cookie.parse(cookie)
|
66
|
+
|
67
|
+
self.cookie.merge!(cookie)
|
69
68
|
end
|
70
69
|
|
71
70
|
option :cookie_param, short: '-c',
|
@@ -76,10 +75,7 @@ module Ronin
|
|
76
75
|
desc: 'Sets an additional cookie param' do |param|
|
77
76
|
name, value = param.split('=',2)
|
78
77
|
|
79
|
-
|
80
|
-
@cookie ||= Support::Network::HTTP::Cookie.new
|
81
|
-
|
82
|
-
@cookie[name] = value
|
78
|
+
self.cookie[name] = value
|
83
79
|
end
|
84
80
|
|
85
81
|
option :referer, short: '-R',
|
@@ -88,7 +84,7 @@ module Ronin
|
|
88
84
|
usage: 'URL'
|
89
85
|
},
|
90
86
|
desc: 'Sets the Referer header' do |referer|
|
91
|
-
|
87
|
+
self.referer = referer
|
92
88
|
end
|
93
89
|
|
94
90
|
option :form_param, short: '-F',
|
@@ -99,10 +95,7 @@ module Ronin
|
|
99
95
|
desc: 'Sets an additional form param' do |param|
|
100
96
|
name, value = param.split('=',2)
|
101
97
|
|
102
|
-
|
103
|
-
@form_data ||= {}
|
104
|
-
|
105
|
-
@form_data[name] = value
|
98
|
+
self.form_data[name] = value
|
106
99
|
end
|
107
100
|
|
108
101
|
option :test_query_param, value: {
|
@@ -110,14 +103,16 @@ module Ronin
|
|
110
103
|
usage: 'NAME'
|
111
104
|
},
|
112
105
|
desc: 'Tests the URL query param name' do |name|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
106
|
+
case (test_query_params = self.test_query_params)
|
107
|
+
when true
|
108
|
+
# no-op, test all query params
|
109
|
+
when Set
|
110
|
+
test_query_params << name
|
111
|
+
end
|
117
112
|
end
|
118
113
|
|
119
114
|
option :test_all_query_params, desc: 'Test all URL query param names' do
|
120
|
-
|
115
|
+
self.test_query_params = true
|
121
116
|
end
|
122
117
|
|
123
118
|
option :test_header_name, value: {
|
@@ -125,10 +120,7 @@ module Ronin
|
|
125
120
|
usage: 'NAME'
|
126
121
|
},
|
127
122
|
desc: 'Tests the HTTP Header name' do |name|
|
128
|
-
|
129
|
-
@test_header_names ||= Set.new
|
130
|
-
|
131
|
-
@test_header_names << name
|
123
|
+
self.test_header_names << name
|
132
124
|
end
|
133
125
|
|
134
126
|
option :test_cookie_param, value: {
|
@@ -136,26 +128,25 @@ module Ronin
|
|
136
128
|
usage: 'NAME'
|
137
129
|
},
|
138
130
|
desc: 'Tests the HTTP Cookie name' do |name|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
131
|
+
case (test_cookie_params = self.test_cookie_params)
|
132
|
+
when true
|
133
|
+
# no-op, test all query params
|
134
|
+
when Set
|
135
|
+
test_cookie_params << name
|
136
|
+
end
|
143
137
|
end
|
144
138
|
|
145
139
|
option :test_all_cookie_params, desc: 'Test all Cookie param names' do
|
146
|
-
|
140
|
+
self.test_cookie_params = true
|
147
141
|
end
|
148
142
|
|
149
143
|
option :test_form_param, value: {
|
150
144
|
type: String,
|
151
|
-
|
145
|
+
usage: 'NAME'
|
152
146
|
},
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
@test_form_params << name
|
158
|
-
end
|
147
|
+
desc: 'Tests the form param name' do |name|
|
148
|
+
self.test_form_params << name
|
149
|
+
end
|
159
150
|
|
160
151
|
option :input, short: '-i',
|
161
152
|
value: {
|
@@ -175,60 +166,11 @@ module Ronin
|
|
175
166
|
# * `:all` - Find all vulnerabilities for each URL.
|
176
167
|
attr_reader :scan_mode
|
177
168
|
|
178
|
-
#
|
179
|
-
#
|
180
|
-
# @return [Hash{String => String}, nil]
|
181
|
-
attr_reader :headers
|
182
|
-
|
183
|
-
# The raw `Cookie` header to send.
|
184
|
-
#
|
185
|
-
# @return [String, nil]
|
186
|
-
attr_reader :raw_cookie
|
187
|
-
|
188
|
-
# The optional `Cookie` header to send.
|
189
|
-
#
|
190
|
-
# @return [Ronin::Support::Network::HTTP::Cookie, nil]
|
191
|
-
attr_reader :cookie
|
192
|
-
|
193
|
-
# The optional `Referer` header to send.
|
194
|
-
#
|
195
|
-
# @return [String, nil]
|
196
|
-
attr_reader :referer
|
197
|
-
|
198
|
-
# Additional form params.
|
199
|
-
#
|
200
|
-
# @return [Hash{String => String}, nil]
|
201
|
-
attr_reader :form_data
|
202
|
-
|
203
|
-
# The URL query params to test.
|
204
|
-
#
|
205
|
-
# @return [Set<String>, nil]
|
206
|
-
attr_reader :test_query_params
|
207
|
-
|
208
|
-
# Indicates whether to test all of the query params of the URL.
|
209
|
-
#
|
210
|
-
# @return [Boolean, nil]
|
211
|
-
attr_reader :test_all_query_params
|
212
|
-
|
213
|
-
# The HTTP Header names to test.
|
214
|
-
#
|
215
|
-
# @return [Set<String>, nil]
|
216
|
-
attr_reader :test_header_names
|
217
|
-
|
218
|
-
# The HTTP Cookie to test.
|
219
|
-
#
|
220
|
-
# @return [Set<String>, nil]
|
221
|
-
attr_reader :test_cookie_params
|
222
|
-
|
223
|
-
# Indicates whether to test all `Cookie` params for the URL.
|
169
|
+
# Keywrod arguments that will be used in {#scan_url} and {#test_url} to
|
170
|
+
# call {WebVuln.scan} or {WebVuln.test}.
|
224
171
|
#
|
225
|
-
# @return [
|
226
|
-
attr_reader :
|
227
|
-
|
228
|
-
# The form params to test.
|
229
|
-
#
|
230
|
-
# @return [Set<String>, nil]
|
231
|
-
attr_reader :test_form_params
|
172
|
+
# @return [Hash{Symbol => Object}]
|
173
|
+
attr_reader :scan_kwargs
|
232
174
|
|
233
175
|
#
|
234
176
|
# Initializes the command.
|
@@ -239,7 +181,8 @@ module Ronin
|
|
239
181
|
def initialize(**kwargs)
|
240
182
|
super(**kwargs)
|
241
183
|
|
242
|
-
@scan_mode
|
184
|
+
@scan_mode = :first
|
185
|
+
@scan_kwargs = {}
|
243
186
|
end
|
244
187
|
|
245
188
|
#
|
@@ -308,42 +251,111 @@ module Ronin
|
|
308
251
|
end
|
309
252
|
|
310
253
|
#
|
311
|
-
#
|
254
|
+
# Additional headers.
|
312
255
|
#
|
313
256
|
# @return [Hash{String => String}]
|
314
|
-
# The keyword arguments.
|
315
257
|
#
|
316
|
-
def
|
317
|
-
|
258
|
+
def headers
|
259
|
+
@scan_kwargs[:headers] ||= {}
|
260
|
+
end
|
261
|
+
|
262
|
+
#
|
263
|
+
# The optional `Cookie` header to send.
|
264
|
+
#
|
265
|
+
# @return [Ronin::Support::Network::HTTP::Cookie]
|
266
|
+
#
|
267
|
+
def cookie
|
268
|
+
@scan_kwargs[:cookie] ||= Support::Network::HTTP::Cookie.new
|
269
|
+
end
|
318
270
|
|
319
|
-
|
271
|
+
#
|
272
|
+
# The optional HTTP `Referer` header to send.
|
273
|
+
#
|
274
|
+
# @return [String, nil]
|
275
|
+
#
|
276
|
+
def referer
|
277
|
+
@scan_kwargs[:referer]
|
278
|
+
end
|
320
279
|
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
280
|
+
#
|
281
|
+
# Sets the HTTP `Referer` header to send.
|
282
|
+
#
|
283
|
+
# @param [String, nil] new_referer
|
284
|
+
# The new `Referer` header to send.
|
285
|
+
#
|
286
|
+
# @return [String, nil]
|
287
|
+
#
|
288
|
+
def referer=(new_referer)
|
289
|
+
@scan_kwargs[:referer] = new_referer
|
290
|
+
end
|
326
291
|
|
327
|
-
|
328
|
-
|
292
|
+
#
|
293
|
+
# Additional form params.
|
294
|
+
#
|
295
|
+
# @return [Hash{String => String}, nil]
|
296
|
+
#
|
297
|
+
def form_data
|
298
|
+
@scan_kwargs[:form_data] ||= {}
|
299
|
+
end
|
329
300
|
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
301
|
+
#
|
302
|
+
# The URL query params to test.
|
303
|
+
#
|
304
|
+
# @return [Set<String>, true]
|
305
|
+
#
|
306
|
+
def test_query_params
|
307
|
+
@scan_kwargs[:query_params] ||= Set.new
|
308
|
+
end
|
309
|
+
|
310
|
+
#
|
311
|
+
# Sets the URL query params to test.
|
312
|
+
#
|
313
|
+
# @param [Set<String>, true] new_query_params
|
314
|
+
# The query params to test.
|
315
|
+
#
|
316
|
+
# @return [Set<String>, true]
|
317
|
+
#
|
318
|
+
def test_query_params=(new_query_params)
|
319
|
+
@scan_kwargs[:query_params] = new_query_params
|
320
|
+
end
|
335
321
|
|
336
|
-
|
322
|
+
#
|
323
|
+
# The HTTP Header names to test.
|
324
|
+
#
|
325
|
+
# @return [Set<String>]
|
326
|
+
#
|
327
|
+
def test_header_names
|
328
|
+
@scan_kwargs[:header_names] ||= Set.new
|
329
|
+
end
|
337
330
|
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
331
|
+
#
|
332
|
+
# The HTTP Cookie to test.
|
333
|
+
#
|
334
|
+
# @return [Set<String>, true]
|
335
|
+
#
|
336
|
+
def test_cookie_params
|
337
|
+
@scan_kwargs[:cookie_params] ||= Set.new
|
338
|
+
end
|
343
339
|
|
344
|
-
|
340
|
+
#
|
341
|
+
# Sets the HTTP Cookie to test.
|
342
|
+
#
|
343
|
+
# @param [Set<String>, true] new_cookie_params
|
344
|
+
# The new cookie param names to test.
|
345
|
+
#
|
346
|
+
# @return [Set<String>, true]
|
347
|
+
#
|
348
|
+
def test_cookie_params=(new_cookie_params)
|
349
|
+
@scan_kwargs[:cookie_params] = new_cookie_params
|
350
|
+
end
|
345
351
|
|
346
|
-
|
352
|
+
#
|
353
|
+
# The form params to test.
|
354
|
+
#
|
355
|
+
# @return [Set<String>, nil]
|
356
|
+
#
|
357
|
+
def test_form_params
|
358
|
+
@scan_kwargs[:form_params] ||= Set.new
|
347
359
|
end
|
348
360
|
|
349
361
|
#
|
@@ -30,7 +30,7 @@ module Ronin
|
|
30
30
|
|
31
31
|
# Where in the HTML the XSS occurs.
|
32
32
|
#
|
33
|
-
# @return [:double_quoted_attr_value, :single_quoted_attr_value, :unquoted_attr_value, :attr_name, :attr_list, :tag_name, :tag_body]
|
33
|
+
# @return [:double_quoted_attr_value, :single_quoted_attr_value, :unquoted_attr_value, :attr_name, :attr_list, :tag_name, :tag_body, :comment]
|
34
34
|
# The context which the XSS occurs in.
|
35
35
|
# * `:tag_body` occurred within a tag's body (ex: `<tag>XSS...</tag>`)
|
36
36
|
# * `:double_quoted_attr_value` - occurred in a double quoted
|
@@ -44,13 +44,14 @@ module Ronin
|
|
44
44
|
# * `:attr_list` - occurred in the attribute list
|
45
45
|
# (ex: `<tag XSS>...</tag>`)
|
46
46
|
# * `:tag_name` - occurred in the tag name (ex: `<tagXSS>...</tag>`)
|
47
|
+
# * `:comment` - occurred in a comment (ex: `<!-- XSS -->`)
|
47
48
|
#
|
48
49
|
# @api public
|
49
50
|
attr_reader :location
|
50
51
|
|
51
52
|
# The name of the parent tag which the XSS occurs in.
|
52
53
|
#
|
53
|
-
# @return [String]
|
54
|
+
# @return [String, nil]
|
54
55
|
#
|
55
56
|
# @api public
|
56
57
|
attr_reader :tag
|
@@ -65,9 +66,9 @@ module Ronin
|
|
65
66
|
#
|
66
67
|
# Initializes the context.
|
67
68
|
#
|
68
|
-
# @param [:double_quoted_attr_value, :single_quoted_attr_value, :unquoted_attr_value, :attr_name, :attr_list, :tag_name, :tag_body] location
|
69
|
+
# @param [:double_quoted_attr_value, :single_quoted_attr_value, :unquoted_attr_value, :attr_name, :attr_list, :tag_name, :tag_body, :comment] location
|
69
70
|
#
|
70
|
-
# @param [String] tag
|
71
|
+
# @param [String, nil] tag
|
71
72
|
#
|
72
73
|
# @param [String, nil] attr
|
73
74
|
#
|
@@ -100,6 +101,11 @@ module Ronin
|
|
100
101
|
# @api private
|
101
102
|
ATTR_LIST = /(?:\s+#{ATTR})*/
|
102
103
|
|
104
|
+
# HTML comment regexp.
|
105
|
+
#
|
106
|
+
# @api private
|
107
|
+
COMMENT = /<![^>]*>/
|
108
|
+
|
103
109
|
# HTML tag name regexp.
|
104
110
|
#
|
105
111
|
# @api private
|
@@ -108,7 +114,7 @@ module Ronin
|
|
108
114
|
# Regexp matching when an XSS occurs within a tag's inner HTML.
|
109
115
|
#
|
110
116
|
# @api private
|
111
|
-
IN_TAG_BODY = %r{<(#{TAG_NAME})#{ATTR_LIST}\s*(?:>|/>)[^<>]*\z}
|
117
|
+
IN_TAG_BODY = %r{<(#{TAG_NAME})#{ATTR_LIST}\s*(?:>|/>)([^<>]|#{COMMENT})*\z}
|
112
118
|
|
113
119
|
# Regexp matching when an XSS occurs within a double-quoted attribute
|
114
120
|
# value.
|
@@ -142,6 +148,11 @@ module Ronin
|
|
142
148
|
# @api private
|
143
149
|
IN_TAG_NAME = /<(#{TAG_NAME})\z/
|
144
150
|
|
151
|
+
# Regexp matching when an XSS occurs within a comment.
|
152
|
+
#
|
153
|
+
# @api private
|
154
|
+
IN_COMMENT = /<![^>]*\z/
|
155
|
+
|
145
156
|
#
|
146
157
|
# Determine the context of the XSS by checking the characters that come
|
147
158
|
# before the given index.
|
@@ -174,6 +185,8 @@ module Ronin
|
|
174
185
|
new(:attr_list, tag: match[1])
|
175
186
|
elsif (match = prefix.match(IN_TAG_NAME))
|
176
187
|
new(:tag_name, tag: match[1])
|
188
|
+
elsif prefix.match?(IN_COMMENT)
|
189
|
+
new(:comment)
|
177
190
|
end
|
178
191
|
end
|
179
192
|
|
@@ -193,7 +206,8 @@ module Ronin
|
|
193
206
|
attr_name: MINIMAL_REQUIRED_CHARS,
|
194
207
|
attr_list: MINIMAL_REQUIRED_CHARS,
|
195
208
|
tag_name: MINIMAL_REQUIRED_CHARS,
|
196
|
-
tag_body: MINIMAL_REQUIRED_CHARS
|
209
|
+
tag_body: MINIMAL_REQUIRED_CHARS,
|
210
|
+
comment: MINIMAL_REQUIRED_CHARS
|
197
211
|
}
|
198
212
|
|
199
213
|
#
|
data/lib/ronin/vulns/sqli.rb
CHANGED
@@ -105,6 +105,18 @@ module Ronin
|
|
105
105
|
# @param [URI::HTTP, String] url
|
106
106
|
# The URL to test or exploit.
|
107
107
|
#
|
108
|
+
# @param [Array<Boolean>, Boolean] escape_quote
|
109
|
+
# Controls whether to escape a quoted string value. If not specified,
|
110
|
+
# with and without quoted string escaping will be tested.
|
111
|
+
#
|
112
|
+
# @param [Array<Boolean>, Boolean] escape_parens
|
113
|
+
# Controls whether to escape parenthesis. If not specified, with and
|
114
|
+
# without parenthesis escaping will be tested.
|
115
|
+
#
|
116
|
+
# @param [Array<Boolean>, Boolean] terminate
|
117
|
+
# Controls whether to terminate the SQL statement with `--`.
|
118
|
+
# If not specified, with and without `--` terminate will be tested.
|
119
|
+
#
|
108
120
|
# @param [Ronin::Support::Network::HTTP, nil] http
|
109
121
|
# An HTTP session to use for testing the URL.
|
110
122
|
#
|
@@ -115,28 +127,28 @@ module Ronin
|
|
115
127
|
# If a block is given it will be yielded each discovered SQL injection
|
116
128
|
# vulnerability.
|
117
129
|
#
|
118
|
-
# @yieldparam [
|
130
|
+
# @yieldparam [SQLI] sqli
|
119
131
|
# A discovered SQL injection vulnerability in the URL.
|
120
132
|
#
|
121
|
-
# @return [Array<
|
133
|
+
# @return [Array<SQLI>]
|
122
134
|
# All discovered SQL injection vulnerabilities.
|
123
135
|
#
|
124
|
-
def self.scan(url,
|
136
|
+
def self.scan(url, escape_quote: [false, true],
|
137
|
+
escape_parens: [false, true],
|
138
|
+
terminate: [false, true],
|
139
|
+
# WebVuln.scan keyword arguments
|
140
|
+
http: nil, **kwargs, &block)
|
125
141
|
url = URI(url)
|
126
142
|
http ||= Support::Network::HTTP.connect_uri(url)
|
127
143
|
|
128
|
-
escape_quotes = [false, true]
|
129
|
-
escape_parens = [false, true]
|
130
|
-
terminations = [false, true]
|
131
|
-
|
132
144
|
vulns = []
|
133
145
|
|
134
|
-
|
135
|
-
escape_parens.each do |
|
136
|
-
|
137
|
-
vulns.concat(super(url, escape_quote:
|
138
|
-
escape_parens:
|
139
|
-
terminate:
|
146
|
+
Array(escape_quote).each do |escape_quote_value|
|
147
|
+
Array(escape_parens).each do |escape_parens_value|
|
148
|
+
Array(terminate).each do |terminate_value|
|
149
|
+
vulns.concat(super(url, escape_quote: escape_quote_value,
|
150
|
+
escape_parens: escape_parens_value,
|
151
|
+
terminate: terminate_value,
|
140
152
|
http: http,
|
141
153
|
**kwargs,
|
142
154
|
&block))
|
data/lib/ronin/vulns/ssti.rb
CHANGED
@@ -102,13 +102,13 @@ module Ronin
|
|
102
102
|
# @param [URI::HTTP, String] url
|
103
103
|
# The URL to scan.
|
104
104
|
#
|
105
|
-
# @param [
|
106
|
-
# Additional keyword arguments for {#initialize}.
|
107
|
-
#
|
108
|
-
# @option kwargs [Proc, nil] :escape
|
105
|
+
# @param [Array<Proc>, Proc, nil] escape
|
109
106
|
# The escape method to use. If `escape:` is not given, then all escapes
|
110
107
|
# in {ESCAPES} will be tested..
|
111
108
|
#
|
109
|
+
# @param [Hash{Symbol => Object}] kwargs
|
110
|
+
# Additional keyword arguments for {#initialize}.
|
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
|
#
|
@@ -145,14 +145,14 @@ module Ronin
|
|
145
145
|
# @return [Array<SSTI>]
|
146
146
|
# All discovered SSTI vulnerabilities.
|
147
147
|
#
|
148
|
-
def self.scan(url, **kwargs,&block)
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
super(url, escape: escape, **kwargs, &block)
|
154
|
-
end
|
148
|
+
def self.scan(url, escape: ESCAPES, **kwargs,&block)
|
149
|
+
vulns = []
|
150
|
+
|
151
|
+
Array(escape).each do |escape_char|
|
152
|
+
vulns.concat(super(url, escape: escape_char, **kwargs, &block))
|
155
153
|
end
|
154
|
+
|
155
|
+
return vulns
|
156
156
|
end
|
157
157
|
|
158
158
|
#
|
data/lib/ronin/vulns/version.rb
CHANGED
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.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Postmodern
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-09-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ronin-support
|