ronin-vulns 0.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
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,149 @@
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
+
24
+ module Ronin
25
+ module Vulns
26
+ class ReflectedXSS < WebVuln
27
+ #
28
+ # A test string of characters to determine which special characters are
29
+ # escaped/filtered and which are passed through.
30
+ #
31
+ # @api private
32
+ #
33
+ class TestString
34
+
35
+ # The test string.
36
+ #
37
+ # @return [String]
38
+ attr_reader :string
39
+
40
+ # The test regexp to determine which special characters were
41
+ # escaped/filtered and which were passed through unescaped.
42
+ #
43
+ # @return [Regexp]
44
+ attr_reader :regexp
45
+
46
+ #
47
+ # Initializes the test string.
48
+ #
49
+ # @param [String] string
50
+ # The test string.
51
+ #
52
+ # @param [Regexp] regexp
53
+ # The test regexp to determine which special characters were
54
+ # escaped/filtered and which were passed through unescaped.
55
+ #
56
+ def initialize(string,regexp)
57
+ @string = string
58
+ @regexp = regexp
59
+ end
60
+
61
+ # Special characters and their common escaped equivalents.
62
+ ESCAPED_CHARS = {
63
+ "'" => ['%27', '&#39;', "\\'"],
64
+ '"' => ['%22', '&quot;', "\\\""],
65
+ ' ' => ['+', '%20', '&nbsp;'],
66
+ '=' => ['%3D'],
67
+ '/' => ['%2F'],
68
+ '<' => ['%3C', '&lt;'],
69
+ '>' => ['%3E', '&gt;'],
70
+ '&' => ['%26', '&amp;'],
71
+ }
72
+
73
+ #
74
+ # Builds a test string from a mapping of characters and their HTML
75
+ # escaped equivalents.
76
+ #
77
+ # @param [String] chars
78
+ # The characters for the test string.
79
+ #
80
+ # @return [TestString]
81
+ # The built test string.
82
+ #
83
+ def self.build(chars)
84
+ string = String.new
85
+ regexp = String.new
86
+
87
+ chars.each_char do |char|
88
+ string << char
89
+
90
+ regexp << "(?:(#{Regexp.escape(char)})"
91
+
92
+ if (escaped_chars = ESCAPED_CHARS[char])
93
+ escaped_chars.each do |string|
94
+ regexp << "|#{Regexp.escape(string)}"
95
+ end
96
+ end
97
+
98
+ regexp << ')?'
99
+ end
100
+
101
+ return new(string,Regexp.new(regexp))
102
+ end
103
+
104
+ #
105
+ # Wraps the test string with a prefix and suffix.
106
+ #
107
+ # @param [String] prefix
108
+ # The prefix string to prepend to the test string.
109
+ #
110
+ # @param [String] suffix
111
+ # The suffix string to append to the test string.
112
+ #
113
+ # @return [TestString]
114
+ # The new test string with the prefix and suffix.
115
+ #
116
+ def wrap(prefix,suffix)
117
+ self.class.new(
118
+ "#{prefix}#{@string}#{suffix}",
119
+ /#{Regexp.escape(prefix)}#{@regexp}#{Regexp.escape(suffix)}/
120
+ )
121
+ end
122
+
123
+ #
124
+ # Matches the response body against {#regexp}.
125
+ #
126
+ # @param [String] body
127
+ # The response body to try matching.
128
+ #
129
+ # @return [MatchData, nil]
130
+ # The match data or `nil` if the body did not match {#regexp}.
131
+ #
132
+ def match(body)
133
+ body.match(@regexp)
134
+ end
135
+
136
+ #
137
+ # Converts the test string to a String.
138
+ #
139
+ # @return [String]
140
+ # The {#string}.
141
+ #
142
+ def to_s
143
+ @string
144
+ end
145
+
146
+ end
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,184 @@
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/reflected_xss/test_string'
24
+ require 'ronin/vulns/reflected_xss/context'
25
+
26
+ require 'set'
27
+
28
+ module Ronin
29
+ module Vulns
30
+ #
31
+ # Represents a (Reflected) Cross Site Scripting (XSS) vulnerability.
32
+ #
33
+ # ## Features
34
+ #
35
+ # * Tests a URL with just one HTTP request (per param).
36
+ # * Tests which HTML special characters are allowed.
37
+ # * Identifies the context, tag name, and/or attribute name of the XSS.
38
+ # * Determines viability of XSS based on the context.
39
+ # * Includes random data in the test values.
40
+ #
41
+ class ReflectedXSS < WebVuln
42
+
43
+ # The characters that are allowed and will not be escaped or filtered.
44
+ #
45
+ # @return [Set<String>, nil]
46
+ attr_reader :allowed_chars
47
+
48
+ # The context the XSS occurred in.
49
+ #
50
+ # @return [Context, nil]
51
+ attr_reader :context
52
+
53
+ #
54
+ # Tests the test string by sending an HTTP request with the test string
55
+ # embedded.
56
+ #
57
+ # @param [TestString] test_string
58
+ #
59
+ # @yield [body, match]
60
+ # If the response was `text/html` and the test string appears (at least
61
+ # partially) in the response body, the response body and match data will
62
+ # be yielded.
63
+ #
64
+ # @yieldparam [String] body
65
+ # The response body.
66
+ #
67
+ # @yieldparam [MatchData] match
68
+ # The matched data for the test string.
69
+ #
70
+ # @api private
71
+ #
72
+ def test_string(test_string)
73
+ test_string = test_string.wrap(random_value,random_value)
74
+
75
+ response = exploit("#{original_value}#{test_string}")
76
+ content_type = response.content_type
77
+ body = response.body
78
+
79
+ if content_type && content_type.include?('text/html')
80
+ if (match = test_string.match(body))
81
+ yield body, match
82
+ end
83
+ end
84
+ end
85
+
86
+ #
87
+ # Tests whether characters in the test string will be escaped/filtered or
88
+ # passed through and updates {#allowed_chars}.
89
+ #
90
+ # @param [TestString] test_string
91
+ # The test string to send.
92
+ #
93
+ # @yield [body, match]
94
+ # If a block is given, it will be passed the response body and the
95
+ # regular expression match data, if the response contains the test
96
+ # string.
97
+ #
98
+ # @yieldparam [String] body
99
+ # The response body.
100
+ #
101
+ # @yieldparam [MatchData] match
102
+ # The matched data for the test string.
103
+ #
104
+ # @api private
105
+ #
106
+ def test_chars(test_string)
107
+ test_string(test_string) do |body,match|
108
+ @allowed_chars ||= Set.new
109
+ @allowed_chars.merge(match.captures.compact)
110
+
111
+ yield body, match if block_given?
112
+ end
113
+ end
114
+
115
+ # HTML special characters to test.
116
+ HTML_TEST_STRING = TestString.build("'\"= /><")
117
+
118
+ #
119
+ # Tests which HTML characters are accepted or escaped/filtered.
120
+ #
121
+ # @yield [body, match]
122
+ # If a block is given, it will be passed the response body and the
123
+ # regular expression match data, if the response contains the test
124
+ # string.
125
+ #
126
+ # @yieldparam [String] body
127
+ # The response body.
128
+ #
129
+ # @yieldparam [MatchData] match
130
+ # The matched data for the test string.
131
+ #
132
+ # @api private
133
+ #
134
+ def test_html_chars(&block)
135
+ test_chars(HTML_TEST_STRING,&block)
136
+ end
137
+
138
+ #
139
+ # Tests whether the URL is vulnerable to (Reflected) Cross Site Scripting
140
+ # (XSS).
141
+ #
142
+ # @return [Boolean]
143
+ # Indicates whether the URL is vulnerable to (Reflected) Cross Site
144
+ # Scripting (XSS).
145
+ #
146
+ # @note
147
+ # If the URL is vulnerable, {#allowed_chars} and {#context} will be set.
148
+ #
149
+ def vulnerable?
150
+ # test HTML special characters
151
+ test_html_chars do |body,match|
152
+ xss_index = match.begin(0)
153
+
154
+ # determine the contents which the XSS occurs
155
+ if (@context = Context.identify(body,xss_index))
156
+ # determine whether enough special HTML characters are allowed to
157
+ # escape the context which the XSS occurs.
158
+ return @context.viable?(@allowed_chars)
159
+ end
160
+ end
161
+
162
+ return false
163
+ end
164
+
165
+ #
166
+ # Returns the type or kind of vulnerability.
167
+ #
168
+ # @return [Symbol]
169
+ #
170
+ # @note
171
+ # This is used internally to map an vulnerability class to a printable
172
+ # type.
173
+ #
174
+ # @api private
175
+ #
176
+ # @abstract
177
+ #
178
+ def self.vuln_type
179
+ :reflected_xss
180
+ end
181
+
182
+ end
183
+ end
184
+ end
@@ -0,0 +1,224 @@
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/version'
23
+
24
+ require 'ronin/support/network/http'
25
+ require 'uri/query_params'
26
+
27
+ module Ronin
28
+ module Vulns
29
+ #
30
+ # Represents a Remote File Inclusion (RFI) vulnerability.
31
+ #
32
+ class RFI < WebVuln
33
+
34
+ # The script extensions and their languages
35
+ URL_EXTS = {
36
+ '.asp' => :asp,
37
+ '.aspx' => :asp_net,
38
+ '.cfm' => :cold_fusion,
39
+ '.cfml' => :cold_fusion,
40
+ '.jsp' => :jsp,
41
+ '.php' => :php,
42
+ '.pl' => :perl
43
+ }
44
+
45
+ # The github.com base URL for all RFI test scripts.
46
+ GITHUB_BASE_URL = "https://raw.githubusercontent.com/ronin-rb/ronin-vulns/#{VERSION}/data"
47
+
48
+ # Mapping of scripting languages to RFI test scripts.
49
+ TEST_SCRIPT_URLS = {
50
+ asp: "#{GITHUB_BASE_URL}/rfi_test.asp",
51
+ asp_net: "#{GITHUB_BASE_URL}/rfi_test.aspx",
52
+ cold_fusion: "#{GITHUB_BASE_URL}/rfi_test.cfm",
53
+ jsp: "#{GITHUB_BASE_URL}/rfi_test.jsp",
54
+ php: "#{GITHUB_BASE_URL}/rfi_test.php",
55
+ perl: "#{GITHUB_BASE_URL}/rfi_test.pl"
56
+ }
57
+
58
+ # The string that will be returned if the Remote File Inclusion (RFI)
59
+ # script is executed.
60
+ VULN_RESPONSE_STRING = "Security Alert: Remote File Inclusion Detected!"
61
+
62
+ # The filter bypass technique to use.
63
+ #
64
+ # @return [nil, :double_encode, :suffix_escape, :null_byte]
65
+ attr_reader :filter_bypass
66
+
67
+ # URL of the Remote File Inclusion (RFI) Test script
68
+ #
69
+ # @return [URI::HTTP, String]
70
+ attr_reader :test_script_url
71
+
72
+ #
73
+ # Creates a new Remote File Inclusion (RFI) object.
74
+ #
75
+ # @param [String, URI::HTTP] url
76
+ # The URL to attempt to exploit.
77
+ #
78
+ # @param [:null_byte, :double_encode, nil] filter_bypass
79
+ # Specifies which filter bypass technique to use.
80
+ # * `:double_encode` - will cause the inclusion URL to be URI escaped
81
+ # twice.
82
+ # * `:suffix_escape` - escape any appended suffix (ex: `param + ".php"`)
83
+ # by adding a URI fragment character (`#`) to the end of the RFI
84
+ # script URL. The fragment component of the URI is not sent to the
85
+ # web server.
86
+ # * `:null_byte` - will cause the inclusion URL to be appended with a
87
+ # `%00` character. **Note:* this technique only works on PHP < 5.3.
88
+ #
89
+ # @param [:asp, :asp_net, :cold_fusion, :jsp, :php, :perl, nil] script_lang
90
+ # Explicitly specifies the scripting language that the URL uses.
91
+ #
92
+ # @param [String, URI::HTTP, nil] test_script_url
93
+ # The URL of the RFI test script. If not specified, it will default to
94
+ # {test_script_for}.
95
+ #
96
+ def initialize(url, script_lang: nil, test_script_url: nil, filter_bypass: nil, **kwargs)
97
+ super(url,**kwargs)
98
+
99
+ @test_script_url = if test_script_url
100
+ test_script_url
101
+ elsif script_lang
102
+ self.class.test_script_url_for(script_lang)
103
+ else
104
+ self.class.test_script_for(@url)
105
+ end
106
+
107
+ @filter_bypass = filter_bypass
108
+ end
109
+
110
+ #
111
+ # Returns the test script URL for the given scripting language.
112
+ #
113
+ # @param [:asp, :asp_net, :cold_fusion, :jsp, :php, :perl] script_lang
114
+ # The scripting language.
115
+ #
116
+ # @return [String]
117
+ # The test script URL for the given scripting language.
118
+ #
119
+ # @raise [ArgumentError]
120
+ # An unknown scripting language value was given.
121
+ #
122
+ def self.test_script_url_for(script_lang)
123
+ TEST_SCRIPT_URLS.fetch(script_lang) do
124
+ raise(ArgumentError,"unknown scripting language: #{script_lang.inspect}")
125
+ end
126
+ end
127
+
128
+ #
129
+ # Attempts to infer the programming language used for the web page at the
130
+ # given URL.
131
+ #
132
+ # @param [String, URI::HTTP] url
133
+ # The URL to infer from.
134
+ #
135
+ # @return [:asp, :cold_fusion, :jsp, :php, :perl, nil]
136
+ # The programming language inferred from the URL.
137
+ #
138
+ def self.infer_script_lang(url)
139
+ url = URI(url)
140
+
141
+ return URL_EXTS[File.extname(url.path)]
142
+ end
143
+
144
+ #
145
+ # Selects the RFI test script for the scripting language used by the given
146
+ # URL.
147
+ #
148
+ # @param [String, URI::HTTP] url
149
+ # The URL to test.
150
+ #
151
+ # @return [String, nil]
152
+ # The RFI test script URL or `nil` if the scripting language could not
153
+ # be inferred from the URL.
154
+ #
155
+ def self.test_script_for(url)
156
+ if (lang = infer_script_lang(url))
157
+ TEST_SCRIPT_URLS.fetch(lang)
158
+ end
159
+ end
160
+
161
+ #
162
+ # Optionally applies a filter bypass technique to the RFI URL.
163
+ #
164
+ # @param [URI::HTTP, String] url
165
+ # The RFI URL to optionall encode before it will be injected into a
166
+ # HTTP request.
167
+ #
168
+ # @return [String]
169
+ # The optionally encoded RFI URL.
170
+ #
171
+ def encode_payload(url)
172
+ url = url.to_s
173
+
174
+ case @filter_bypass
175
+ when :double_encode
176
+ # Optionally double URI encodes the script URL
177
+ url = URI::QueryParams.escape(url)
178
+ when :suffix_escape
179
+ # Optionally append a '#' character to escape any appended suffixes
180
+ # (ex: `param + ".php"`).
181
+ url = "#{url}#"
182
+ when :null_byte
183
+ # Optionally append a null-byte
184
+ # NOTE: uri-query_params will automatically URI encode the null byte
185
+ url = "#{url}\0"
186
+ end
187
+
188
+ return url
189
+ end
190
+
191
+ #
192
+ # Tests whether the URL and query parameter are vulnerable to Remote File
193
+ # Inclusion (RFI).
194
+ #
195
+ # @return [Boolean]
196
+ # Specifies whether the URL and query parameter are vulnerable to RFI.
197
+ #
198
+ def vulnerable?
199
+ response = exploit(@test_script_url)
200
+ body = response.body
201
+
202
+ return body.include?(VULN_RESPONSE_STRING)
203
+ end
204
+
205
+ #
206
+ # Returns the type or kind of vulnerability.
207
+ #
208
+ # @return [Symbol]
209
+ #
210
+ # @note
211
+ # This is used internally to map an vulnerability class to a printable
212
+ # type.
213
+ #
214
+ # @api private
215
+ #
216
+ # @abstract
217
+ #
218
+ def self.vuln_type
219
+ :rfi
220
+ end
221
+
222
+ end
223
+ end
224
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # ronin-vulns - A Ruby library for blind vulnerability testing.
4
+ #
5
+ # Copyright (c) 2007-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
+ module Ronin
22
+ module Vulns
23
+ # Path to `ronin-vulns` root directory.
24
+ #
25
+ # @api private
26
+ ROOT = File.expand_path(File.join(__dir__,'..','..','..'))
27
+ end
28
+ end
@@ -0,0 +1,89 @@
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
+ class SQLI < WebVuln
26
+ #
27
+ # Represents a collection of patterns for SQL error messages for a
28
+ # particular database.
29
+ #
30
+ # @api private
31
+ #
32
+ class ErrorPattern
33
+
34
+ # The combined error message regexp.
35
+ #
36
+ # @return [Regexp]
37
+ attr_reader :regexp
38
+
39
+ #
40
+ # Initializes the error pattern.
41
+ #
42
+ # @param [Regexp] regexp
43
+ # The combined of regular expression.
44
+ #
45
+ def initialize(regexp)
46
+ @regexp = regexp
47
+ end
48
+
49
+ #
50
+ # Creates an error pattern from multiple different regexps.
51
+ #
52
+ # @param [Array<Regexp>] regexps
53
+ # The collection of regular expressions.
54
+ #
55
+ def self.[](*regexps)
56
+ new(Regexp.union(regexps))
57
+ end
58
+
59
+ #
60
+ # Tests whether the respones body contains a SQL error.
61
+ #
62
+ # @param [String] response_body
63
+ # The HTTP response body.
64
+ #
65
+ # @return [MatchData, nil]
66
+ # The match data if the {#regexp} is found within the response body.
67
+ #
68
+ def match(response_body)
69
+ @regexp.match(response_body)
70
+ end
71
+
72
+ #
73
+ # Tests whether the file was successfully included into the response
74
+ # body.
75
+ #
76
+ # @param [String] response_body
77
+ # The HTTP response body.
78
+ #
79
+ # @return [Integer, nil]
80
+ # Indicates whether the {#regexp} was found in the response body.
81
+ #
82
+ def =~(response_body)
83
+ response_body =~ @regexp
84
+ end
85
+
86
+ end
87
+ end
88
+ end
89
+ end