High
CVE-2023-21768
CVE ID
AttackerKB requires a CVE ID in order to pull vulnerability data and references from the CVE list and the National Vulnerability Database. If available, please supply below:
Add References:
CVE-2023-21768
MITRE ATT&CK
Collection
Command and Control
Credential Access
Defense Evasion
Discovery
Execution
Exfiltration
Impact
Initial Access
Lateral Movement
Persistence
Privilege Escalation
Topic Tags
Description
Windows Ancillary Function Driver for WinSock Elevation of Privilege Vulnerability
Add Assessment
Ratings
-
Attacker ValueHigh
-
ExploitabilityMedium
Technical Analysis
Interesting bug that was announced on Twitter at https://twitter.com/chompie1337/status/1633498392125997056 and later posted on GitHub at https://github.com/xforcered/Windows_LPE_AFD_CVE-2023-21768. Bug occurs in afd.sys
which is the Windows Ancillary Function Driver for WinSock, and allows privilege escalation from a local user to NT AUTHORITY\SYSTEM
.
Whats interesting about this bug though is that unlike other EoP bugs, this only seems to affect Windows 11 and Windows Server 2022 according to https://msrc.microsoft.com/update-guide/en-US/vulnerability/CVE-2023-21768. Additionally the exploit at https://github.com/chompie1337/Windows_LPE_AFD_CVE-2023-21768 is noted to only work on vulnerable Windows 11 22H2 systems, which raises the question of if there were some specific items that needed to be hardcoded for a specific version of Windows, such as offsets or similar.
The current exploit that is available, from my brief look at things, appears to use the I/O Ring R/W primitive that Yarden Shafir talked about at https://windows-internals.com/one-i-o-ring-to-rule-them-all-a-full-read-write-exploit-primitive-on-windows-11/ and later released a PoC on at https://github.com/yardenshafir/IoRingReadWritePrimitive. I’m somewhat surprised that Microsoft still hasn’t patched this several months later given how strict they have been at trying to fix such items in the past, but these things typically require complicated change to the OS so perhaps I shouldn’t be all too surprised, particularly given its dealing with I/O buffers which are heavily utilized.
After leaking some addresses it appears to do the standard SYSTEM token replacement using the leaked EPROCESS address of the SYSTEM process and then takes that security token and replaces the chosen processes’s security token with the SYSTEM security token. Note I say chosen here as the exploit takes a PID as an argument and uses that PID to find out which process’s token it should replace with the SYSTEM security token.
Looking closer at the exploit to perform some of the leaks there seems to be a reference to NtQuerySystemInformation
which is commonly used for leaking information, however I don’t actually see that being used anywhere, so it looks like it is potentially left over code.
The main vulnerability exploit code appears to be centralized into ArbitraryKernelWrite0x1
in https://github.com/xforcered/Windows_LPE_AFD_CVE-2023-21768/blob/master/Windows_AFD_LPE_CVE-2023-21768/exploit.c, which is then used to overwrite some entries in the IO ring buffer to transform it from arbitrary kernel write to arbitrary kernel read and write.
Looking into ArbitrarykernelWrite0x1
it seems it takes in a pointer to the address to overwrite, then creates an IPv4 extended TCP socket attribute structure, creates an IoCompletion object using NtCreateIoCompletion
that allows for both querying and modifying the state, and allows one thread of concurrent access to the object.
We then call NtSetIoCompletion
(documented to some degree at http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/IoCompletion/NtSetIoCompletion.html) on the same object with a completion key of 0x1337
and pass it the empty IO_STATUS_BLOCK
object IoStatusBlock
so we can keep track of the IO status of this IoCompletion object. We set the completion status to 0, aka not completed, and set the number of bytes transferred in a manually finished I/O operation to 0x100. Not sure why this value was chosen but eh.
If this completes successfully, then we go ahead and make a UNICODE_STRING called ObjectFilePath
that holds the string \\Device\\Afd\\Endpoint
, which according “Reverse Engineering Windows AFD.sys” by Steven Vittitoe which was presented at Recon 2015 at https://recon.cx/2015/slides/recon2015-20-steven-vittitoe-Reverse-Engineering-Windows-AFD-sys.pdf, is an endpoint that allows access to 70+ IOCTLs that are defined within the afd.sys
driver.
Looking more at this paper we can also see that AFD.sys handles everything from TCP/IP to SAN and that its listed as the “Ring 0 entrypoint for WinSock”, aka all WinSock calls will end up going through this driver which executes at the kernel level. This is backed up by their point that it handles all socket()
calls.
Anyway getting back to this we can see we also set an OBJECT_ATTRIBUTES object to the name of this string as the ObjectName
parameter, and then set its attributes to 0x40, aka OBJ_CASE_INSENSITIVE as noted at http://www.jasinskionline.com/technicalwiki/Print.aspx?Page=Constants-Windows-API&AspxAutoDetectCookieSupport=1, as I guess we need case insensitive operations for this? Idk though without further info.
Finally we call NtCreateFile
to create this file and save the handle into hSocket
. We ask for the maximium permissions possible on this object, pass in the ObjectAttributes
object attributes object we created earlier so that we use the \\Device\\Afd\\Endpoint
and use case insensitive naming, pass in the IoStatusBlock
for the I/O completion object, allow read and write sharing, pass in nothing for the creation options since this device should already be created, and pass in 1 aka FILE_OPEN so we open the existing file. Finally we pass in bExtendedAttributes
which will hold the hardcoded extended attributes for a IPv4 TCP socket.
If all goes well then we should now have an file handle in hSocket
however the AFD driver still isn’t fully aware of this socket. To complete this we then create a new Data
object of type AFD_NOTIFYSOCK_DATA
. This object type is not publicly documented anywhere as far as I can tell, and appears to have been guessed at via reverse engineering. In this structure we can see that we have a few pointers, a handle to hCompletion
which explains our earlier completion object creation call, and some DWORDs.
The next few lines of the code will set the hCompletion
parameter of this structure to the hCompletion
object we created earlier, and after this we set pData1
and pData2
to 0x2000 byte long heap buffers that are readable and writeable and which have been reserved and committed in memory.
We then set dwCounter
to 1 to indicate one entry, and set dwLen
to 1. Not sure what dwLen
controls though but we’ll have to wait for the blog for more details. We interestingly set dwTimeout
to an insanely large value of 100000000
. Its possible this may be related to an overflow which leads to the out of bound write, or it could be set this way to hold the connection open whilst the exploit happens and prevent timeouts. Finally we see that the address we wish to overwrite is placed into Data.pPwnPtr
suggesting that this structure is responsible for the arbitrary overwrite and perhaps doesn’t validate that the address is actually a kernel address and not a user address like it should be.
Finally we create an event using CreateEvent
and then call IOCTL 0x12127 on AFD, which the exploit notes as AFD_NOTIFYSOCK_IOCTL. My guess is that this processes the malicious Data
structure of type AFD_NOTIFYSOCK_DATA
and then fails to notice that the Data.pPwnPtr
is out of the expected address range, allowing for an arbitrary write vulnerability.
Would you also like to delete your Exploited in the Wild Report?
Delete Assessment Only Delete Assessment and Exploited in the Wild ReportCVSS V3 Severity and Metrics
General Information
Vendors
- microsoft
Products
- windows 11 21h2,
- windows 11 22h2,
- windows server 2022 -
Exploited in the Wild
Would you like to delete this Exploited in the Wild Report?
Yes, delete this reportWould you like to delete this Exploited in the Wild Report?
Yes, delete this reportReferences
Exploit
A PoC added here by the AKB Worker must have at least 2 GitHub stars.
Additional Info
Technical Analysis
Report as Emergent Threat Response
Report as Exploited in the Wild
CVE ID
AttackerKB requires a CVE ID in order to pull vulnerability data and references from the CVE list and the National Vulnerability Database. If available, please supply below: