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,218 @@
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
+ require 'ronin/vulns/lfi'
22
+ require 'ronin/vulns/rfi'
23
+ require 'ronin/vulns/sqli'
24
+ require 'ronin/vulns/ssti'
25
+ require 'ronin/vulns/reflected_xss'
26
+ require 'ronin/vulns/open_redirect'
27
+
28
+ module Ronin
29
+ module Vulns
30
+ module URLScanner
31
+ #
32
+ # Scans a URL for web vulnerabilities.
33
+ #
34
+ # @param [URI::HTTP, String] url
35
+ # The URL to test or exploit.
36
+ #
37
+ # @option kwargs [String, Symbol, nil] :query_param
38
+ # The query param to test or exploit.
39
+ #
40
+ # @option kwargs [String, Symbol, nil] :header_name
41
+ # The HTTP Header name to test or exploit.
42
+ #
43
+ # @option kwargs [String, Symbol, nil] :cookie_param
44
+ # The `Cookie:` param name to test or exploit.
45
+ #
46
+ # @option kwargs [String, Symbol, nil] :form_param
47
+ # The form param name to test or exploit.
48
+ #
49
+ # @option kwargs [Ronin::Support::Network::HTTP, nil] :http
50
+ # An HTTP session to use for testing the URL.
51
+ #
52
+ # @option kwargs [:copy, :delete, :get, :head, :lock, :mkcol, :move,
53
+ # :options, :patch, :post, :propfind, :proppatch, :put,
54
+ # :trace, :unlock] :request_method
55
+ # The HTTP request mehtod for each request.
56
+ #
57
+ # @option kwargs [String, nil] :user
58
+ # The user to authenticate as.
59
+ #
60
+ # @option kwargs [String, nil] :password
61
+ # The password to authenticate with.
62
+ #
63
+ # @option kwargs [Hash{Symbol,String => String}, nil] :headers
64
+ # Additional HTTP header names and values to add to the request.
65
+ #
66
+ # @option kwargs [String, Hash{String => String}, nil] :cookie
67
+ # Additional `Cookie` header. If a `Hash` is given, it will be
68
+ # converted to a `String` using `Ronin::Support::Network::HTTP::Cookie`.
69
+ #
70
+ # @option kwargs [Hash, String, nil] :form_data
71
+ # The form data that may be sent in the body of the request.
72
+ #
73
+ # @option kwargs [String, nil] :referer
74
+ # The optional HTTP `Referer` header to send with each request.
75
+ #
76
+ # @param [Hash{Symbol => Object}, false] lfi
77
+ # Additional options for {LFI.scan}.
78
+ #
79
+ # @option lfi [:unix, :windows, nil] :os (:unix)
80
+ # Operating System to specifically target.
81
+ #
82
+ # @option lfi [Integer] :depth (6)
83
+ # Number of directories to escape up.
84
+ #
85
+ # @option lfi [:null_byte, :double_escape, :base64, :rot13, :zlib, nil] :filter_bypass
86
+ # Specifies which filter bypass technique to use.
87
+ #
88
+ # * `:null_byte - appends a `%00` null byte to the escaped path.
89
+ # **Note:* this technique only works on PHP < 5.3.
90
+ # * `:double_escape` - Double escapes the {LFI#escape_path}
91
+ # (ex: `....//....//`).
92
+ # * `:base64` - Base64 encodes the included local file.
93
+ # * `:rot13` - ROT13 encodes the included local file.
94
+ # * `:zlib` - Zlib compresses and Base64 encodes the included local
95
+ # file.
96
+ #
97
+ # @param [Hash{Symbol => Object}, false] rfi
98
+ # Additional options for {RFI.scan}.
99
+ #
100
+ # @option rfi [:null_byte, :double_encode, nil] :filter_bypass
101
+ # Specifies which filter bypass technique to use.
102
+ # * `:double_encode` - will cause the inclusion URL to be URI escaped
103
+ # twice.
104
+ # * `:suffix_escape` - escape any appended suffix (ex: `param + ".php"`)
105
+ # by adding a URI fragment character (`#`) to the end of the RFI
106
+ # script URL. The fragment component of the URI is not sent to the
107
+ # web server.
108
+ # * `:null_byte` - will cause the inclusion URL to be appended with a
109
+ # `%00` character. **Note:* this technique only works on PHP < 5.3.
110
+ #
111
+ # @option rfi [String, URI::HTTP, nil] :test_script_url
112
+ # The URL of the RFI test script. If not specified, it will default to
113
+ # {RFI.test_script_for}.
114
+ #
115
+ # @param [Hash{Symbol => Object}, false] sqli
116
+ # Additional options for {SQLI.scan}.
117
+ #
118
+ # @option sqli [Boolean] :escape_quote (false)
119
+ # Specifies whether to escape a quoted string value.
120
+ #
121
+ # @option sqli [Boolean] :escape_parens (false)
122
+ # Specifies whether to escape parenthesis.
123
+ #
124
+ # @option sqli [Boolean] :terminate (false)
125
+ # Specifies whether to terminate the SQL statement with `--`.
126
+ #
127
+ # @param [Hash{Symbol => Object}, false] ssti
128
+ # Additional options for {SSTI.scan}.
129
+ #
130
+ # @option ssti [Proc, nil] :escape
131
+ # How to escape a given payload. Either a proc that will accept a String
132
+ # and return a String, or `nil` to indicate that the payload will not
133
+ # be escaped.
134
+ #
135
+ # @option ssti [(String, String)] :test
136
+ # The test payload and expected result to check for when testing the URL
137
+ # for SSTI.
138
+ #
139
+ # @param [Hash{Symbol => Object}, false] reflected_xss
140
+ # Additional options for {ReflectedXSS.scan}.
141
+ #
142
+ # @param [Hash{Symbol => Object}, false] open_redirect
143
+ # Additional options for {OpenRedirect.scan}.
144
+ #
145
+ # @option open_redirect [String] :test_url (OpenRedirect.random_test_url)
146
+ # The desired redirect URL to test the URL with.
147
+ #
148
+ # @yield [vuln]
149
+ # If a block is given it will be yielded each discovered web
150
+ # vulnerability.
151
+ #
152
+ # @yieldparam [LFI, RFI, SQLI, SSTI, ReflectedXSS, OpenRedirect] vuln
153
+ # A discovered web vulnerability in the URL.
154
+ #
155
+ # @return [Array<LFI, RFI, SQLI, SSTI, ReflectedXSS, OpenRedirect>]
156
+ # All discovered Web vulnerabilities.
157
+ #
158
+ def self.scan(url, lfi: {},
159
+ rfi: {},
160
+ sqli: {},
161
+ ssti: {},
162
+ reflected_xss: {},
163
+ open_redirect: {},
164
+ **kwargs,
165
+ &block)
166
+ vulns = []
167
+
168
+ if lfi
169
+ vulns.concat(LFI.scan(url,**kwargs,**lfi,&block))
170
+ end
171
+
172
+ if rfi
173
+ vulns.concat(RFI.scan(url,**kwargs,**rfi,&block))
174
+ end
175
+
176
+ if sqli
177
+ vulns.concat(SQLI.scan(url,**kwargs,**sqli,&block))
178
+ end
179
+
180
+ if ssti
181
+ vulns.concat(SSTI.scan(url,**kwargs,**ssti,&block))
182
+ end
183
+
184
+ if reflected_xss
185
+ vulns.concat(ReflectedXSS.scan(url,**kwargs,**reflected_xss,&block))
186
+ end
187
+
188
+ if open_redirect
189
+ vulns.concat(OpenRedirect.scan(url,**kwargs,**open_redirect,&block))
190
+ end
191
+
192
+ return vulns
193
+ end
194
+
195
+ #
196
+ # Tests the URL for a Web vulnerability and returns the first found
197
+ # vulnerability.
198
+ #
199
+ # @param [URI::HTTP, String] url
200
+ # The URL to test.
201
+ #
202
+ # @param [Hash{Symbol => Object}] kwargs
203
+ # Additional keyword arguments for {scan}.
204
+ #
205
+ # @return [LFI, RFI, SQLI, SSTI, ReflectedXSS, OpenRedirect, nil]
206
+ # The first discovered web vulnerability or `nil` if no vulnerabilities
207
+ # were discovered.
208
+ #
209
+ def self.test(url,**kwargs)
210
+ scan(url,**kwargs) do |vuln|
211
+ return vuln
212
+ end
213
+
214
+ return nil
215
+ end
216
+ end
217
+ end
218
+ end
@@ -0,0 +1,26 @@
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
+ # The ronin-vulns version
24
+ VERSION = '0.1.0.beta1'
25
+ end
26
+ end
@@ -0,0 +1,49 @@
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
+ module Ronin
22
+ module Vulns
23
+ #
24
+ # Base class for all vulnerability classes.
25
+ #
26
+ # @abstract
27
+ #
28
+ class Vuln
29
+
30
+ #
31
+ # Returns the type or kind of vulnerability.
32
+ #
33
+ # @return [Symbol]
34
+ #
35
+ # @note
36
+ # This is used internally to map an vulnerability class to a printable
37
+ # type.
38
+ #
39
+ # @api private
40
+ #
41
+ # @abstract
42
+ #
43
+ def self.vuln_type
44
+ raise(NotImplementedError,"#{self}.vuln_type was not implemented")
45
+ end
46
+
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,223 @@
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/vuln'
23
+ require 'ronin/support/network/http/cookie'
24
+
25
+ require 'uri/query_params'
26
+
27
+ module Ronin
28
+ module Vulns
29
+ class WebVuln < Vuln
30
+ #
31
+ # Represents a HTTP request.
32
+ #
33
+ # @api private
34
+ #
35
+ class HTTPRequest
36
+
37
+ # The URL of the request.
38
+ #
39
+ # @return [URI::HTTP]
40
+ attr_reader :url
41
+
42
+ # The HTTP request method.
43
+ #
44
+ # @return [:copy, :delete, :get, :head, :lock, :mkcol, :move,
45
+ # :options, :patch, :post, :propfind, :proppatch, :put,
46
+ # :trace, :unlock]
47
+ attr_reader :request_method
48
+
49
+ # The user to authenticate as.
50
+ #
51
+ # @return [String, nil]
52
+ attr_reader :user
53
+
54
+ # The password to authenticate with.
55
+ #
56
+ # @return [String, nil]
57
+ attr_reader :password
58
+
59
+ # The optional HTTP `Referer` header for the request.
60
+ #
61
+ # @return [String, nil]
62
+ attr_reader :referer
63
+
64
+ # The query param for the request.
65
+ #
66
+ # @return [Hash{String,Symbol => String}, nil]
67
+ attr_reader :query_params
68
+
69
+ # Additional `Cookie` header for the request.
70
+ #
71
+ # @return [Ronin::Support::Network::HTTP::Cookie, nil]
72
+ attr_reader :cookie
73
+
74
+ # Additional HTTP header names and values to add to the request.
75
+ #
76
+ # @return [Hash{Symbol,String => String}, nil]
77
+ attr_reader :headers
78
+
79
+ # The form data that may be sent in the body of the request.
80
+ #
81
+ # @return [Hash{String => Object}, nil]
82
+ attr_reader :form_data
83
+
84
+ #
85
+ # Initializes the HTTP request object.
86
+ #
87
+ # @param [URI::HTTP] url
88
+ # The URL to test or exploit.
89
+ #
90
+ # @param [:copy, :delete, :get, :head, :lock, :mkcol, :move,
91
+ # :options, :patch, :post, :propfind, :proppatch, :put,
92
+ # :trace, :unlock] request_method
93
+ # The HTTP request mehtod for each request.
94
+ #
95
+ # @param [String, nil] user
96
+ # The user to authenticate as.
97
+ #
98
+ # @param [String, nil] password
99
+ # The password to authenticate with.
100
+ #
101
+ # @param [Hash{Symbol,String => String}, nil] query_params
102
+ # Additional URL query params for the request.
103
+ #
104
+ # @param [Hash{Symbol,String => String}, nil] headers
105
+ # Additional HTTP header names and values to add to the request.
106
+ #
107
+ # @param [String, Hash{String => String}, nil] cookie
108
+ # Additional `Cookie` header for the request..
109
+ #
110
+ # @param [Hash, nil] form_data
111
+ # The form data that may be sent in the body of the request.
112
+ #
113
+ def initialize(url, request_method: :get,
114
+ user: nil,
115
+ password: nil,
116
+ referer: nil,
117
+ query_params: nil,
118
+ headers: nil,
119
+ cookie: nil,
120
+ form_data: nil)
121
+ @url = url
122
+
123
+ if query_params && !query_params.empty?
124
+ @url = url.dup
125
+ @url.query_params = query_params
126
+ end
127
+
128
+ @request_method = request_method
129
+ @user = user
130
+ @password = password
131
+ @referer = referer
132
+
133
+ @query_params = query_params
134
+ @cookie = if cookie
135
+ Support::Network::HTTP::Cookie.new(cookie)
136
+ end
137
+ @headers = headers
138
+ @form_data = form_data
139
+ end
140
+
141
+ #
142
+ # Converts the HTTP request to a `curl` command.
143
+ #
144
+ # @return [String]
145
+ #
146
+ def to_curl
147
+ escape = ->(str) { "'#{str.to_s.tr("'","\\'")}'" }
148
+
149
+ command = ['curl']
150
+
151
+ if @request_method != :get
152
+ command << '--request' << @request_method.upcase
153
+ end
154
+
155
+ if (@user || @password)
156
+ command << '--user' << escape.call("#{@user}:#{@password}")
157
+ end
158
+
159
+ if @referer
160
+ command << '--referer' << escape.call(@referer)
161
+ end
162
+
163
+ if (@cookie && !@cookie.empty?)
164
+ command << '--cookie' << escape.call(@cookie)
165
+ end
166
+
167
+ if @headers
168
+ @headers.each do |name,value|
169
+ command << '--header' << escape.call("#{name}: #{value}")
170
+ end
171
+ end
172
+
173
+ if (@form_data && !@form_data.empty?)
174
+ form_string = URI.encode_www_form(@form_data)
175
+ command << '--form-string' << escape.call(form_string)
176
+ end
177
+
178
+ command << escape.call(@url)
179
+
180
+ return command.join(' ')
181
+ end
182
+
183
+ # HTTP newline deliminator.
184
+ CRLF = "\r\n"
185
+
186
+ #
187
+ # Converts the HTTP request to a raw HTTP request.
188
+ #
189
+ # @return [String]
190
+ #
191
+ def to_http
192
+ request = []
193
+ request << "#{@request_method.upcase} #{@url.request_uri} HTTP/1.1"
194
+
195
+ if (@form_data && !@form_data.empty?)
196
+ request << "Content-Type: x-www-form-urlencoded"
197
+ end
198
+
199
+ if (@user || @password)
200
+ basic_auth = ["#{@user}:#{@password}"].pack('m0')
201
+ request << "Authorization: Basic #{basic_auth}"
202
+ end
203
+
204
+ request << "Referer: #{@referer}" if @referer
205
+ request << "Cookie: #{@cookie}" if (@cookie && !@cookie.empty?)
206
+
207
+ if @headers
208
+ @headers.each do |name,value|
209
+ request << "#{name}: #{value}"
210
+ end
211
+ end
212
+
213
+ if (@form_data && !@form_data.empty?)
214
+ request << ''
215
+ request << URI.encode_www_form(@form_data)
216
+ end
217
+
218
+ return request.join(CRLF) << CRLF
219
+ end
220
+ end
221
+ end
222
+ end
223
+ end