ronin-vulns 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
|