ronin-vulns 0.1.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/.github/workflows/ruby.yml +31 -0
  4. data/.gitignore +13 -0
  5. data/.rspec +1 -0
  6. data/.ruby-version +1 -0
  7. data/.yardopts +1 -0
  8. data/COPYING.txt +165 -0
  9. data/ChangeLog.md +22 -0
  10. data/Gemfile +34 -0
  11. data/README.md +328 -0
  12. data/Rakefile +34 -0
  13. data/bin/ronin-vulns +19 -0
  14. data/data/rfi_test.asp +21 -0
  15. data/data/rfi_test.aspx +25 -0
  16. data/data/rfi_test.cfm +27 -0
  17. data/data/rfi_test.jsp +19 -0
  18. data/data/rfi_test.php +24 -0
  19. data/data/rfi_test.pl +25 -0
  20. data/gemspec.yml +41 -0
  21. data/lib/ronin/vulns/cli/command.rb +39 -0
  22. data/lib/ronin/vulns/cli/commands/lfi.rb +145 -0
  23. data/lib/ronin/vulns/cli/commands/open_redirect.rb +119 -0
  24. data/lib/ronin/vulns/cli/commands/reflected_xss.rb +99 -0
  25. data/lib/ronin/vulns/cli/commands/rfi.rb +156 -0
  26. data/lib/ronin/vulns/cli/commands/scan.rb +316 -0
  27. data/lib/ronin/vulns/cli/commands/sqli.rb +133 -0
  28. data/lib/ronin/vulns/cli/commands/ssti.rb +126 -0
  29. data/lib/ronin/vulns/cli/logging.rb +78 -0
  30. data/lib/ronin/vulns/cli/web_vuln_command.rb +347 -0
  31. data/lib/ronin/vulns/cli.rb +45 -0
  32. data/lib/ronin/vulns/lfi/test_file.rb +91 -0
  33. data/lib/ronin/vulns/lfi.rb +266 -0
  34. data/lib/ronin/vulns/open_redirect.rb +118 -0
  35. data/lib/ronin/vulns/reflected_xss/context.rb +224 -0
  36. data/lib/ronin/vulns/reflected_xss/test_string.rb +149 -0
  37. data/lib/ronin/vulns/reflected_xss.rb +184 -0
  38. data/lib/ronin/vulns/rfi.rb +224 -0
  39. data/lib/ronin/vulns/root.rb +28 -0
  40. data/lib/ronin/vulns/sqli/error_pattern.rb +89 -0
  41. data/lib/ronin/vulns/sqli.rb +397 -0
  42. data/lib/ronin/vulns/ssti/test_expression.rb +104 -0
  43. data/lib/ronin/vulns/ssti.rb +203 -0
  44. data/lib/ronin/vulns/url_scanner.rb +218 -0
  45. data/lib/ronin/vulns/version.rb +26 -0
  46. data/lib/ronin/vulns/vuln.rb +49 -0
  47. data/lib/ronin/vulns/web_vuln/http_request.rb +223 -0
  48. data/lib/ronin/vulns/web_vuln.rb +774 -0
  49. data/man/ronin-vulns-lfi.1 +107 -0
  50. data/man/ronin-vulns-lfi.1.md +80 -0
  51. data/man/ronin-vulns-open-redirect.1 +98 -0
  52. data/man/ronin-vulns-open-redirect.1.md +73 -0
  53. data/man/ronin-vulns-reflected-xss.1 +95 -0
  54. data/man/ronin-vulns-reflected-xss.1.md +71 -0
  55. data/man/ronin-vulns-rfi.1 +107 -0
  56. data/man/ronin-vulns-rfi.1.md +80 -0
  57. data/man/ronin-vulns-scan.1 +138 -0
  58. data/man/ronin-vulns-scan.1.md +103 -0
  59. data/man/ronin-vulns-sqli.1 +107 -0
  60. data/man/ronin-vulns-sqli.1.md +80 -0
  61. data/man/ronin-vulns-ssti.1 +99 -0
  62. data/man/ronin-vulns-ssti.1.md +74 -0
  63. data/ronin-vulns.gemspec +60 -0
  64. metadata +161 -0
