In this excerpt of a Trend Micro Vulnerability Research Service vulnerability report, Guy Lederfein and Quintin Crist of the Trend Micro Research Team detail a recently patched remote code execution vulnerability in the Microsoft Windows operating system, originally discovered and reported by Yuki Chen. The bug is found in the implementation of Network File System (NFS)and is due to improper handling of NFSv4 requests. An unauthenticated attacker could exploit this bug to execute arbitrary code in the context of SYSTEM. The following is a portion of their write-up covering CVE-2022-30136, with a few minimal modifications.
A remote code execution vulnerability exists in Windows Network File System. The vulnerability is due to improper handling of NFSv4 requests.
A remote attacker can exploit this vulnerability by sending malicious RPC calls to a target server. Successful exploitation results in arbitrary code execution in the context of SYSTEM. Unsuccessful exploitation may result in a crash of the target system.
The Vulnerability
Microsoft Windows ships with several network features designed to communicate and interact with non-Windows file shares. One of these modules is called Network File System (NFS).
NFS is a network file system protocol originally developed by Sun Microsystems in 1984. Version 2 is documented in RFC 1094. Version 3 is documented in RFC 1813. Version 4 was developed by the IETF and is documented in RFC 3010 (released December 2000) and revised in RFC 3530 (released April 2003) and RFC 7530 (released March 2015). NFS allows users to access remote file shares in the same way that the local file system is accessed. Different access levels and permissions can be set on the share, such as read-write and read-only. Additionally, IP/UID/GID/Kerberos security can be used. NFS uses Open Network Computing (ONC) Remote Procedure Call (RPC) to exchange control messages. ONC RPC was originally developed by Sun Microsystems and can also be referred to as Sun RPC.
When ONC RPC messages are transferred over TCP, they are prepended with a Fragment header structure (as illustrated in the following table) that specifies the length of the message. This allows the receiver to distinguish multiple messages sent over a single TCP session. Other protocols such as UDP do not use this field. Note that all multi-byte values are encoded in big-endian byte order.
The structure of ONC RPC request messages, in general, is as follows:
The Credentials structure in a Sun-RPC message has the following structure:
The Flavor field in the above structure serves as a type identifier of the Contents data. Security flavors have been called authentication flavors for historical reasons. There are multiple security flavors defined in the RPC specification, such as AUTH_NONE(0), AUTH_SYS(1), AUTH_SHORT(2), AUTH_DH(3), and RPCSEC_GSS(6).
The Contents field for the flavor RPCSEC_GSS has the following structure:
There are four types such as RPCSEC_GSS_DATA(0), RPCSEC_GSS_INIT(1), RPCSEC_GSS_CONTINUE_INIT(2), and RPCSEC_GSS_DESTROY(3) defined in the GSS Procedure field. Also, in the GSS Service field, there are three types: rpc_gss_svc_none(1), rpc_gss_svc_integrity(2), and rpc_gss_svc_privacy(3). When using RPCSEC_GSS to authenticate the RPC clients, a security context must be created by using RPCSEC_GSS_INIT and RPCSEC_GSS_CONTINUE_INIT RPC messages. First, the RPC client sends an RPCSEC_GSS_INIT message to start the creation of the context. Then, the RPC server decides whether it needs another token for the creation. If so, the server replies with a GSS_S_CONTINUE_NEEDED message, and the client needs to send an RPCSEC_GSS_CONTINUE_INIT message to continue.
If the GSS Service field is set to 2 (rpc_gss_svc_integrity), the Program-specific data field is prefixed with the following structure:
If the GSS Service field is set to 3 (rpc_gss_svc_privacy), the Program-specific data field is encrypted.
When the Program field is set to 100003 (NFS) and the Procedure field is set to 1 (Compound), the Program-specific data field has the following structure:
A buffer overflow vulnerability exists in the Windows implementation of NFS. The vulnerability is due to incorrect calculation of the size of response messages. The server calls the function Nfs4SvrXdrpGetEncodeOperationResultByteCount() to calculate the size of each opcode response, but it does not include the size of the opcode itself. This results in the size of the response buffer being too small by OP Count * 4 bytes. A corresponding buffer is allocated with OncRpcBufMgrpAllocate. When the response data is written to the buffer, the response data overflows. Due to the function only being used for NFS version 4, only NFS4 is vulnerable.
OncRpcBufMgrpAllocate() will actually allocate the data with either OncRpcBufMgrpAllocateDescriptorFromLLInlineBuffer(), when the request is under 0x800 bytes in size, or OncRpcBufMgrpAllocateDescriptorFromLLLargePoolAllocation(), which is used otherwise.
OncRpcBufMgrpAllocateDescriptorFromLLInlineBuffer() returns a buffer in a static 0x800 bytes inside the descriptor. The descriptor structure has 0x50 bytes of space that appears to be unused after the static buffer.
OncRpcBufMgrpAllocateDescriptorFromLLLargePoolAllocation() returns a buffer allocated with ExAllocatePoolWithTag(). The number of bytes allocated is equal to the following:
This means that for either buffer type, more than 0x48 bytes must be overflowed to get past the padding in either buffer type. Since the number of overflowed bytes is OP Count * 4, a minimum of 19 operations must be performed in a compound message for the overflow to have any impact.
An attacker can use this vulnerability to send a crafted request with many operations, producing a large size miscalculation, resulting in a buffer overflow. Successful exploitation results in arbitrary code execution in the context of SYSTEM. Unsuccessful exploitation may result in a crash of the target system.
Detecting Attacks
Much of this information is largely seen earlier in this post. It is reposted here for your convenience.
When ONC RPC messages are transferred over TCP, they are prepended with a Fragment header structure (as illustrated in the following table) that specifies the length of the message. This allows the receiver to distinguish multiple messages sent over a single TCP session. Other protocols such as UDP do not use this field. Note that all multi-byte values are encoded in big-endian byte order.
The structure of ONC RPC request messages is shown above, as is the Credentials structure in a Sun-RPC message. As shown above, the Flavor field in the above structure serves as a type identifier of the Contents data. Security flavors have been called authentication flavors for historical reasons. There are multiple security flavors defined in the RPC specification, such as AUTH_NONE(0), AUTH_SYS(1), AUTH_SHORT(2), AUTH_DH(3), and RPCSEC_GSS(6).
As a reminder, the Contents field for the flavor RPCSEC_GSS has the following structure:
There are four types such as RPCSEC_GSS_DATA(0), RPCSEC_GSS_INIT(1), RPCSEC_GSS_CONTINUE_INIT(2), and RPCSEC_GSS_DESTROY(3) defined in the GSS Procedure field. Also, in the GSS Service field, there are three types: rpc_gss_svc_none(1), rpc_gss_svc_integrity(2), and rpc_gss_svc_privacy(3). When using RPCSEC_GSS to authenticate the RPC clients, a security context must be created by using RPCSEC_GSS_INIT and RPCSEC_GSS_CONTINUE_INIT RPC messages. Firstly, the RPC client sends an RPCSEC_GSS_INIT message to start the creation of the context. Then, the RPC server will decide whether it needs another token for the creation. If so, the server will reply with a GSS_S_CONTINUE_NEEDED message, and the client needs to send an RPCSEC_GSS_CONTINUE_INIT message to continue.
If the GSS Service field is set to 2 (rpc_gss_svc_integrity), the Program-specific data field is prefixed with the following structure:
If the GSS Service field is set to 3 (rpc_gss_svc_privacy), the Program-specific data field is encrypted and must be decrypted before continuing.
The detection device needs to check if the Program field in an RPC request message has the value 100003 (NFS), the Procedure field has the value 1 (COMPOUND), and the Program Version field has the value 4 (NFS4). If found, the device must inspect the Program-specific data in the ONC RPC messages.
The data format of NFS COMPOUND has the following structure:
The buffer overflow is only triggered if at least 19 operations are present in the NFS reply. Since the NFS reply has the response for each operation in the NFS request, request messages should be monitored for an OP Count field greater than 18.
If a packet with greater than 18 operations is detected, the traffic should be considered suspicious; an attack exploiting this vulnerability is likely underway.
Note that all multi-byte values are expressed in network (big-endian) byte order. Also, this detection method may generate false positives if normal traffic contains similar NFS COMPOUND requests.
Conclusion
This bug was patched by Microsoft in June 2022 and assigned CVE-2022-30136. In their write-up, they also list disabling NFSv4.1 as a method to mitigate attacks. However, this could lead to a loss of functionality. Also, Microsoft notes the update to address this bug should not be applied unless the fix for CVE-2022-26937 is installed. Applying both updates in the appropriate order is the best method to fully address these vulnerabilities.
Special thanks to Guy Lederfein and Quintin Crist of the Trend Micro Research Team for providing such a thorough analysis of this vulnerability. For an overview of Trend Micro Research services please visit http://go.trendmicro.com/tis/.
The threat research team will be back with other great vulnerability analysis reports in the future. Until then, follow the ZDI team for the latest in exploit techniques and security patches.