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,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