@@ -0,0 +1,397 @@
1
+ # frozen_string_literal: true
2
+ # frozen_string_literal: true
3
+ #
4
+ # ronin-vulns - A Ruby library for blind vulnerability testing.
5
+ #
6
+ # Copyright (c) 2022 Hal Brodigan (postmodern.mod3 at gmail.com)
7
+ #
8
+ # ronin-vulns is free software: you can redistribute it and/or modify
9
+ # it under the terms of the GNU Lesser General Public License as published
10
+ # by the Free Software Foundation, either version 3 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # ronin-vulns is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU Lesser General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU Lesser General Public License
19
+ # along with ronin-vulns. If not, see <https://www.gnu.org/licenses/>.
20
+ #
21
+
22
+ require 'ronin/vulns/web_vuln'
23
+ require 'ronin/vulns/sqli/error_pattern'
24
+
25
+ require 'time'
26
+
27
+ module Ronin
28
+ module Vulns
29
+ #
30
+ # Represents a SQL injection vulnerability.
31
+ #
32
+ # ## Features
33
+ #
34
+ # * Supports testing ` OR 1=1` and ` AND 1=0`.
35
+ # * Supports testing SQL sleep functions.
36
+ #
37
+ class SQLI < WebVuln
38
+
39
+ # Specifies whether to escape a quoted string value.
40
+ #
41
+ # @return [Boolean]
42
+ attr_reader :escape_quote
43
+
44
+ # Specifies whether to escape parenthesis.
45
+ #
46
+ # @return [Boolean]
47
+ attr_reader :escape_parens
48
+
49
+ # Specifies whether to terminate the SQL statement with `--`.
50
+ #
51
+ # @return [Boolean]
52
+ attr_reader :terminate
53
+
54
+ #
55
+ # Initializes the SQL injection vulnerability.
56
+ #
57
+ # @param [URI::HTTP, String] url
58
+ # The URL to test or exploit.
59
+ #
60
+ # @param [Boolean] escape_quote
61
+ # Specifies whether to escape a quoted string value.
62
+ #
63
+ # @param [Boolean] escape_parens
64
+ # Specifies whether to escape parenthesis.
65
+ #
66
+ # @param [Boolean] terminate
67
+ # Specifies whether to terminate the SQL statement with `--`.
68
+ #
69
+ def initialize(url, escape_quote: false,
70
+ escape_parens: false,
71
+ terminate: false,
72
+ **kwargs)
73
+ super(url,**kwargs)
74
+
75
+ @escape_quote = escape_quote
76
+ @escape_parens = escape_parens
77
+ @terminate = terminate
78
+
79
+ @escape_string = build_escape_string
80
+ end
81
+
82
+ private
83
+
84
+ #
85
+ # Builds the SQL escape String.
86
+ #
87
+ # @return [String]
88
+ #
89
+ def build_escape_string
90
+ if @escape_quote && @escape_parens
91
+ "#{original_value}')"
92
+ elsif @escape_quote
93
+ "#{original_value}'"
94
+ elsif @escape_parens
95
+ "#{original_value})"
96
+ else
97
+ original_value
98
+ end
99
+ end
100
+
101
+ public
102
+
103
+ #
104
+ # Scans the URL for SQL injections.
105
+ #
106
+ # @param [URI::HTTP, String] url
107
+ # The URL to test or exploit.
108
+ #
109
+ # @param [Ronin::Support::Network::HTTP, nil] http
110
+ # An HTTP session to use for testing the URL.
111
+ #
112
+ # @param [Hash{Symbol => Object}] kwargs
113
+ # Additional keyword arguments for {WebVuln.scan}.
114
+ #
115
+ # @yield [sqli]
116
+ # If a block is given it will be yielded each discovered SQL injection
117
+ # vulnerability.
118
+ #
119
+ # @yieldparam [SQLi] sqli
120
+ # A discovered SQL injection vulnerability in the URL.
121
+ #
122
+ # @return [Array<SQLi>]
123
+ # All discovered SQL injection vulnerabilities.
124
+ #
125
+ def self.scan(url, http: nil, **kwargs, &block)
126
+ url = URI(url)
127
+ http ||= Support::Network::HTTP.connect_uri(url)
128
+
129
+ escape_quotes = [false, true]
130
+ escape_parens = [false, true]
131
+ terminations = [false, true]
132
+
133
+ vulns = []
134
+
135
+ escape_quotes.each do |escape_quote|
136
+ escape_parens.each do |escape_paren|
137
+ terminations.each do |terminate|
138
+ vulns.concat(super(url, escape_quote: escape_quote,
139
+ escape_parens: escape_paren,
140
+ terminate: terminate,
141
+ http: http,
142
+ **kwargs,
143
+ &block))
144
+ end
145
+ end
146
+ end
147
+
148
+ return vulns
149
+ end
150
+
151
+ #
152
+ # Escapes the given SQL and turns it into a SQL injection.
153
+ #
154
+ # @param [#to_s] sql
155
+ # The SQL expression to escape.
156
+ #
157
+ # @return [String]
158
+ # The escaped SQL expression.
159
+ #
160
+ def escape(sql)
161
+ sqli = if sql.start_with?(';')
162
+ "#{@escape_string}#{sql}"
163
+ else
164
+ "#{@escape_string} #{sql}"
165
+ end
166
+
167
+ if @terminate
168
+ sqli << '--'
169
+ else
170
+ sqli.chop! if (@escape_parens && sqli.end_with?(')'))
171
+ sqli.chop! if (@escape_quote && sqli.end_with?("'"))
172
+ end
173
+
174
+ return sqli
175
+ end
176
+
177
+ #
178
+ # Encodes the SQL payload.
179
+ #
180
+ # @see #escape
181
+ #
182
+ def encode_payload(sql)
183
+ escape(sql)
184
+ end
185
+
186
+ #
187
+ # Tests whether the URL is vulnerable to SQL injection.
188
+ #
189
+ # @return [Boolean]
190
+ #
191
+ def vulnerable?
192
+ test_or_true_and_false || test_sleep
193
+ end
194
+
195
+ # SQL error message patterns for various databases.
196
+ ERROR_PATTERNS = {
197
+ postgresql: ErrorPattern[
198
+ /PostgreSQL.*ERROR/,
199
+ /Warning.*\Wpg_/,
200
+ /valid PostgreSQL result/,
201
+ /Npgsql\./,
202
+ /PG::SyntaxError:/,
203
+ /org\.postgresql\.util\.PSQLException/,
204
+ /ERROR:\s\ssyntax error at or near/,
205
+ /ERROR: parser: parse error at or near/,
206
+ /PostgreSQL query failed/,
207
+ /org\.postgresql\.jdbc/,
208
+ /Pdo[.\/_\\]Pgsql/,
209
+ /PSQLException/
210
+ ],
211
+
212
+ mysql: ErrorPattern[
213
+ /SQL syntax.*MySQL/,
214
+ /Warning.*\Wmysqli?_/,
215
+ /MySQLSyntaxErrorException/,
216
+ /valid MySQL result/,
217
+ /check the manual that corresponds to your (MySQL|MariaDB) server version/,
218
+ /Unknown column '[^ ]+' in 'field list'/,
219
+ /MySqlClient\./,
220
+ /com\.mysql\.jdbc/,
221
+ /Zend_Db_(?:Adapter|Statement)_Mysqli_Exception/,
222
+ /Pdo[.\/_\\]Mysql/,
223
+ /MySqlException/
224
+ ],
225
+
226
+ sqlite: ErrorPattern[
227
+ /SQLite\/JDBCDriver/,
228
+ /SQLite\.Exception/,
229
+ /(Microsoft|System)\.Data\.SQLite\.SQLiteException/,
230
+ /Warning.*\W(?:sqlite_|SQLite3::)/,
231
+ /\[SQLITE_ERROR\]/,
232
+ /SQLite error \d+:/,
233
+ /sqlite3\.OperationalError:/,
234
+ /SQLite3::SQLException/,
235
+ /org\.sqlite\.JDBC/,
236
+ /Pdo[.\/_\\]Sqlite/,
237
+ /SQLiteException/
238
+ ],
239
+
240
+ mssql: ErrorPattern[
241
+ /Driver.* SQL[\-\_\ ]*Server/,
242
+ /OLE DB.* SQL Server/,
243
+ /\bSQL Server[^<"]+Driver/,
244
+ /Warning.*\W(?:mssql|sqlsrv)_/,
245
+ /\bSQL Server[^<"]+[0-9a-fA-F]{8}/,
246
+ /System\.Data\.SqlClient\.SqlException/,
247
+ /Exception.*\bRoadhouse\.Cms\./m,
248
+ /Microsoft SQL Native Client error '[0-9a-fA-F]{8}/,
249
+ /\[SQL Server\]/,
250
+ /ODBC SQL Server Driver/,
251
+ /ODBC Driver \d+ for SQL Server/,
252
+ /SQLServer JDBC Driver/,
253
+ /com\.jnetdirect\.jsql/,
254
+ /macromedia\.jdbc\.sqlserver/,
255
+ /Zend_Db_(?:Adapter|Statement)_Sqlsrv_Exception/,
256
+ /com\.microsoft\.sqlserver\.jdbc/,
257
+ /Pdo[.\/_\\](?:Mssql|SqlSrv)/,
258
+ /SQL(?:Srv|Server)Exception/
259
+ ],
260
+
261
+ oracle: ErrorPattern[
262
+ /\bORA-\d{5}/,
263
+ /Oracle error/,
264
+ /Oracle.*Driver/,
265
+ /Warning.*\W(?:oci|ora)_/,
266
+ /quoted string not properly terminated/,
267
+ /SQL command not properly ended/,
268
+ /macromedia\.jdbc\.oracle/,
269
+ /oracle\.jdbc/,
270
+ /Zend_Db_(?:Adapter|Statement)_Oracle_Exception/,
271
+ /Pdo[.\/_\\](?:Oracle|OCI)/,
272
+ /OracleException/
273
+ ]
274
+ }
275
+
276
+ #
277
+ # Checks if the response contains a SQL error message.
278
+ #
279
+ # @param [Net::HTTPResponse] response
280
+ # The HTTP response object to check.
281
+ #
282
+ # @return [Boolean]
283
+ # Indicates whether the response was a `500` and if the respones body
284
+ # contained a SQL error message.
285
+ #
286
+ def check_for_sql_errors(response)
287
+ if response.code == '500'
288
+ ERROR_PATTERNS.each do |database,error_pattern|
289
+ if error_pattern =~ response.body
290
+ return true
291
+ end
292
+ end
293
+ end
294
+
295
+ return false
296
+ end
297
+
298
+ #
299
+ # Returns a random ID.
300
+ #
301
+ # @return [Integer]
302
+ # A four digit ID.
303
+ #
304
+ # @api private
305
+ #
306
+ def random_id
307
+ rand(8_999) + 1_000
308
+ end
309
+
310
+ #
311
+ # Tests whether the URL is vulnerable to SQL injection, using the
312
+ # ` OR 1=1` vs. ` AND 1=0` technique.
313
+ #
314
+ # @return [Boolean]
315
+ #
316
+ # @api private
317
+ #
318
+ def test_or_true_and_false
319
+ id = random_id
320
+ response1 = exploit("OR #{id}=#{id}")
321
+ response2 = exploit("AND #{random_id}=#{random_id}")
322
+
323
+ # check for SQL errors in both responses
324
+ if check_for_sql_errors(response1) || check_for_sql_errors(response2)
325
+ return true
326
+ end
327
+
328
+ if response1.code =~ /^20[0-6]$/ && response2.code =~ /^20[0-6]$/
329
+ # the first response contained more results than the second response
330
+ return response1.body.length > response2.body.length
331
+ elsif response1.code =~ /^20[0-6]$/ && response2.code =~ /^(?:404|500)$/
332
+ # if the second response return an error, that indicates the
333
+ # SQL expression evaluated to false and returned no results.
334
+ return true
335
+ end
336
+ end
337
+
338
+ # Various SQL sleep functions or statements.
339
+ #
340
+ # @api private
341
+ SLEEP_TESTS = [
342
+ 'SLEEP(5)',
343
+ "PG_SLEEP(5)",
344
+ "WAITFOR DELAY '0:0:5'"
345
+ ]
346
+
347
+ #
348
+ # Tests whether the URL is vulnerable to SQL injection, by calling SQL
349
+ # sleep functions to see if it takes longer for the response to be
350
+ # returned.
351
+ #
352
+ # @return [Boolean]
353
+ #
354
+ # @api private
355
+ #
356
+ def test_sleep
357
+ SLEEP_TESTS.each do |sql|
358
+ [sql, ";SELECT #{sql}"].each do |sqli|
359
+ start_time = Time.now
360
+ response = exploit(sqli)
361
+ stop_time = Time.now
362
+ delta = (stop_time - start_time)
363
+
364
+ # check for SQL errors first
365
+ if check_for_sql_errors(response)
366
+ return true
367
+ end
368
+
369
+ # if the response took more than 5 seconds, our SQL sleep function
370
+ # probably worked.
371
+ return true if delta > 5.0
372
+ end
373
+ end
374
+
375
+ return false
376
+ end
377
+
378
+ #
379
+ # Returns the type or kind of vulnerability.
380
+ #
381
+ # @return [Symbol]
382
+ #
383
+ # @note
384
+ # This is used internally to map an vulnerability class to a printable
385
+ # type.
386
+ #
387
+ # @api private
388
+ #
389
+ # @abstract
390
+ #
391
+ def self.vuln_type
392
+ :sqli
393
+ end
394
+
395
+ end
396
+ end
397
+ end
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # ronin-vulns - A Ruby library for blind vulnerability testing.
4
+ #
5
+ # Copyright (c) 2022 Hal Brodigan (postmodern.mod3 at gmail.com)
6
+ #
7
+ # ronin-vulns is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Lesser General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # ronin-vulns is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Lesser General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public License
18
+ # along with ronin-vulns. If not, see <https://www.gnu.org/licenses/>.
19
+ #
20
+
21
+ require 'ronin/vulns/web_vuln'
22
+
23
+ module Ronin
24
+ module Vulns
25
+ #
26
+ # Represents a Server Side Template Injection (SSTI) vulnerability.
27
+ #
28
+ class SSTI < WebVuln
29
+ #
30
+ # Represents a expression to test SSTI with (ex: `7*7`).
31
+ #
32
+ class TestExpression
33
+
34
+ # The expression string.
35
+ #
36
+ # @return [String]
37
+ attr_reader :string
38
+
39
+ # The expected result of the string.
40
+ #
41
+ # @return [String]
42
+ attr_reader :result
43
+
44
+ #
45
+ # Initializes the test expression.
46
+ #
47
+ # @param [String] string
48
+ # The expression string.
49
+ #
50
+ # @param [String] result
51
+ # The expected result of the expression.
52
+ #
53
+ def initialize(string,result)
54
+ @string = string
55
+ @result = result
56
+ end
57
+
58
+ #
59
+ # Parses an expression string and calculates the result.
60
+ #
61
+ # @param [String] string
62
+ # The expression string to parse.
63
+ #
64
+ # @return [TestExpression]
65
+ # The parsed test expression.
66
+ #
67
+ # @raise [ArgumentError]
68
+ # Could not parse the test expression.
69
+ #
70
+ def self.parse(string)
71
+ unless (match = string.match(/\A(\d+)\s*([\*\/\+\-])\s*(\d+)\z/))
72
+ raise(ArgumentError,"could not parse the expression: #{string.inspect}")
73
+ end
74
+
75
+ lvalue = match[1].to_i
76
+ op = match[2]
77
+ rvalue = match[3].to_i
78
+
79
+ result = case op
80
+ when '*' then lvalue * rvalue
81
+ when '/' then lvalue / rvalue
82
+ when '+' then lvalue + rvalue
83
+ when '-' then lvalue - rvalue
84
+ else
85
+ raise(NotImplementedError,"unsupported expression operator: #{op.inspect}")
86
+ end
87
+
88
+ return new(string,result.to_s)
89
+ end
90
+
91
+ #
92
+ # The test expression as a String.
93
+ #
94
+ # @return [String]
95
+ # The {#string} value.
96
+ #
97
+ def to_s
98
+ @string
99
+ end
100
+
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,203 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # ronin-vulns - A Ruby library for blind vulnerability testing.
4
+ #
5
+ # Copyright (c) 2022 Hal Brodigan (postmodern.mod3 at gmail.com)
6
+ #
7
+ # ronin-vulns is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Lesser General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # ronin-vulns is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Lesser General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public License
18
+ # along with ronin-vulns. If not, see <https://www.gnu.org/licenses/>.
19
+ #
20
+
21
+ require 'ronin/vulns/web_vuln'
22
+ require 'ronin/vulns/ssti/test_expression'
23
+
24
+ module Ronin
25
+ module Vulns
26
+ #
27
+ # Represents a Server Side Template Injection (SSTI) vulnerability.
28
+ #
29
+ class SSTI < WebVuln
30
+
31
+ # List of common Server Side Template Injection (SSTI) escapes.
32
+ #
33
+ # @api private
34
+ ESCAPES = [
35
+ nil, # does not escape the expression
36
+ ->(expression) { "{{#{expression}}}" },
37
+ ->(expression) { "${#{expression}}" },
38
+ ->(expression) { "${{#{expression}}}" },
39
+ ->(expression) { "\#{#{expression}}" },
40
+ ->(expression) { "<%= #{expression} %>" }
41
+ ]
42
+
43
+ # How to escape the payload so that it's executed.
44
+ #
45
+ # @return [Proc, nil]
46
+ # The proc that will accept a String and return a String, or `nil` to
47
+ # indicate that the payload will not be escaped.
48
+ attr_reader :escape
49
+
50
+ # The test expression to use when testing the URL for SSTI.
51
+ #
52
+ # @return [TestExpression]
53
+ attr_reader :test_expr
54
+
55
+ #
56
+ # Initializes the Server Side Template Injection (SSTI) vulnerability.
57
+ #
58
+ # @param [String, URI::HTTP] url
59
+ # The URL to exploit.
60
+ #
61
+ # @param [Proc, nil] escape
62
+ # How to escape a given payload. Either a proc that will accept a String
63
+ # and return a String, or `nil` to indicate that the payload will not
64
+ # be escaped.
65
+ #
66
+ # @param [TestExpression] test_expr
67
+ # The test payload and expected result to check for when testing the URL
68
+ # for SSTI.
69
+ #
70
+ def initialize(url, escape: nil,
71
+ test_expr: self.class.random_test,
72
+ **kwargs)
73
+ super(url,**kwargs)
74
+
75
+ @escape = escape
76
+ @test_expr = test_expr
77
+
78
+ unless @test_expr
79
+ raise(ArgumentError,"must specify both a test expression")
80
+ end
81
+ end
82
+
83
+ #
84
+ # Generates a random `N*M` SSTI test.
85
+ #
86
+ # @return [TestExpression]
87
+ # A random test expression.
88
+ #
89
+ def self.random_test
90
+ int1 = rand(999) + 1_000
91
+ int2 = rand(999) + 1_000
92
+
93
+ string = "#{int1}*#{int2}"
94
+ result = (int1 * int2).to_s
95
+
96
+ return TestExpression.new(string,result)
97
+ end
98
+
99
+ #
100
+ # Scans the URL for Server Side Template Injection (SSTI) vulnerabilities.
101
+ #
102
+ # @param [URI::HTTP, String] url
103
+ # The URL to scan.
104
+ #
105
+ # @param [Hash{Symbol => Object}] kwargs
106
+ # Additional keyword arguments for {#initialize}.
107
+ #
108
+ # @option kwargs [Proc, nil] :escape
109
+ # The escape method to use. If `escape:` is not given, then all escapes
110
+ # in {ESCAPES} will be tested..
111
+ #
112
+ # @option kwargs [Array<Symbol, String>, Symbol, String, true, nil] :query_params
113
+ # The query param name(s) to test.
114
+ #
115
+ # @option kwargs [Array<Symbol, String>, Symbol, String, nil] :header_names
116
+ # The header name(s) to test.
117
+ #
118
+ # @option kwargs [Array<Symbol, String>, Symbol, String, true, nil] :cookie_params
119
+ # The cookie param name(s) to test.
120
+ #
121
+ # @option kwargs [Array<Symbol, String>, Symbol, String, nil] :form_params
122
+ # The form param name(s) to test.
123
+ #
124
+ # @option kwargs [Ronin::Support::Network::HTTP, nil] :http
125
+ # An HTTP session to use for testing the LFI.
126
+ #
127
+ # @option kwargs [Hash{String => String}, nil] :headers
128
+ # Additional headers to send with requests.
129
+ #
130
+ # @option kwargs [String, Ronin::Support::Network::HTTP::Cookie, nil] :cookie
131
+ # Additional cookie params to send with requests.
132
+ #
133
+ # @option kwargs [String, nil] :referer
134
+ # Optional `Referer` header to send with requests.
135
+ #
136
+ # @option kwargs [Hash{String => String}, nil] :form_data
137
+ # Additional form data to send with requests.
138
+ #
139
+ # @yield [vuln]
140
+ # If a block is given it will be yielded each discovered vulnerability.
141
+ #
142
+ # @yieldparam [SSTI] vuln
143
+ # A discovered SSTI vulnerability in the URL.
144
+ #
145
+ # @return [Array<SSTI>]
146
+ # All discovered SSTI vulnerabilities.
147
+ #
148
+ def self.scan(url, **kwargs,&block)
149
+ if kwargs.has_key?(:escape)
150
+ super(url, **kwargs, &block)
151
+ else
152
+ ESCAPES.each do |escape|
153
+ super(url, escape: escape, **kwargs, &block)
154
+ end
155
+ end
156
+ end
157
+
158
+ #
159
+ # Escapes the payload using {#escape}.
160
+ #
161
+ # @param [String] payload
162
+ #
163
+ # @return [String]
164
+ #
165
+ def encode_payload(payload)
166
+ if @escape then @escape.call(payload)
167
+ else payload
168
+ end
169
+ end
170
+
171
+ #
172
+ # Determine whether the URL is vulnerable to Server Side Template
173
+ # Injection (SSTI).
174
+ #
175
+ # @return [Boolean]
176
+ #
177
+ def vulnerable?
178
+ response = exploit(@test_expr.string)
179
+ body = response.body
180
+
181
+ return body.include?(@test_expr.result)
182
+ end
183
+
184
+ #
185
+ # Returns the type or kind of vulnerability.
186
+ #
187
+ # @return [Symbol]
188
+ #
189
+ # @note
190
+ # This is used internally to map an vulnerability class to a printable
191
+ # type.
192
+ #
193
+ # @api private
194
+ #
195
+ # @abstract
196
+ #
197
+ def self.vuln_type
198
+ :ssti
199
+ end
200
+
201
+ end
202
+ end
203
+ end