🔒
There are new articles available, click to refresh the page.
Before yesterdayZero Day Initiative - Blog

MindShaRE: Analyzing BSD Kernels for Uninitialized Memory Disclosures using Binary Ninja

21 September 2022 at 16:39

Disclosure of uninitialized memory is one of the common problems faced when copying data across trust boundaries. This can happen between the hypervisor and guest OS, kernel and user space, or across the network. The most common bug pattern noticed among these cases is where a structure or union is allocated in memory, and some of the fields or padding bytes are not initialized before copying it across trust boundaries. The question is, is it possible to perform variant analysis of such bugs?

The idea here is to perform a control flow insensitive analysis to track all memory store operations statically. Any memory region never written to is identified as uninitialized when the data from it is copied across trust boundaries.

Generalizing the code pattern for analysis

Consider the case of CVE-2018-17155, a FreeBSD kernel memory disclosure in the getcontext() and swapcontext() system calls due to a lack of structure initialization. Shown below is the patch for sys_getcontext(). The listing on the left shows the patched code. sys_swapcontext() was patched in a similar fashion.

Figure 1 - Patch for sys_getcontext() information disclosure. Vulnerable code appears on the right.

The vulnerable code declared a ucontext_t structure on the stack, wrote to some but not all fields, and finally used copyout() to copy UC_COPY_SIZE bytes of data from the structure to userland. The problem here is that not all fields are initialized, so any data occupying the uninitialized parts of the structure memory region are disclosed. To solve the problem, the patched code zeroes out the entire structure using the bzero() function.

The generalization of the above code pattern looks like this:

• A memory region (structure, union, etc.) is declared on the stack or allocated on the heap, which could be the source of uninitialized memory.
• The memory region may get fully or partially written.
• There is an API that transfers data across trust boundaries. This could be the sink for uninitialized memory.
• The API generally takes at least 3 parameters: source buffer, destination buffer, and size. In this case, the source of the memory is a stack offset, and the size of the transfer is a constant value. A constant size of transfer means the value is either the entire size of the memory region (using sizeof operator) or a part of it until an offset.
• The memory region may be zeroed out before usage using functions like memset() or bzero().

The sink function is application-specific. To mention a few of the more likely sinks: copy_to_user() in case of Linux kernel, copyout() in case of BSD kernels, send() or sendto() for network transfers or any wrappers around them. The definitions of these functions are either documented, or else understood by reverse engineering if the target is closed source.

Searching the code pattern for analysis

Once the sink function and its definition are known, we can query for calls to the sink function with a constant size argument and source buffer pointing to a stack offset or heap memory. Querying for a pointer to stack memory is straightforward, whereas detecting heap pointers requires visiting the definition site of source variables. Consider the definition of copyout() function in BSD:

         copyout(const void *kaddr, void *uaddr, size_t len)

When looking for stack memory disclosures, search for cross-references to the copyout() function where kaddr is pointing to a stack offset and the len parameter is a constant.

Binary Ninja has a static data flow feature that propagates known values within a function, including stack frame offsets and type information. Using this feature, it is possible to narrow down calls to copyout() that satisfy our search criteria. To understand this better, let’s inspect the arguments passed to copyout() from sys_getcontext().

Figure 2 - sys_getcontext() invoking copyout(kaddr, uaddr, len)

The kaddr parameter, or params[0], holds a kernel stack pointer, is shown as the stack frame offset -0x398. The value for the len parameter, or params[1], is shown as the constant 0x330. Since Binary Ninja has no information regarding uaddr, this is shown as <undetermined>. With this register type information for kaddr and len, the following query fetches all instances of calls to copyout() with a kernel stack pointer and constant size:

Statically tracking memory stores

The core idea of the analysis is to track all the memory store operations using Binary Ninja’s static data flow capability and propagate pointers manually using Single Static Assignment (SSA) form whenever necessary. For tracking stack memory stores in local function scope, we rely on Low-Level IL (LLIL), because Medium Level IL (MLIL) abstracts stack access and might eliminate some of the memory stores. For tracking inter-procedure store operations where the address is passed to another function, we rely on the MLIL SSA form to propagate the pointers. The visitor class implemented to handle IL instructions is based on Josh Watson’s Emilator.

Tracking stack memory stores with LLIL

In LLIL, any instruction writing to memory is represented as an LLIL_STORE operation. It has a source and destination parameter. The idea is to linearly visit each LLIL instruction in a function and check if it is an LLIL_STORE operation having a stack frame offset as its destination. When a memory store writing to stack is identified, we will log the source offset of the write and its size. Consider a simple 8-byte memory move operation and its corresponding LLIL information provided by Binary Ninja:

Figure 3 - LLIL_STORE operation in freebsd32_sigtimedwait()

The StackFrameOffset value is the offset from the base of the stack and the size property gives the size of the store operation. Using this information, it is possible to know which memory address are being written. In this case, the addresses from stack base offset -116 to -109 (8 bytes) are being initialized.

Static function hooks and memory writing APIs

While memory store instructions are one way to initialize memory, functions like memset() and bzero() are frequently used to initialize a memory region with NULLs. Similarly, functions such as memcpy(), memmove(), bcopy(), strncpy(), and strlcpy() are also used to write to a memory region. All these functions have something in common: there is a destination memory pointer and a size to write. If the destination and size values are known, it is possible to know the memory region being written to. Consider the case of bzero(), which is used to clear stack memory in the patched sys_getcontext():

Figure 4 - Clearing stack memory using bzero()

By querying the destination pointer and size parameters, it is possible to know their respective values and hence the target memory region.

Now let us consider how the analyzer can handle CALL operations. Static hooks are handlers to functions which we intend to handle differently compared to other functions. For any CALL instruction with a known destination i.e., MLIL_CONST_PTR, the symbol is fetched to check for static hooks.

A JSON configuration with the function names as well their positional parameters (destination buffer and size) is provided to the analyzer for static hooking:

The copyin() function is specific to BSD kernels. It is used to initialize kernel buffers with data from user space. Any target-specific functions to hook can be added to the JSON config and handled in visit_function_hooks() as per necessity.

Handling x86 REP optimization

Many times compilers optimize memory writing functions into REP instructions or a series of store operations. While store operations introduced due to optimization can be handled like any other store operation, REP instructions requires special handling. Static function hooks are not useful in detecting memory writes due to REP. So how do we handle such optimizations and avoid missing those memory writes? First, let’s look at how Binary Ninja translates the REP instruction in LLIL or MLIL.

Figure 5 - memcpy() optimized to REP instruction

Figure 6 - REP instruction translation in MLIL

The REP instruction repeats the string operation until RCX is 0. The direction of copy operation depends on the Direction Flag (DF), hence the branching where one branch increments the source (RSI) and destination (RDI) pointers and the other decrements them. In general, it is reasonably safe to assume that DF will be 0, and that pointers are incremented.

When linearly walking through the ILs, the translated REP instruction will look no different from other instructions. The idea is to check for GOTO instruction, and for every GOTO instruction in IL, fetch the disassembly at the same address. If the disassembly is REP instruction, then fetch the destination pointer as well as size arguments and mark the memory region as initialized.

The LLIL has a get_possible_reg_values() API to read values of registers statically. The MLIL provides couple of APIs, get_var_for_reg() and get_ssa_var_version(), to map architecture registers to SSA variables. This is very useful when propagating values manually using SSA variables in the absence of RegisterValueType information (i.e. RegisterValueType.UndeterminedValue). Similar APIs are currently missing in LLIL and tracked as a feature request: API to get SSARegister for a register at a given LLIL instruction.

Tracking Inter-procedure memory stores with MLIL

At this point we can track memory store operations, CALL operations such as bzero(), memset(), and also deal with REP optimization. The next task is to track memory writes across function calls, as when a caller passes a memory address to a callee. The interesting challenge here is that once a stack pointer has been passed into another function, it can no longer be tracked using the register value type information (StackFrameOffset) as we did within the local function scope using LLIL (see above).

To solve this problem, we propagate the pointers within the callee function using MLIL SSA variables, just like propagating taint information. Whenever a MLIL_STORE_SSA instruction is encountered, we log the offset of the write operation and size values whenever the destination of the memory write operation is resolved manually based on values of SSA variables. The set_function_args() function shown below iterates through MLIL variables and assigns the value (pointer) passed by the caller:

Once the initial SSA variables are set, we visit all the instructions linearly to propagate the pointer and log memory writes. While doing this, the most common operation performed on the pointer is addition. Therefore, it is necessary to emulate MLIL_ADD instruction to handle pointer arithmetic operations. Additionally, it is also important to emulate instructions such as MLIL_SUB, MLIL_LSR and MLIL_AND to handle certain pointer-aligning operations in case of optimizations. Here is an example of how these MLIL SSA expressions are resolved to log a memory store operation:

Considering the SSA variable rax_43#65 as a manually propagated pointer value, it is possible to resolve the destination of the store operation as well as the size of the write. But when the value of the SSA variable rax_43#65 is not available, this memory is not associated with the pointer that was propagated by the caller and therefore not logged.

Handling pointer-aligning optimizations

When performing inter-procedure analysis, further optimizations were noticed in addition to the REP optimization as seen in the “Handling x86 REP optimization” section above. A variable allocated on the stack will usually be aligned to meet the needs of upcoming operations. Let’s say a stack pointer is passed to memset() and the compiler inlines the call as a REP instruction. In this case, it is very likely the memory will be allocated at an aligned address such that the fastest instructions can be used during REP operation.

However, when a pointer is received as an argument by a callee or as a return value of an allocator function, the compiler may have to generate pointer and size alignment opcodes which could rely on branching decisions before reaching REP instruction. Here is an example of such an optimization commonly found in the NetBSD kernel used for analysis:

Figure 7 - An example memset() optimization from NetBSD

When such branching decisions are involved, the pointer, as well as the size, can take multiple possible values (from the perspective of static analysis) at the point of REP instruction. This is different from what we observed in the “Handling x86 REP optimization" section where there is only one possible value for pointer and size. Our goal here is to find the actual value of the pointer and size in the absence of pointer-aligning computations. To achieve this, a couple of SSA expressions were identified that can be used to resolve the original value:

• Search for an expression involving (ADDRESS & BYTESIZE). This could be the first use of ADDRESS before taking any conditional branches.
• Search for an expression involving (SIZE >> 3). This is where the adjusted size is passed to a REP instruction.

I had a couple of ideas in mind to track back the above expressions from the point of REP instruction, one relying entirely on SSA and the other based on dominators:

• Use get_ssa_var_definition() and get_ssa_var_uses() APIs to get a variable’s definition site and its uses.
• Alternatively, get the dominators of the basic block containing the REP instruction and visit the instructions in the dominator blocks.

The function resolve_optimization() shown below uses dominators to get the basic blocks to perform the search operation. Since the pointer is manually passed by the caller, the value is fetched from the SSA variables.

In the case of a possible constant size value, we fetch the maximum from the list of available size values. Once both pointer and size values are available, we log the memory region as initialized.

Tracking memory stores in dynamic memory allocations

So far, all our analyses were concentrated on stack memory as the source buffer for information disclosure. This is largely due to the prevalence of stack memory disclosure bugs, as described in KLEAK: Practical Kernel Memory Disclosure Detection (PDF). What about other memory regions such as the heap? Can we model some of the heap memory disclosures too?

When looking for heap memory disclosures, the idea remains the same. We are still looking for calls to sink functions with known size value. But instead of the source pointer being RegisterValueType.StackFrameOffset, we check for RegisterValueType.UndeterminedValue. Consider the code for sys_statfs():

Figure 8 - Dynamic memory allocation in sys_statfs()

Here the kernel pointer rdi_1#2 in copyout() is undetermined because Binary Ninja does not know what the allocator function returns. However, by using the SSA form, we can manually track back whether rdi_1#2 is holding the return value of malloc(). For example, follow the highlighted instructions in Figure 8. - the variables are assigned as rax_1#1->r15#1->rdi_1#2. This information can be obtained programmatically using the MLIL get_ssa_var_definition() API. Once the definition site of an SSA variable is obtained, we can check whether the variable is initialized using a CALL operation as demonstrated below:

How does the analyzer know the definition of allocator functions? We can take the same approach used for providing information regarding static function hooks (see the “Static function hooks and memory writing APIs” section above). A JSON configuration with a list of allocator functions and an index of size parameters is provided to the analyzer. For any CALL instruction with a known destination (i.e., MLIL_CONST_PTR), the symbol is fetched to check for known allocator functions. Here is a sample JSON configuration used for analysis:

Once we have established the connection between the source pointer and allocator call, the next question is, what pointer value will be assigned as the return value of the allocator call? The stack pointers as tracked as negative offsets in Binary Ninja as seen below:

To have a generalized representation between the stack and heap pointers, I decided to set the return value of a heap allocator calls as a negative value of the size of the allocation. For the malloc() call in sys_statfs(), rax_1#1 is set to -0x1d8 as the starting address. Therefore, the memory region which needs to be initialized ranges from -0x1d8 to 0 [start + size of allocation]. Even when the allocation size is undetermined, starting address can be set to some arbitrary value such as -0x10000. All that matters here is to know whether the contiguous memory region accessed by copyout() is initialized or not.

Filtering memory stores using dominators and post dominators

A dominator in graph theory provides information on the order of execution of some basic blocks. While we have already used dominators for handling pointer-aligning optimizations in the “Handling pointer aligning optimizations” section, this section details the usage of dominators in detecting control flow-sensitive memory store operations.

To analyze uninitialized memory disclosures, we explore two ideas: dominators and post-dominators. A basic block X is said to dominate another basic block Y if all paths to Y should go through X. A basic block Y is said to post-dominate basic block X if all paths from X to any of the function’s return blocks should go through Y. Consider this example from Wikipedia:

Figure 9 - Graph demonstrating dominators and post dominators

In the provided graph, node B dominates nodes C, D, E, and F because all paths to these nodes must go through node B. By definition, every node dominates itself, so the set of all nodes dominated by node B will be B, C, D, E, and F. Also, node A dominates all the nodes in the graph. Therefore, the dominators of nodes C, D, E, F are A and B.

Similarly, when A is considered as the function entry node, with E and F being exit nodes, node B is the post-dominator of node A. This is because all paths from A to the exit nodes must go through B.

Now, how can dominators and post-dominators help us in this analysis?

We can perform dominator analysis on the callers of the sink function. The idea is to log only memory stores in basic blocks which dominate the basic block calling copyout(), that is, basic blocks which will be executed irrespective of branching decisions. Consider the code below:

Figure 10 - Dominators of basic block calling copyout()

Here the basic block calling copyout() is <mlil block: [email protected]> and there are five dominator blocks in the path from the function entry to copyout(). When performing dominator-based analysis, we will log only memory stores within these five dominator blocks. The memory store operations in other basic blocks might be skipped and not execute. The same is the case with the callee function. We will perform an inter-procedure analysis only when the function is called from a dominator block.

Post-dominator analysis is done on the callee function during an inter-procedure analysis. It is meant to find bugs where a callee can possibly return before initializing the memory region it is supposed to. Consider the callee function do_sys_waitid() from figure 10.

Figure 11 - Post dominators of function entry block in do_sys_waitid()

The function entry block <mlil block: [email protected]> is always executed. The other basic blocks that are executed irrespective of the branching decisions are <mlil block: [email protected]> and <mlil block: [email protected]>. Once again, memory stores and callee analysis are limited only to these three basic blocks.

Dominator- and post-dominator-based analysis tries to fill the gaps in control flow insensitive analysis performed by the analyzer. The general assumption here is that memory is initialized or cleared before performing further operations and therefore dominates other basic blocks. However, this assumption is not always true. For example, there are cases where individual code paths can perform the same operation as done in the dominators. Moreover, when a callee returns due to any error condition, the return value could be validated by the caller before calling copyout(). Consequently, dominator-based analysis as done in this implementation is prone to large numbers of false positives.

Checking for uninitialized memory disclosures

Once all the memory store operations are statically logged with information on offset and size of write, the memory region copied out to user space using copyout() can be evaluated for uninitialized memory disclosure. Consider the call to copyout() shown below:

The source pointer is -0x398 and the size copied is 0x330 bytes. Therefore, the analyzer has to validate if all the bytes in the memory range from -0x398 to (-0x398 + 0x330) are initialized, and if not, flag that as a bug.

False positives and limitations

The analyzer is written with the goal of finding memory regions that never get written to in any possible code paths. False positives occur in cases when it is unable to track a memory store operation. Below are some common false positive conditions and limitations of the implementation:

• The analyzer does not emulate branching instructions. Therefore, false positives are seen in code constructs involving control flow decisions. Consider a memory region such as an array that is initialized in a loop operation. In this case, the store operation would be detected only once because the loop body is visited only once by the analyzer, and not in a loop as it would be during execution.

• Indirect calls are not resolved statically. Consequently, any memory store done during indirect calls is not tracked.

• Optimizations may make it harder to track memory stores. Some common optimizations noticed were tackled in the “Handling x86 REP optimization” and “Handling pointer aligning optimizations” sections.

• Binary Ninja may wrongly detect type information of functions used for static hooking or sink functions like copyout(). Since our analysis relies on RegisterValueType information, any failure to accurately detect the function prototype may lead to false results. Verify the type information before analysis and update if necessary.

• The analyzer looks only for code patterns where the memory source and sink function are within the same function. There is no tracking back of memory source beyond the local function scope.

• Dominator analysis is experimental. You should use it only as a guideline to perform code reviews.

When there is access to source code, some of these false positives can be resolved by changing the optimization flags or by unrolling loops to reduce branching decisions.

Analysis and results

The target kernel executable is loaded in Binary Ninja to generate the BNDB analysis database. Then the analyzer is executed against the database for faster analysis. There are a couple of scripts: one for analyzing stack memory disclosures and another for analyzing sink functions with known size and unknown source pointer. Since the source pointer could be from a heap allocator, provide a JSON configuration with a list of allocator functions as an argument. The dominator analysis is experimental. You need to enable it using an optional argument when needed:

Conclusion

The scripts were tested on Binary Ninja version 2.4.2846 against FreeBSD 11.4, NetBSD 9.2, and OpenBSD 6.9 kernels. Amongst the results, code paths that are possibly reachable for an unprivileged user were evaluated. The OpenBSD bugs were found in sysctls related to multicast routing in IPv4 as well as IPv6, which are tracked as ZDI-22-073 and ZDI-22-012 respectively.

The four vulnerabilities (ZDI-22-075, ZDI-22-1036, ZDI-22-1037, ZDI-22-1067) found in NetBSD are related to syscalls supporting backward compatibility for older NetBSD releases ZDI-22-075 and ZDI-22-1036 are information disclosures in VFS syscalls for NetBSD 3.0 and NetBSD 5.0 respectively. Details regarding the fixes can be found here. Next, ZDI-22-1037 is an information disclosure in getkerneinfo syscall for NetBSD 4.3. This bug was fixed with many other potential issues as seen here. Finally, ZDI-22-1067 is another information disclosure related to VFS syscalls but in NetBSD 2.0 compatibility. Details regarding the fix can be found here.

The FreeBSD bug found in version 11.4 was also related to compatibility, which in this case for supporting 32-bit binaries. However, this bug was fixed without a disclosure during a large change done for the 64-bit inode. The uninitialized structure fields were cleared in the copy_stat function as part of the 64-bit inode project. Though this commit was in May 2017, it was tagged to release 12.0 and above. Therefore, the bug remained unfixed in release 11.4 until it reached EOL in September 2021, soon after our bug report.

Putting it together, most of the bugs were found in BSD’s compatibility layers. Additionally, all these bugs are stack memory disclosures. For anyone interested, the source code for the project can be found here.

 You can find me on Twitter @RenoRobertr, and follow the team on Twitter or Instagram for the latest in exploit techniques and security patches.

 

Acknowledgments and references

— Various blog posts from Trail of Bits on Binary Ninja
— Josh Watson for various projects using Binary Ninja. The visitor class implementation is based on emilator
— Jordan for all the code snippets and the Binary Ninja slack community for answering various questions
KLEAK: Practical Kernel Memory Disclosure Detection by Thomas Barabosch and Maxime Villard
Solving Uninitialized Stack Memory on Windows by Joe Bialek
Building Faster AMD64 Memset Routines by Joe Bialek

MindShaRE: Analyzing BSD Kernels for Uninitialized Memory Disclosures using Binary Ninja

The September 2022 Security Update Review

13 September 2022 at 17:25

Another Patch Tuesday is upon, and Adobe and Microsoft have released a bevy of new security updates. Take a break from your regularly scheduled activities and join us as we review the details of their latest security offerings.

Adobe Patches for September 2022

 For September, Adobe released seven patches addressing 63 in Adobe Experience Manager, Bridge, InDesign, Photoshop, InCopy, Animate, and Illustrator. A total of 42 of these bugs were reported by ZDI Sr Vulnerability Researcher Mat Powell. The update for InDesign is the largest patch this month, with eight Critical-rated and 10 Important-rated vulnerabilities receiving fixes. The most severe of these could lead to code execution if a specially crafted file is opened on an affected system. The patch for Photoshop fixes 10 CVEs, nine of which are rated Critical. Again, an attacker can get code execution if they can convince a user to open a malicious file. The fix for InCopy fixes five similar code execution bugs and two info disclosure bugs. Adobe Animate also receives patches for two Critical-rated code execution bugs.

The update for Adobe Bridge corrects 10 Critical-rated code execution bugs and two Important-rated info disclosure bugs. One of the three Illustrator vulnerabilities getting patched could also lead to code execution. As with the bugs previously mentioned, a user would need to open a malicious file with an affected software version. Finally, the patch for Adobe Experience Manager addresses 11 Important-rated bugs, primarily of the cross-site scripting (XSS) variety.

None of the bugs fixed by Adobe this month are listed as publicly known or under active attack at the time of release. Adobe categorizes these updates as a deployment priority rating of 3.

Apple Patches for September 2022

Yesterday, Apple released updates for iOS, iPadOS, macOS, and Safari. They also released updates for watchOS and tvOS but provided no details on any of the fixes included in these patches. Two of the bugs patched by Apple were identified as being under active exploit. The first is a kernel bug (CVE-2022-32917) resulting from improper bounds checking. It affects iOS 15 and iPadOS 15, macOS Big Sur, and macOS Monterey. Interestingly, this CVE is also listed in the advisory for iOS 16, but it is not called out as being under active exploit for that flavor of the OS. The Big Sur version of macOS also includes a fix for an Out-of-Bounds (OOB) Write bug in the kernel (CVE-2022-32894) that’s also listed as under active attack. One final note: Apple states in its iOS 16 advisory that “Additional CVE entries to be added soon.” It is possible other bugs could also impact this version of the OS. Either way, it’s time to update your Apple devices.

Microsoft Patches for September 2022

This month, Microsoft released 64 new patches addressing CVEs in Microsoft Windows and Windows Components; Azure and Azure Arc; .NET and Visual Studio and .NET Framework; Microsoft Edge (Chromium-based); Office and Office Components; Windows Defender; and Linux Kernel (really). This is in addition to the 15 CVEs patched in Microsoft Edge (Chromium-based) and one patch for side-channel speculation in Arm processors. That brings the total number of CVEs to 79. Five of these CVEs were submitted through the ZDI program.

The volume of fixes released this month is about half of what we saw in August, but it is in line with the volume of patches from previous September releases. For whatever reason, the last quarter of the calendar year tends to have fewer patches released. We’ll see if that trend continues in 2022.

Of the 64 new CVEs released today, five are rated Critical, 57 are rated Important, one is rated Moderate, and one is rated Low in severity. One of these new CVEs is listed as publicly known and under active attack at the time of release. Let’s take a closer look at some of the more interesting updates for this month, starting with the CLFS bug under active attack:

-       CVE-2022-37969 - Windows Common Log File System Driver Elevation of Privilege Vulnerability
This bug in the Common Log File System (CLFS) allows an authenticated attacker to execute code with elevated privileges. Bugs of this nature are often wrapped into some form of social engineering attack, such as convincing someone to open a file or click a link. Once they do, additional code executes with elevated privileges to take over a system. Usually, we get little information on how widespread an exploit may be used. However, Microsoft credits four different agencies reporting this bug, so it’s likely beyond just targeted attacks.

-       CVE-2022-34718 - Windows TCP/IP Remote Code Execution Vulnerability
This Critical-rated bug could allow a remote, unauthenticated attacker to execute code with elevated privileges on affected systems without user interaction. That officially puts it into the “wormable” category and earns it a CVSS rating of 9.8. However, only systems with IPv6 enabled and IPSec configured are vulnerable. While good news for some, if you’re using IPv6 (as many are), you’re probably running IPSec as well. Definitely test and deploy this update quickly.

-       CVE-2022-34724 - Windows DNS Server Denial of Service Vulnerability
This bug is only rated Important since there’s no chance of code execution, but you should probably treat it as Critical due to its potential impact. A remote, unauthenticated attacker could create a denial-of-service (DoS) condition on your DNS server. It’s not clear if the DoS just kills the DNS service or the whole system. Shutting down DNS is always bad, but with so many resources in the cloud, a loss of DNS pointing the way to those resources could be catastrophic for many enterprises.

-       CVE-2022-3075 - Chromium: CVE-2022-3075 Insufficient data validation in Mojo
This patch was released by the Google Chrome team back on September 2, so this is more of an “in case you missed it.” This vulnerability allows code execution on affected Chromium-based browsers (like Edge) and has been detected in the wild. This is the sixth Chrome exploit detected in the wild this year. The trend shows the near-ubiquitous browser platform has become a popular target for attackers. Make sure to update all of your systems based on Chromium.

Here’s the full list of CVEs released by Microsoft for September 2022:

CVE Title Severity CVSS Public Exploited Type
CVE-2022-37969 Windows Common Log File System Driver Elevation of Privilege Vulnerability Important 7.8 Yes Yes EoP
CVE-2022-23960 * Arm: CVE-2022-23960 Cache Speculation Restriction Vulnerability Important N/A Yes No Info
CVE-2022-34700 Microsoft Dynamics 365 (on-premises) Remote Code Execution Vulnerability Critical 8.8 No No RCE
CVE-2022-35805 Microsoft Dynamics 365 (on-premises) Remote Code Execution Vulnerability Critical 8.8 No No RCE
CVE-2022-34721 Windows Internet Key Exchange (IKE) Protocol Extensions Remote Code Execution Vulnerability Critical 9.8 No No RCE
CVE-2022-34722 Windows Internet Key Exchange (IKE) Protocol Extensions Remote Code Execution Vulnerability Critical 9.8 No No RCE
CVE-2022-34718 Windows TCP/IP Remote Code Execution Vulnerability Critical 9.8 No No RCE
CVE-2022-38013 .NET Core and Visual Studio Denial of Service Vulnerability Important 7.5 No No DoS
CVE-2022-26929 .NET Framework Remote Code Execution Vulnerability Important 7.8 No No RCE
CVE-2022-38019 AV1 Video Extension Remote Code Execution Vulnerability Important 7.8 No No RCE
CVE-2022-38007 Azure Guest Configuration and Azure Arc-enabled servers Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-37954 DirectX Graphics Kernel Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-35838 HTTP V3 Denial of Service Vulnerability Important 7.5 No No DoS
CVE-2022-35828 Microsoft Defender for Endpoint for Mac Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-34726 Microsoft ODBC Driver Remote Code Execution Vulnerability Important 8.8 No No RCE
CVE-2022-34727 Microsoft ODBC Driver Remote Code Execution Vulnerability Important 8.8 No No RCE
CVE-2022-34730 Microsoft ODBC Driver Remote Code Execution Vulnerability Important 8.8 No No RCE
CVE-2022-34732 Microsoft ODBC Driver Remote Code Execution Vulnerability Important 8.8 No No RCE
CVE-2022-34734 Microsoft ODBC Driver Remote Code Execution Vulnerability Important 8.8 No No RCE
CVE-2022-37963 Microsoft Office Visio Remote Code Execution Vulnerability Important 7.8 No No RCE
CVE-2022-38010 Microsoft Office Visio Remote Code Execution Vulnerability Important 7.8 No No RCE
CVE-2022-34731 Microsoft OLE DB Provider for SQL Server Remote Code Execution Vulnerability Important 8.8 No No RCE
CVE-2022-34733 Microsoft OLE DB Provider for SQL Server Remote Code Execution Vulnerability Important 8.8 No No RCE
CVE-2022-35834 Microsoft OLE DB Provider for SQL Server Remote Code Execution Vulnerability Important 8.8 No No RCE
CVE-2022-35835 Microsoft OLE DB Provider for SQL Server Remote Code Execution Vulnerability Important 8.8 No No RCE
CVE-2022-35836 Microsoft OLE DB Provider for SQL Server Remote Code Execution Vulnerability Important 8.8 No No RCE
CVE-2022-35840 Microsoft OLE DB Provider for SQL Server Remote Code Execution Vulnerability Important 8.8 No No RCE
CVE-2022-37962 Microsoft PowerPoint Remote Code Execution Vulnerability Important 7.8 No No RCE
CVE-2022-35823 Microsoft SharePoint Remote Code Execution Vulnerability Important 8.1 No No RCE
CVE-2022-37961 Microsoft SharePoint Server Remote Code Execution Vulnerability Important 8.8 No No RCE
CVE-2022-38008 Microsoft SharePoint Server Remote Code Execution Vulnerability Important 8.8 No No RCE
CVE-2022-38009 Microsoft SharePoint Server Remote Code Execution Vulnerability Important 8.8 No No RCE
CVE-2022-37959 Network Device Enrollment Service (NDES) Security Feature Bypass Vulnerability Important 6.5 No No SFB
CVE-2022-38011 Raw Image Extension Remote Code Execution Vulnerability Important 7.3 No No RCE
CVE-2022-35830 Remote Procedure Call Runtime Remote Code Execution Vulnerability Important 8.1 No No RCE
CVE-2022-37958 SPNEGO Extended Negotiation (NEGOEX) Security Mechanism Information Disclosure Vulnerability Important 7.5 No No Info
CVE-2022-38020 Visual Studio Code Elevation of Privilege Vulnerability Important 7.3 No No EoP
CVE-2022-34725 Windows ALPC Elevation of Privilege Vulnerability Important 7 No No EoP
CVE-2022-35803 Windows Common Log File System Driver Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-30170 Windows Credential Roaming Service Elevation of Privilege Vulnerability Important 7.3 No No EoP
CVE-2022-34719 Windows Distributed File System (DFS) Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-34724 Windows DNS Server Denial of Service Vulnerability Important 7.5 No No DoS
CVE-2022-34723 Windows DPAPI (Data Protection Application Programming Interface) Information Disclosure Vulnerability Important 5.5 No No Info
CVE-2022-35841 Windows Enterprise App Management Service Remote Code Execution Vulnerability Important 8.8 No No RCE
CVE-2022-35832 Windows Event Tracing Denial of Service Vulnerability Important 5.5 No No DoS
CVE-2022-38004 Windows Fax Service Remote Code Execution Vulnerability Important 7.8 No No RCE
CVE-2022-34729 Windows GDI Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-38006 Windows Graphics Component Information Disclosure Vulnerability Important 6.5 No No Info
CVE-2022-34728 Windows Graphics Component Information Disclosure Vulnerability Important 5.5 No No Info
CVE-2022-35837 Windows Graphics Component Information Disclosure Vulnerability Important 5 No No Info
CVE-2022-37955 Windows Group Policy Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-34720 Windows Internet Key Exchange (IKE) Extension Denial of Service Vulnerability Important 7.5 No No DoS
CVE-2022-33647 Windows Kerberos Elevation of Privilege Vulnerability Important 8.1 No No EoP
CVE-2022-33679 Windows Kerberos Elevation of Privilege Vulnerability Important 8.1 No No EoP
CVE-2022-37956 Windows Kernel Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-37957 Windows Kernel Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-37964 Windows Kernel Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-30200 Windows Lightweight Directory Access Protocol (LDAP) Remote Code Execution Vulnerability Important 7.8 No No RCE
CVE-2022-26928 Windows Photo Import API Elevation of Privilege Vulnerability Important 7 No No EoP
CVE-2022-38005 Windows Print Spooler Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-35831 Windows Remote Access Connection Manager Information Disclosure Vulnerability Important 5.5 No No Info
CVE-2022-30196 Windows Secure Channel Denial of Service Vulnerability Important 8.2 No No DoS
CVE-2022-35833 Windows Secure Channel Denial of Service Vulnerability Important 7.5 No No DoS
CVE-2022-38012 Microsoft Edge (Chromium-based) Remote Code Execution Vulnerability Low 7.7 No No RCE
CVE-2022-3038 * Chromium: CVE-2022-3038 Use after free in Network Service Critical N/A No No RCE
CVE-2022-3075 * Chromium: CVE-2022-3075 Insufficient data validation in Mojo High N/A No Yes RCE
CVE-2022-3039 * Chromium: CVE-2022-3039 Use after free in WebSQL High N/A No No RCE
CVE-2022-3040 * Chromium: CVE-2022-3040 Use after free in Layout High N/A No No RCE
CVE-2022-3041 * Chromium: CVE-2022-3041 Use after free in WebSQL High N/A No No RCE
CVE-2022-3044 * Chromium: CVE-2022-3044 Inappropriate implementation in Site Isolation High N/A No No N/A
CVE-2022-3045 * Chromium: CVE-2022-3045 Insufficient validation of untrusted input in V8 High N/A No No RCE
CVE-2022-3046 * Chromium: CVE-2022-3046 Use after free in Browser Tag High N/A No No RCE
CVE-2022-3047 * Chromium: CVE-2022-3047 Insufficient policy enforcement in Extensions API Medium N/A No No SFB
CVE-2022-3053 * Chromium: CVE-2022-3053 Inappropriate implementation in Pointer Lock Medium N/A No No N/A
CVE-2022-3054 * Chromium: CVE-2022-3054 Insufficient policy enforcement in DevTools Medium N/A No No SFB
CVE-2022-3055 * Chromium: CVE-2022-3055 Use after free in Passwords Medium N/A No No RCE
CVE-2022-3056 * Chromium: CVE-2022-3056 Insufficient policy enforcement in Content Security Policy Low N/A No No SFB
CVE-2022-3057 * Chromium: CVE-2022-3057 Inappropriate implementation in iframe Sandbox Low N/A No No EoP
CVE-2022-3058 * Chromium: CVE-2022-3058 Use after free in Sign-In Flow Low N/A No No RCE

* Indicates this CVE had previously been assigned by a 3rd-party and is now being incorporated into Microsoft products.

Checking the remaining Critical-rated updates, there are two for Windows Internet Key Exchange (IKE) Protocol Extensions that could also be classified as “wormable.” For both bugs, only systems running IPSec are affected. There are also two Critical-rated vulnerabilities in Dynamics 365 (On-Premises) that could allow an authenticated user to perform SQL injection attacks and execute commands as db_owner within their Dynamics 356 database.

Moving on to other code execution bugs, more than half of this month’s release involves some form of remote code execution. Of these, the patches for SharePoint stand out. Microsoft recently detailed how a SharePoint bug was used by Iranian threat actors against the Albanian government, resulting in Albania breaking off diplomatic relations with Iran. Those attacks involved a SharePoint bug we had previously blogged about. These new SharePoint cases do require authentication, but they sound very similar to other SharePoint bugs that came through the ZDI program. There are six RCE bugs in OLE DB Provider for SQL Server, but they require user interaction. A threat actor would need a user on an affected system to connect to a malicious SQL server via OLEDB, which could result in the target server receiving a malicious packet, resulting in code execution. There are five RCE bugs in the ODBC driver that also require user interaction. For these, opening a malicious MDB in Access would get code execution, similar to the other open-and-own bugs in Office components. The bug in LDAP also requires user interaction, but no other information about the exploit scenario is given.

The bug in the Enterprise App Management component requires authentication, but it’s still intriguing. An attacker could use the vulnerability to install arbitrary SYSTEM services that would then run with SYSTEM privileges. I could definitely see this bug being used after an initial breach for lateral movement and to maintain a presence on a target network. The RPC bug also looks interesting, but it’s likely not as practical since an attacker would need to spoof the localhost IP address of the target. There’s an RCE bug in .NET, but no information besides the requirement for user interaction is given. Finally, there are updates for the AV1 video extension and the Raw image extension. Both updates are delivered automatically through the Microsoft store. If you’re in a disconnected environment, you’ll need to apply these updates manually.

There are a total of 19 elevation of privilege (EoP) fixes in this month’s release, including the aforementioned patch for CLFS. Many of these require an authenticated user to run specially crafted code on an affected system. The bug in Windows Defender for Mac fits this description, as do the kernel-related patches. However, there are a couple of interesting bugs that don’t fit this profile. The first of these is a bug in the Credential Roaming Service that could allow attackers to gain remote interactive logon rights on a machine. There are two bugs in Kerberos that could lead to SYSTEM, but both have many caveats, so exploitation is unlikely. The EoP in Azure Guest Configuration and Arc-Enabled servers is fascinating for multiple reasons. A threat actor could use this vulnerability to replace Microsoft-shipped code with their own code, which would then be run as root in the context of a Guest Configuration daemon. On an Azure Arc-enabled server, it could run in the context of the GC Arc Service or Extension Service daemons. While this is interesting on its own, the mere fact that Microsoft is producing patches for the Linux kernel boggles the mind. And, of course, it wouldn’t be a monthly update if it didn’t include a patch for the print spooler.

The September release includes six patches for information disclosure vulnerabilities. For the most part, these only result in leaks consisting of unspecified memory contents. One exception is the bug impacting the Data Protection Application Programming Interface (DPAPI). If you aren’t familiar with it, DPAPI allows you to encrypt data using information from the current user account or computer. The bug patched this month could allow an attacker to view the DPAPI master key. The vulnerability in the Windows graphics component could leak metafile memory values, although it’s not clear what an attacker could do with this information.

Seven different DoS vulnerabilities are patched this month, including the DNS bug previously mentioned above. Two bugs in secure channel would allow an attacker to crash a TLS by sending specially crafted packets. There’s a DoS in IKE, but unlike the code execution bugs listed above, no IPSec requirements are listed here. If you’re running newer OSes with the latest features, don’t miss the fix for an HTTP DoS. The system needs HTTP/3 enabled and the server using buffered I/O to be affected. HTTP/3 is a new feature in Windows Server 2022, so in this rare instance, older is better.

The September release includes a fix for a lone security feature bypass in Network Device Enrollment (NDES) Service. An attacker could bypass the service’s cryptographic service provider.

The Low-rated bug is a sandbox escape in Microsoft Edge (Chromium-based) that requires user interaction. However, the CVSS for this bug is 7.7, which Mitre classifies as “High.” Microsoft claims the user interaction involved justifies the Low rating, but I would still treat this as an important update and not delay the rollout.

No new advisories were released this month. The latest servicing stack updates can be found in the revised ADV990001.

Looking Ahead

The next Patch Tuesday falls on October 11, and we’ll return with details and patch analysis then. Don’t forget - I’ll be premiering the Patch Report webcast tomorrow on our YouTube channel at 9:00 am Central time. I hope you’re able to tune in and check it out. Until then, stay safe, happy patching, and may all your reboots be smooth and clean!

The September 2022 Security Update Review

Riding the InfoRail to Exploit Ivanti Avalanche – Part 2

8 September 2022 at 16:07

In my first blog post covering bugs in Ivanti Avalanche, I covered how I reversed the Avalanche custom InfoRail protocol, which allowed me to communicate with multiple services deployed within this product. This allowed me to find multiple vulnerabilities in the popular mobile device management (MDM) tool. If you aren’t familiar with it, Ivanti Avalanche allows enterprises to manage mobile device and supply chain mobility solutions. That’s why the bugs discussed here could be used by threat actors to disrupt centrally managed Android, iOS and Windows devices. To refresh your memory, the following vulnerabilities were presented in the previous post:

 ·       Five XStream insecure deserialization issues, where deserialization was performed on the level of message handling.
·       A race condition leading to authentication bypass, wherein I abused a weakness in the protocol and the communication between services.

This post is a continuation of that research. By understanding the expanded attack surface exposed by the InfoRail protocol, I was able to discover an additional 20 critical and high severity vulnerabilities. This blog post takes a detailed look at three of my favorite vulnerabilities, two of which have a rating of CVSS 9.8:

·       CVE-2022-36971 – Insecure deserialization.
·       CVE-2021-42133 – Arbitrary file write/read through the SMB server.
·       CVE-2022-36981 – Path traversal, delivered with a fun authentication bypass.

Each of these three vulnerabilities leads to remote code execution as SYSTEM.

CVE-2022-36971: A Tricky Insecure Deserialization

I discovered the first vulnerability when I came across an interesting class named JwtTokenUtility, which defines a non-default constructor that could be a potential target:

At [1], the function base64-decodes one of the arguments.

At [2], it checks if the publicOnly argument is true.

If not, it deserializes the base64 decoded argument at [3].

This looks like a possible insecure deserialization sink. In addition, it is invoked from many locations within the codebase. The following screenshot illustrates several instances where it is invoked with the first argument set to false:

Figure 1 - Example invocations of JwtTokenUtility non-default constructor

It turned out that most of these potential vectors require control over the SQL database. The serialized object is retrieved from the database, and I found no direct way to modify this value. Luckily, there are two services with a more direct attack vector: the Printer Device Server and the Smart Device Server. The exploitation of both services is almost identical. We will focus on the Printer Device Server (PDS).

Let’s have a look at the PDS AmcConfigDirector.createAccessTokenGenerator method:

At [1], it uses acctApi.getGlobal to retrieve an object that implements IGlobal.

At [2], it retrieves the pkk string by calling global.getAccessKeyPair.

At [3], it decrypts the pkk string by calling PasswordUtils.decryptPassword. We are not going to analyze this decryption routine. This decryption function implements a fixed algorithm with a hardcoded key, thus the attacker can easily perform the encryption or decryption on their own.

At [4], it invokes the vulnerable JwtTokenUtility constructor, passing the pkk string as an argument.

At this point, we are aware that there is potential for abusing the non-default JwtTokenUtility constructor. However, we are missing two things:

       -- How can we control the pkk string?
       -- How can we reach createAccessTokenGenerator?

Let’s start with the control of the pkk string.

Controlling the value of pkk

To begin, we know that:

       -- The code retrieves an object to assign to the global variable. This object implements IGlobal.
       -- It calls the global.getAccessKeyPair getter to retrieve pkk.

There is a Global class that appears to control the PDS service global settings. It implements the IGlobal interface and both the getter and the setter for the accessKeyPair member, so this is probably the class we’re looking for.

Next, we must look for corresponding setAccessKeyPair setter calls. Such a call can be found in the AmcConfigDirector.processServerProfile method.

At [1], processServerProfile accepts the config argument, which is of type PrinterAgentConfig.

At [2], it retrieves a list of PropertyPayload objects by calling config.getPayload.

At [3], the code iterates over the list of PropertyPayload objects.

At [4], there is a switch statement based on the property.name field.

At [5], the code checks to see if property.name is equal to the string "webfs.ac.ppk".

If so, it calls setAccessKeyPair at [6].

So, the AmcConfigDirector.processServerProfile method can be used to control the pkk value. Finally, we note that this method can be invoked remotely through a ServerConfigHandler InfoRail message:

At [1], we see that this message type can be accessed through the subcategory 1000000 (see first blog post - Message Processing and Subcategories section).

At [2], the main processMessage method is defined. It will be called during message handling.

At [3], the code retrieves the message payload.

At [4], it calls the second processMessage method.

At [5], it deserializes the payload and casts it to the PrinterAgentConfig type.

At [6], it calls processServerProfile and provides the deserialized config object as an argument.

Success! We can now deliver our own configuration through the ServerConfigHandler method of the PDS server. This method can be invoked through the InfoRail protocol. Next, we need to get familiar with the PrinterAgentConfig class to prepare the appropriate serialized object.

It has a member called payload, which is of type List<PropertyPayload>.

PropertyPayload has two members that are interesting for us: name and value. Recall that the processServerProfile method does the following:

       -- Iterates through the list of PropertyPayload objects with a for loop.
       -- Executes switch statement based on PropertyPayload.name.
       -- Sets values based on PropertyPayload.value.

With this in mind, we can understand how to deliver a serialized object and control the pkk variable. We have to prepare an appropriate gadget (we can use the Ysoserial C3P0 or CommonsBeanutils1 gadgets), encrypt it (decryption will be handled by the PasswordUtils.decryptPassword method) and deliver through the InfoRail protocol.

The properties of the InfoRail message should be as follows:

       -- Message subcategory: 1000000.
       -- InfoRail distribution list address: 255.3.5.15 (PDS server).

Here is an example payload:

The first step of the exploitation is completed. Next, we must find a way to call the createAccessTokenGenerator function.

Triggering the Deserialization

Because the full flow that leads to the invocation of createAccessTokenGenerator is extensive, I will omit some of the more tedious details. We will instead focus on the InfoRail message that allows us to trigger the deserialization via the needFullConfigSync function. Be aware that the PDS server frequently performs synchronization operations, but typically does not perform a synchronization of the full configuration. By calling needFullConfigSync, a full synchronization will be performed, leading to execution of doPostDeploymentCleanup:

At [1], the code invokes our target method, createAccessTokenGenerator.

The following snippet presents the NotificationHandler message, which calls the needFullConfigSync method:

At [1], the message subcategory is defined as 2200.

At [2], the main processMessage method is defined.

At [3], the payload is deserialized and casted to the NotifyUpdate type (variable nu).

At [4], the code iterates through the entries of the NotifyUpdateEntry object that was obtained from nu.getEntries.

At [5], [6], and [7], the code checks to see if entry.ObjectType is equal to 61, 64, or 59.

If one of the conditions is true, the code sets the universalDeployment variable to true value at [8], [9], or [10], so that needFullConfigSync will be called at [11].

The last step is to create an appropriate serialized message object. An example payload is presented below. Here, the objectType field is equal to 61.

The attacker must send this payload through a message with the following properties:

-- Message subcategory: 2200.
-- InfoRail distribution list address: 255.3.5.15 (PDS server).

To summarize, we must send two different InfoRail messages to exploit this deserialization issue. The first message is to invoke ServerConfigHandler, which delivers a serialized pkk string. The second message is to invoke NotificationHandler, to trigger the insecure deserialization of the pkk value. The final result is a nice pre-auth remote code execution as SYSTEM.

CVE-2021-42133: One Vuln to Rule Them All - Arbitrary File Read and Write

Ivanti Avalanche has a File Store functionality, which can be used to upload files of various types. This functionality has been already abused in the past, in CVE-2021-42125, where an administrative user could:

-- Use the web application to change the location of the File Storage and point it to the web root.
-- Upload a file of any extension, such as a JSP webshell, through the web-based functionality.
-- Use the webshell to get code execution.

The File Store configuration operations are performed through the Enterprise Server, and they can be invoked through InfoRail messages. I quickly discovered three interesting properties of the File Store:

  1. It supports Samba shares. Therefore, it is possible to connect it to any reachable SMB server. The attacker can set the File Store path pointing to his server by specifying a UNC path.
  2. Whenever the File Store path is changed, Avalanche copies all files from the previous File Store directory to the new one. If a file of the same name already exists in the new location, it will be overwritten.
  3. The File Store path can also be set to any location in the local file system.

These properties allow an attacker to freely exchange files between their SMB server and the Ivanti Avalanche local file system. In order to modify the File Store configuration, the attacker needs to send a SetFileStoreConfig message:

At [1], the subcategory is defined as 1501.

At [2], the standard Enterprise Server processMessage method is defined. The implementation of message processing is a little bit different in the Enterprise Server, although the underlying idea is the same as in previous examples.

At [3] and [4], the method saves the new configuration values.

The only thing that we must know about the saveConfig method is that it overwrites all the properties with the new ones provided in the serialized payload. Moreover, some of the properties, such as the username and password for the SMB share, are encrypted in the same manner as in the previously described deserialization vulnerability.

To sum up this part, we must send an InfoRail message with the following properties:

--Message subcategory: 1501.
--Message distribution list: 255.3.2.5 (Enterprise Server).

Below is a fragment of an example payload, which sets the File Store path to an attacker-controlled SMB server:

Arbitrary File Read Scenario

The whole Arbitrary File Read scenario can be summarized in the following picture:

Figure 2 - Example scenario for the Arbitrary File Read exploitation

  1. The attacker points the File Store to a non-existent SMB share. This step is optional, but makes the exploit cleaner by ensuring that files from the current File Store location will not be copied to the location where the attacker wants to retrieve the files.
  2. The attacker points the File Store to a desired local file system path from which he wants to disclose files.
  3. The attacker points the File Store to his SMB share.
  4. Files from the previous File Store path (local file system) are transferred to the attacker’s SMB share.

The following screenshot presents an example exploitation of this scenario:

Figure 3 - Exploitation of the Arbitrary File Read scenario

As shown, the exploit is targeting the main Ivanti Avalanche directory: C:\Program Files\Wavelink\Avalanche.

The following screenshot presents the exploitation results. Files from the Avalanche main directory were gradually copied to the attacker’s server:

Figure 4 - Exploitation of the Arbitrary File Read scenario - results

Arbitrary File Write Scenario

The following screenshot presents the Arbitrary File Write scenario:

Figure 5 - Example scenario for the Arbitrary File Write scenario

  1. The attacker creates an SMB share that contains the JSP webshell.
  2. The attacker points the File Store to a non-existent SMB share. This step is optional, but makes the exploit cleaner by ensuring that files from the current File Store location will not be copied to the Avalanche webroot.
  3. The attacker points the File Store to the SMB share containing the webshell file.
  4. The attacker points the File Store to the Ivanti Avalanche webroot directory.
  5. Avalanche copies the webshell to the webroot.
  6. The attacker executes code through the webshell.

The following screenshot presents an example exploitation attempt. It uploads a file named poc-upload.jsp to C:\Program Files\Wavelink\Avalanche\Web\webapps\ROOT:

Figure 6 - Exploitation of the Arbitrary File Write scenario

Finally, one can use the uploaded webshell to execute arbitrary commands.

Figure 7 - Executing arbitrary code via the webshell

CVE-2022-36981: Path Traversal in File Upload, Plus Authentication Bypass

We made it to the final vulnerability we will discuss today. This time, we will exploit a path traversal vulnerability in the Avalanche Smart Device Server, which listens on port TCP 8888 by default. However, InfoRail will play a role during the authentication bypass that allows us to reach the vulnerable code.

Path Traversal in File Upload

Our analysis begins with examining the uploadFile method.

At [1], the endpoint path is defined. The path contains two arguments: uuid and targetbasename.

At [2], the doUploadFile method is called.

Let’s start with the second part of the doUploadFile method, as I want to save the authentication analysis for later in this section.

At [1], the uploadPath string is obtained by calling getUploadFilePath. This method accepts two controllable input arguments: uuid and baseFileName.

At [2], the method instantiates a File object based on uploadPath.

At [3], the method invokes writeToFile, passing the attacker-controlled input stream together with the File object.

We will now analyze the crucial getUploadFilePath method, as this is the method that composes the destination path.

At [1], it constructs deviceRoot as an object of type File. The parameters passed to the constructor are the hardcoded path obtained from getCachePath() and the attacker-controllable uuid value. As shown above, uuid is not subjected to any validation, so we can perform path traversal here.

At [2], the code verifies that the deviceRoot directory exists. From here we see that uuid is intended to specify a directory. If the directory does not exist, the code creates it at [3].

At [4], it validates the attacker-controlled baseFileName against a regular expression. If the validation fails, baseFileName is reassigned at [5].

At [6], it creates a new filename fn, based on the current datetime, an integer value, and baseFileName.

At [7], it instantiates a new object of type File. The path for this File object is composed from uuid and fn.

After ensuring that the file does not already exist, the file path is returned at [8].

After analyzing this method, we can draw two conclusions:

       -- The uuid parameter is not validated to guard against path traversal sequences. An attacker can use this to escape to a different directory.
       -- The extension of baseFileName is not validated. An attacker can use this to upload a file with any extension, though the filename will be prepended with a datetime and an integer.

Ultimately, when doUploadFile calls writeToFile, it will create a new file with this name and write the attacker-controlled input stream to the file. This makes it seem that we can exploit this as a path traversal vulnerability and write an arbitrary file to the filesystem. However, there are two major obstacles that will be presented in the next section.

Authentication and Additional UUID Verification

Now that we’ve covered the second part, let’s go back and analyze the first part of the doUploadFile method.

At [1], the code retrieves the mysterious testFlags.

At [2], it validates the length of the uuid, to ensure it is at least 5 characters long.

At [3], it performs an authorization check (perhaps better thought of as an authentication check) by calling isAuthorized. This method accepts uuid, credentials (authorization), and testFlags.

At [4], the code retrieves the deviceId based on the provided uuid.

At [5], the code checks to see if any device was retrieved. If not, it checks for a specific value in testFlags at [6]. If this second check is also not successful, the code raises an exception.

At [7], it calls allowUpload to perform one additional check. However, this final check has nothing to do with validating uuid. It only verifies the amount of available disk space, and this should not pose any difficulties for us.

We can spot two potential roadblocks:

       -- There is an authentication check.
       -- There is a check on the value of uuid, in that it must map to a known deviceId. However, we can bypass this check if we could get control over testFlags. If testFlags & 0x100 is not equal to 0, the exception will not be thrown, and execution will proceed.

Let’s analyze the most important fragments of the isAuthorized method:

At [1], the method retrieves enrollmentId, found within the token submitted by the requester.

At [2], it tries to retrieve the enrollment object from the database, based on enrollmentId.

At [3], it checks to see if enrollment was retrieved.

Supposing that enrollment was not retrieved successfully, the code checks for a particular value in testFlags at [4]. If not, it will return false at [6]. But if the relevant value is found in testFlags, the authentication routine will return true at [5], even though the requester’s authorization token did not contain a valid enrollmentId.

Note that this method also checks an enrollment password, although that part is not important for our purposes.

Here as well, testFlags can also be used to bypass the relevant check. Hence, if we can control testFlags, neither the authentication nor the uuid validation will cause any further trouble for us.

Here is where InfoRail comes into play. It turns out that the Smart Device Server AgentTaskHandler message can be used to modify testFlags:

At [1], it retrieves flagsToSet from the sds.modflags.set property.

At [2], it obtains the Config Directory API interface.

At [3], it uses flagsToSet to calculate the new flags value.

At [4], it saves the new flag value.

To sum up, an attacker can control testFlags, and use this to bypass both the authentication check and the uuid check.

Exploitation

Exploitation includes two steps.

1) Set testFlags to bypass the authentication and the uuid check.

To modify the testFlags, the attacker must send an InfoRail message with the following parameters:

       -- Message subcategory: 2500.
       -- Distribution list: 255.3.2.17 (SDS server).
       -- Payload:

2) Exploit the path Traversal through a web request

The path traversal can be exploited with an HTTP Request, as in the following example:

The response will return the name of the uploaded webshell:

Finally, an attacker can use the uploaded JSP webshell for remote code execution as SYSTEM.

Figure 8 - Remote Code Execution with the uploaded webshell

Conclusion

I really hope that you were able to make it through this blog post, as I was not able to describe those issues with a smaller number of details (believe me, I have tried). As you can see, undiscovered attack surfaces can lead to both cool and dangerous vulnerabilities. It is something that you must look for, especially in products that are responsible for the administration of many other devices.

This blog post is the last in this series of articles on Ivanti Avalanche research. However, I am planning something new, and yes, it concerns Java deserialization. Until then, you can follow me @chudypb and follow the team on Twitter or Instagram for the latest in exploit techniques and security patches.

Riding the InfoRail to Exploit Ivanti Avalanche – Part 2

CVE-2022-34715: More Microsoft Windows NFS v4 Remote Code Execution

In this excerpt of a Trend Micro Vulnerability Research Service vulnerability report, Quintin Crist and Dusan Stevanovic 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 the researcher known as Arimura. The bug is the result of a dynamically allocated buffer created by an NFS function and is present only on Windows Server 2022. An unauthenticated attacker could exploit this bug to execute arbitrary code in the context of SYSTEM. This is the third such NFS vulnerability in as many months. The following is a portion of their write-up covering CVE-2022-34715, with a few minimal modifications.


A remote code execution vulnerability exists in Windows Network File System. The vulnerability is due to incorrect validation of fields within an NFS request. 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 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 shares, 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 defined for the GSS Procedure field: RPCSEC_GSS_DATA(0), RPCSEC_GSS_INIT(1), RPCSEC_GSS_CONTINUE_INIT(2), and RPCSEC_GSS_DESTROY(3). Also, for 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 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:

In the request data, for each operation in the message:

Operation data for opcode OP_CREATE(6):

Operation data for opcode OP_OPEN(18):

Operation data for opcode OP_SETATTR(34):

Attributes Data (fattr4) has the following format:

Attributes Data for ACL ( Bit12, 0x1000 ):

A buffer overflow vulnerability exists in the Windows implementation of NFS. The vulnerability is due to incorrect validation of the of the ACE_Count field when processing ACL attribute data in Nfs4SrvAclBuildWindowsAclsFromNfsAcl.

This function is only vulnerable when setting ACL attribute data using opcodes 6, 18, 34.

The server allocates a response buffer of size (ACE_Count << 5). This size is stored as a uint64_t in Nfs4SrvAclBuildWindowsAclsFromNfsAcl. A buffer of this size is created using NfsMemMgrBufferAllocate. However, NfsMemMgrBufferAllocate only takes a uint32_t for the buffer size, so the upper 32 bits of the requested size is ignored.

This allows an attacker to specify an ACE_Count such that (ACE_Count << 5) & 0xFFFFFFFF < ACE_Count. This will result in a buffer overflow later in the function when the buffer is used.

In particular, ACE_Count values above 0x8000000 will trigger this vulnerability.

Note that ACE_Count = 0x8000000 itself is not vulnerable since NfsMemMgrBufferAllocate will error when the requested length is zero.

An attacker can use this vulnerability to overflow a heap buffer. Successful exploitation may result in arbitrary code execution in the context of SYSTEM. Unsuccessful exploitation will result in a crash of the target system.

Source Code Walkthrough

The following code snippet was taken from nfssvr.sys version 10.0.20348.825. Comments have been added by Trend Micro researchers.

Detecting Attacks

The detection device needs to check if the Program field in an RPC request message has the value 100003 (NFS), Procedure field has the value 1 (COMPOUND), and Program Version field has the value 4 (NFS4). If found, the device must inspect the Program-specific data in the ONC RPC messages.

The detection device should check for the vulnerable opcodes (6, 18, 34) in each operation. If present the device should check the operation for ACL attribute data. If ACL attribute data is present, the device should check for an ACE_Count field above 0x8000000.

There is no fixed offset into the message that can be used to ignore non-vulnerable opcodes since NFS operations do not consistently contain a length of the operation data. The full message must be processed to determine if there is any ACL attribute data.

If the ACE_Count field is greater than 0x8000000, the traffic should be considered suspicious; an attack exploiting this vulnerability is likely underway.

Conclusion

This bug was patched by Microsoft in August 2022 and assigned CVE-2022-34715. Their advisory lists the vulnerability as not requiring authentication. However, all known exploitation paths require file creation or modification privileges. 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. Applying the NFS-related updates is the best method to fully address the multiple NFS bugs patched in recent months.

Special thanks to Quintin Crist and Dusan Stevanovic 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 team on Twitter or Instagram for the latest in exploit techniques and security patches.

CVE-2022-34715: More Microsoft Windows NFS v4 Remote Code Execution

Announcing Pwn2Own Toronto 2022 and Introducing the SOHO Smashup!

29 August 2022 at 15:09

If you just want to read the rules, you can find them here.

Our Fall Pwn2Own event has become a bit of a nomad, having gone from Amsterdam to Tokyo to Austin. This year, we’re heading to Toronto to celebrate the 10th anniversary of the contest formerly known as Mobile Pwn2Own. Since 2012, we’ve expanded the contest to include devices beyond phones. This year is no different, with devices typically found on homes and home offices.

Pwn2Own Toronto will be held at our Toronto office on December 6-8, 2022. While this year’s contest isn’t being held in conjunction with a conference, we still want contestants to attend in person. In fact, we want them there so much that we’re going to put our money where our mouth is by reimbursing $3,000 for travel expenses for teams that participate in Toronto. We’re also going to try to have some sort of audience there as well, but we’re not offering cash just to watch. If you are a former Pwn2Own winner and would like more information about this program, you know how to get in touch with us.

If you can’t be in Toronto due to travel restrictions or travel safety concerns, you can opt to compete remotely. You will still need to register before the contest deadline (December 2, 2022) and submit a detailed whitepaper completely explaining your exploit chain and instructions on how to run the entry by December 5, 2022. A member of the ZDI staff in Toronto will run your exploit for you. All attempts will be filmed and available for viewing by the contestant and the vendor. As in the past, we will work with remote contestants to monitor the attempt in real-time via a phone call or video chat. Please note that since you are not in person, changes to exploits/scripts/etc. will not be possible, which could lower your chance of winning should something unexpected occur.

As for the contest itself, we’re pleased to welcome back Synology as a co-sponsor of the competition. We’re also excited to announce a special challenge for this year’s contest we’re calling the “SOHO Smashup” (as in Small Office/Home Office). This is a real-world scenario of how a threat actor would exploit a home office, so we wanted to include it here, too. It works like this; a contestant picks a router and begins by exploiting the WAN interface. They must then pivot into the LAN to their choice of second target – one of the other devices in the contest. For example, you could pick the TP-Link router and the HP printer. If you compromise both, you’ll win $100,000 and 10 Master of Pwn points.

Beyond that, the contest remains largely the same as in previous years. We will have a random drawing to determine the schedule of attempts on the first day of the contest, and we will proceed from there. Our intention with allowing remote participation is to provide as many people as possible with the benefits of participating in Pwn2Own while still treating all contestants as equally as possible. As always, if you have questions, please contact us at [email protected]. We will be happy to address your issues or concerns directly.

Now on to the specific target categories. We’ll have seven different categories for this year’s event:

- Mobile Phones
- Wireless Routers
- Home Automation Hubs
- Printers
- Smart Speakers
- NAS Devices
- The SOHO Smashup

Let’s take a look at each category in more detail, starting with mobile phones.

The Target Phones

Back when this version of Pwn2Own started in 2012, it was called Mobile Pwn2Own, and phones are still at the heart of our fall event. As always, these phones will be running the latest version of their respective operating systems with all available updates installed. We’ve increased the rewards on these targets to add further incentives to these handsets.

In this category, contestants must compromise the device by browsing to content in the default browser for the target under test or by communicating with the following short-distance protocols: near field communication (NFC), Wi-Fi, or Bluetooth. The awards for this category are:

Mobile Phone Targets

The Google and Apple devices in this category also include an add-on bonus. If your exploit payload executes with kernel-level privileges, you earn an additional $50,000 and 5 more Master of Pwn points. That means a full exploit chain for the iPhone or Pixel that includes kernel-level access will earn $250,000.

Back to top

Routers - Your SOHO Entry Point

You connect to the world through your local wireless router, and the world has the opportunity to reach back to you. In the past, successful demonstrations included some flair by having the LED lights flash in different patterns. In addition to the home office routers, we have some devices typically used by SMBs as well. An attempt in this category must be launched against the target’s exposed network services from the contestant’s device within the contest network.

WiFi Router Targets

Back to top

Home Automation Hubs

As people add smart devices to their homes, they tend to add a hub to centralize control of all of those devices. From lights, to locks, to thermostats, cameras, and more, all can be accessed through a home automation hub. Of course, that means a threat actor could potentially access them as well. Three of the most popular smart hubs are included in this year’s event.

Home Automation Targets

Back to top

The Return of Printers

Exploits involving printing capabilities have made quite a bit of news over the last couple of years, with ransomware gangs incorporating PrintNightmare bugs in their exploit kits. In last year’s contest, one printer was turned into a jukebox playing classic rock. It will be interesting to see what exploits the contestants come up with this year.

Back to top

Smart Speakers

Smart speakers continue to play a large part in our daily interactions with music, news, and more. They also offer an attack surface for threat actors to target. For this event, Pwn2Own Toronto has three targets available in this category.

Smart Speaker Targets

Back to top

Network Attached Storage (NAS) Devices

NAS devices make their return to Pwn2Own, and both Synology and Western Digital have returned as targets with their latest offerings. Last year’s event exposed some industry-wide Netatalk bugs. Time will tell if this year’s event has a similar impact. An attempt in this category must be launched against the target’s exposed network services from the contestant’s laptop within the contest network. 

Back to top

The SOHO Smashup

With more and more people working from home, many enterprises have found their network perimeter move to the home office as well. Threat actors who exploit home routers and consumer devices can use these as a launch point for lateral movements into enterprise resources. We wanted to demonstrate this during the contest, so we’re introducing the SOHO Smashup category to show how this could happen. Contestants will need to first compromise the WAN port on a selected router. Once they accomplish that, they will need to pivot to one of the other devices and compromise it as well. The contestant is free to select any combination of router and home automation hub, smart speaker, printer, or network attached storage device during the registration process. If they get both devices within 30 minutes, they earn $100,000 and 10 Master of Pwn points. We’re hopeful several contestants will use this category to choose their own (mis)adventure.

Back to top

Master of Pwn

No Pwn2Own contest would be complete without crowning a Master of Pwn, which signifies the overall winner of the competition. Earning the title results in a slick trophy, a different sort of wearable, and brings with it an additional 65,000 ZDI reward points (instant Platinum status in 2023).

For those not familiar with how it works, points are accumulated for each successful attempt. While only the first demonstration in a category wins the full cash award, each successful entry claims the full number of Master of Pwn points. Since the order of attempts is determined by a random draw, those who receive later slots can still claim the Master of Pwn title – even if they earn a lower cash payout. As with previous contests, there are penalties for withdrawing from an attempt once you register for it. If the contestant decides to remove an Add-on Bonus during their attempt, the Master of Pwn points for that Add-on Bonus will be deducted from the final point total for that attempt. For example, someone registers for the Apple iPhone 13 with the Kernel Bonus Add-on. During the attempt, the contestant drops the Kernel Bonus Add-on but completes the attempt. The final point total will be 15 Master of Pwn points.

The Complete Details

The full set of rules for Pwn2Own Toronto 2022 can be found here. They may be changed at any time without notice. We highly encourage potential entrants to read the rules thoroughly and completely should they choose to participate. We also encourage contestants to read this blog covering what to expect when participating in Pwn2Own.

Registration is required to ensure we have sufficient resources on hand at the event. Please contact ZDI at [email protected] to begin the registration process. (Email only, please; queries via Twitter, blog post, or other means will not be acknowledged or answered.) If we receive more than one registration for any category, we’ll hold a random drawing to determine the contest order. Registration closes at 5:00 p.m. Eastern Daylight Time on December 2, 2022.

The Results

We’ll be blogging and tweeting results in real-time throughout the competition. Be sure to keep an eye on the blog for the latest information. Follow us on Twitter at @thezdi and @trendmicro, and keep an eye on the #P2OToronto hashtag for continuing coverage.

We look forward to seeing everyone in Toronto and online, and we look forward to seeing what new exploits and attack techniques they bring with them.

With special thanks to our Pwn2Own Toronto 2022 sponsor, Synology, for providing their assistance and technology.

©2022 Trend Micro Incorporated. All rights reserved. PWN2OWN, ZERO DAY INITIATIVE, ZDI, and Trend Micro are trademarks or registered trademarks of Trend Micro Incorporated. All other trademarks and trade names are the property of their respective owners. The “Synology” logo are trademarks of Synology, Inc., registered in the Republic of China (Taiwan) and other regions.

Announcing Pwn2Own Toronto 2022 and Introducing the SOHO Smashup!

But You Told Me You Were Safe: Attacking the Mozilla Firefox Sandbox (Part 2)

23 August 2022 at 16:34

In the first part of this series, we reviewed how Pwn2Own contestant Manfred Paul was able to compromise the Mozilla Firefox renderer process via a prototype pollution vulnerability in the await implementation. In modern browser architecture design, compromising the renderer gets us just half the way there, since the sandbox prevents further damage. In this blog post, we discuss a second prototype pollution vulnerability that allowed the execution of attacker-controlled JavaScript in the privileged parent process, escaping the sandbox. This vulnerability is known as CVE-2022-1529 and is tracked as ZDI-22-798 on the Zero Day Initiative advisory page. Mozilla fixed this vulnerability along with the first one in Firefox 100.0.2 via Mozilla Foundation Security Advisory 2022-19.

Root Cause

As described in the previous post, the exploit compromised the renderer by leveraging a prototype pollution vulnerability in some built-in JavaScript code that executes in the renderer process. For the sandbox escape part of the exploit, the researcher used a second prototype pollution vulnerability. This second vulnerability exists in built-in JavaScript code that runs in the fully privileged parent process, also known as the chrome process (not to be confused with Google’s Chrome browser).

How can the sandboxed renderer process affect JavaScript running in the chrome process? The answer is that the renderer can communicate with the chrome process via various interfaces. In fact, some of these interfaces can be reached directly from JavaScript when running in a “privileged” JavaScript context (not to be confused with any OS-level concept of privilege). As we will see, achieving “privileged” JavaScript execution will be the exploit’s first step.

After achieving privileged JavaScript execution, the exploit can reach out to various endpoints for communication with the chrome process. One of the endpoints is called NotificationDB. It is implemented almost entirely in JavaScript. It processes various messages, which it receives via the content process message manager. In the case of a “Notification:Save” message, a “save” task is queued:

After the “save” task is put on the queue, it is handled in the chrome process, in the “taskSave” function:

At [1], both origin and notification.id are taken directly from the message data sent by the renderer, without any validation. This means we can set either of these to any serializable JavaScript value. More specifically, we can set them to any values supported by the structured clone algorithm, since this is the algorithm used to marshal data from the renderer to the chrome process. If we set origin to the string "__proto__", then this.notifications[origin] will not access a normal data property. Instead, it will access the object’s prototype. This prototype is Object.prototype, since this.notifications is a plain Object. This gives us a prototype pollution primitive. It allows us to write any serializable JavaScript value to any property of Object.prototype with only one restriction: the value we write must have an id property that matches the property name we are writing to.

Using this prototype pollution, we can corrupt the global JavaScript state in the chrome process. This affects all JavaScript that runs in the chrome process, far beyond NotificationDB.jsm itself. Since JavaScript execution contexts are largely shared, all chrome-level JavaScript modules are now exposed to unexpected properties in Object.prototype. The exploit will use this corruption to gain chrome-level XSS during tab restoration, leading to native code execution outside the sandbox.

Now that we have a complete picture of what we want to do, let’s begin.

Achieving Privileged JavaScript Execution

As mentioned above, before we can invoke NotificationDB, we need to access a privileged JavaScript context. In particular, what we need is access to an object called components. This is a different object than a much more limited object confusingly also named Components, which is intended to be exposed to untrusted script.

To gain access to components, the attacker script performs the following steps. Note that all this is made possible because the attacker script has already gained full native code execution within the renderer sandbox, as detailed in part one of this series:

        1 -- Mark the current JavaScript compartment as system by setting the corresponding flag in memory.
        2 -- Patch CanCreateWrapper to always return NS_OK. This prevents further security checks on the calling context.
        3 -- Call the GetComponents method to add the components object to the scope.

Triggering the Prototype Pollution Primitive

Once we have obtained the components object, we are nearly ready to trigger the prototype pollution. One obstacle remains: due to the details of Firefox's “cross-compartment” handling of JavaScript objects, the ContentProcessMessageManager object we want to access is hidden behind an opaque proxy object. This can be circumvented by reading the proxy’s underlying object pointer and using a “fakeObj” to convert it to a JavaScript object. We can now call the vulnerable NotificationDB interface:

Remember that a limitation applies to the way that we can overwrite properties of Object.prototype: we can set any property name to any value val, but val.id must equal name. For our purposes, the exact value of val will not matter. Only its string representation is important (more precisely, the result of running the ECMAScript ToString algorithm). The loose type system of JavaScript helps us here. Consider the following array object:

This object has its id property set to the arbitrary string "foo", but ToString will represent the object by just the string "bar". Therefore, as long as we only care about the string representation, we can set any property of Object.prototype to any value we desire.

Leveraging the Prototype Pollution for Sandbox Escape

Consider the following code in browser/components/sessionstore/TabAttributes.jsm, which executes in the chrome process:

Note that a for ... in loop will traverse all properties found in the prototype chain, and not only the properties found on the object itself. Therefore, by invoking the code shown above after we have polluted Object.prototype, we can cause tab.setAttribute to be called with arbitrary parameters. This will set an arbitrary HTML (technically XUL) attribute of a tab.

How can we cause this function to run? It turns out that the only time it is called is during the restoration of tabs. There are multiple ways to trigger this functionality:

        1 -- Session restoration after restarting the browser.
        2 -- Use of the “reopen closed tab” feature (Ctrl+Shift+T).
        3 -- Reactivating a tab after “Tab Unloading”, which occurs when Firefox starts to run out of memory.
        4 -- Automatically restoring a tab after it has crashed.

The first choice is not an option, since restarting the browser would not preserve the polluted prototype. In the real world, waiting for option #2 might work, but it requires user interaction, making it unsuitable for Pwn2Own. It’s also possible to force option #3 by allocating large chunks of memory. However, by default, it takes at least 10 minutes of inactivity before unloading will happen, which exceeds the Pwn2Own time constraint. This leaves just option #4. Fortunately, crashing the renderer process is trivial: we have already achieved memory corruption, and we can simply write to an invalid address to force a segmentation fault.

So far, the sandbox escape exploit proceeds as follows:

        1 -- Trigger the prototype pollution, adding a property and value to Object.prototype in the chrome process. The name/value pair we add corresponds to the parameters we want to pass to tab.setAttribute. For example, if we add a property named "a" with string value "b", then tab.setAttribute will ultimately be invoked with parameters ("a", "b").
        2 -- Open a new background tab. Note that a simple window.open method call without prior user interaction is blocked by the popup blocker. However, the check is entirely renderer-side, and the services.ww.openWindow API obtained from the components object has no such restriction.
        3 -- In this background tab, crash the renderer. The chrome process will immediately restore the background tab. The polluted prototype will cause the tab restoration logic to set our chosen attribute on the tab.

Next, we must consider: what parameters do we want to pass to tab.setAttribute? As the browser UI that contains the tab element is written not in HTML but rather the similar XUL markup language, attributes such as “onload” or “onerror” that are commonly used for XSS do not seem to work. Going through a list of XUL event handlers, there are only two that seem to work without any direct user interaction: “onoverflow” and “onunderflow”. These are triggered when the tab’s title text starts to exceed or no longer exceeds the available space. We can trigger the former by setting a style attribute with the value text-indent: 500px.

Once we have achieved JavaScript execution within the chrome process, there are many ways to complete the sandbox escape. For example, we could disable all sandboxing in the future by setting a preference:

  Services.prefs.setIntPref("security.sandbox.content.level", 0);

Afterward, the exploit could run script in a new tab, which will be created without any sandbox protections. Alternatively, it could run script directly in the chrome process. Either way, the file and process APIs that are available in chrome-level JavaScript can be used to gain native code execution not constrained by any sandbox:

Here is a short video demonstrating running the full exploit against Mozilla Firefox 100.0.1 (64-bit):

Final Notes

Modern browsers process large volumes of data coming from numerous untrusted sources. Modern browser architecture goes a long way towards containing damage in cases where the renderer process is compromised. However, there remain multiple security checks that are performed on the renderer side. We have seen how these checks could be bypassed, ultimately leading to full compromise of the main browser process. In general, it is wise to reduce renderer-side security checks and move them to the main process wherever it is practical.

You can find me on Twitter at @hosselot and follow the team on Twitter or Instagram for the latest in exploit techniques and security patches.

But You Told Me You Were Safe: Attacking the Mozilla Firefox Sandbox (Part 2)

But You Told Me You Were Safe: Attacking the Mozilla Firefox Renderer (Part 1)

18 August 2022 at 15:31

Vulnerabilities and exploits in common targets like browsers are often associated with memory safety issues. Typically this involves either a direct error in memory management or a way to corrupt internal object state in the JavaScript engine. One way to eliminate such memory safety issues is to use a memory-safe language such as Rust or even JavaScript itself. At Pwn2Own Vancouver 2022, Manfred Paul compromised the Mozilla Firefox browser using a full chain exploit that broke the mold. Although his exploit used some memory corruptions, the vulnerable code was written in a memory-safe programming language: JavaScript! In fact, both vulnerabilities used in the chain were related to one rather notorious language aspect of JavaScript – prototypes. In this blog, we will look at the first vulnerability in the chain, which was used to compromise the Mozilla Firefox renderer process. This vulnerability, known as CVE-2022-1802, is a prototype pollution vulnerability in the await implementation. You can find more information about this vulnerability on the Zero Day Initiative advisory page tracked as ZDI-22-799. Mozilla fixed this vulnerability in Firefox 100.0.2 via Mozilla Foundation Security Advisory 2022-19.

Note: this blog series is heavily reliant on the details provided by Manfred Paul at the Pwn2Own competition.

 Compromising The Renderer Process

Modern JavaScript features the module syntax, which allows developers to split code into individual files. An even newer feature is the support of asynchronous modules, or, more precisely, the feature known as top level await. In Firefox’s JavaScript engine, SpiderMonkey, large parts of this feature are implemented using built-in JavaScript code. Consider the following function from the SpiderMonkey codebase, in /js/src/builtin/Module.js:

There are three facts we must note the code shown above:

      1 -- This function runs in the same JavaScript context as the user’s code. This is true for most JavaScript-based functions in Firefox. This means that global state, including prototypes of global objects, is shared between this built-in code and untrusted website code.

      2 -- The function has a default argument of execList = []. In practice, the function is called without specifying this argument (except for the recursive call in the function itself). Therefore, a new empty array object is constructed and used for this argument. Like any other ordinary array, this array object has the unique object Array.prototype as its prototype.

      3 -- The function invokes std_Array_push on this array object. The std_Array_push function leads to a call to the Array.prototype.push JavaScript method. While the usage of std_Array_push function instead of Array.prototype.push helps prevent side effects up to a certain point, the function still can interact with the object’s prototype. (Note that in various other places within this same built-in JavaScript file /js/src/builtin/Module.js, a different function is used to assign array values: DefineDataProperty. In contrast to std_Array_push, DefineDataProperty is safe and will not interact in any way with the object’s prototype.)

The semantics of Array.prototype.push with a single argument are very roughly equivalent to the following:

Notably, the assignment is not just the definition of a data property on the object itself. Instead, it searches the object’s prototype chain for existing properties as per usual JavaScript semantics. If the imported module defines a getter/setter for property 0 on the Array prototype (Array.prototype), this assignment operation will trigger the setter function. This call technically violates the ECMAScript specification that defines GatherAsyncParentCompletions in terms of abstract lists and not actual JavaScript arrays. Crucially, this has yet another effect: it leaks the value that is assigned to our setter, so we recover the value “m” representing a module! This object is not the same as the module namespace returned by import(), but rather, it is an internal type of the JavaScript engine not meant to be accessible to untrusted script. It exposes some unsafe methods via its prototype, such as GatherAsyncParentCompletions. Calling GatherAsyncParentCompletions results in a call to the UnsafeSetReservedSlot method, which can be used to achieve memory corruption if we pass in a non-module object.

Triggering The Vulnerability

It is easy to trigger the vulnerability and obtain a Module object:

As described, we simply need to attach a setter to the 0 property of Array.prototype and wait for it to be called. Note that this snippet will only work when imported as a module from another file. The last line exists solely to mark the module as asynchronous, which is needed to trigger the bug.

Achieving Memory Corruption

To achieve memory corruption, we can now call mod.gatherAsyncParentCompletions with an object of the form {asyncParentModules:[obj]}, resulting in a call to UnsafeSetReservedSlot . This will attempt to write the value obj.pendingAsyncDependencies-1 to the internal object slot with number MODULE_OBJECT_PENDING_ASYNC_DEPENDENCIES_SLOT=20. In SpiderMonkey, objects have space for up to 16 so-called fixed slots which are for internal use only. This number is defined by the MAX_FIXED_SLOTS constant. Slots with a higher index are indexed from an array pointed to by the slots_ field. This means our write will be directed to the array pointed to by slots_. No bounds checking exists to make sure that the slots_ array is large enough to accommodate the specified index, because the UnsafeSetReservedSlot function assumes, as the name implies, that the caller will pass only suitable objects.

The general idea now is to:

       1 -- Create a new array object.

       2 -- Set some named properties of the object to force the allocation of a slots_ array for the object. Among these properties, we should create one with the name pendingAsyncDependencies.

       3 -- Write to a few numbered elements of the object to ensure the allocation of elements_ (the backing store for array elements).

By getting the alignment right, slots_[4] will then point to the capacity value of elements_, which we can then overwrite. This is not trivial. Fortunately, the heap allocator is very simple and deterministic. All of the allocations so far will take place in the nursery heap, which is a special area for small short-lived objects. Memory in that area will be allocated by a simple bump allocator. After increasing the capacity, we can write out-of-bounds of the object’s elements_ array and corrupt other nearby objects. From here, arbitrary read and write primitives are easily constructed by overwriting the data pointer of a typed array. Note that corruption in objects in the nursery heap cannot be used for very long since the objects created there will be soon moved to the tenured heap. The best way to proceed is to use corruption in the nursery heap as a first stage only, and immediately use it to produce corruption in the tenured heap. For example, this can be done by corrupting ArrayBuffer objects.

Executing Shellcode

Firefox uses W^X JIT, which means all JIT-produced executable pages are non-writable. This prevents us from overwriting executable JIT code with our shellcode. There is an already well-known method to force JIT to emit arbitrary ROP gadgets by embedding chosen floating-point constants into a JIT-compiled JavaScript function. This results in the appearance of arbitrary short byte sequences in an executable page. Manfred Paul further enhanced this technique. Now it does not even need ROP at all! Instead of using a JavaScript function, the floating-point constants are embedded into a WebAssembly method, so they are compiled into consecutive memory in order of appearance. This makes it possible to insert not just ROP gadgets, but even somewhat longer stretches of shellcode by encoding them in the floating-point constants. There are still some restrictions, though: no 8-byte block may appear twice, or the constant will only be emitted once. Also, due to ambiguity in representation, byte sequences that are equal to NaN might not be encoded correctly. Therefore, Manfred Paul opted for a minimal first-stage shellcode that offers just the following two pieces of functionality:

       1 -- The ability to read a pointer from the Windows PEB structure.

       2 -- The ability to invoke a function given the function’s address.

The attacker, from ordinary JavaScript, triggers execution of the shellcode’s first function to leak a value from the PEB. Next, the JavaScript uses this value together with the arbitrary read primitive to locate kernel32.dll and its functions in memory. Once it has located the address for VirtualProtect, it invokes the shellcode’s second function to mark the backing store of an ArrayBuffer object as executable, making it possible to run a second-stage shellcode without constraints and compromise the renderer process.

Now that we have code execution inside the renderer, it is time to prepare to attack the sandbox. This will be covered in the second blog, coming next week.

Final Notes

For a long time, developers have tried to fight memory corruption vulnerabilities by introducing various mitigations, and they have succeeded in making it more difficult for attackers to fully compromise applications. However, attackers have also come up with their own creative methods to bypass mitigations. Using a memory-safe programming language is a critical move. If the introduction of memory corruption vulnerabilities can be avoided in the first place, it would not be necessary to rely upon the strength of mitigations. This post looked at a great vulnerability demonstrating that even if you replace existing code with JavaScript, you could still be prone to memory corruption.

Stay tuned to this blog for part two of this series coming next week. Until then, you can find me on Twitter at @hosselot and follow the team on Twitter or Instagram for the latest in exploit techniques and security patches.

But You Told Me You Were Safe: Attacking the Mozilla Firefox Renderer (Part 1)

New Disclosure Timelines for Bugs Resulting from Incomplete Patches

11 August 2022 at 19:00

Today at the Black Hat USA conference, we announced some new disclosure timelines. Our standard 120-day disclosure timeline for most vulnerabilities remains, but for bug reports that result from faulty or incomplete patches, we will use a shorter timeline. Moving forward, the ZDI will adopt a tiered approach based on the severity of the bug and the efficacy of the original fix. The first tier will be a 30-day timeframe for most Critical-rated cases where exploitation is detected or expected. The second level will be a 60-day interval for Critical- and High-severity bugs where the patch offers some protections. Finally, there will be a 90-day period for other severities where no imminent exploitation is expected. As with our normal timelines, extensions will be limited and granted on a case-by-case basis.

Since 2005, the ZDI has disclosed more than 10,000 vulnerabilities to countless vendors. These bug reports and subsequent patches allow us to speak from vast experience when it comes to the topic of bug disclosure. Over the last few years, we’ve noticed a disturbing trend – a decrease in patch quality and a reduction in communications surrounding the patch. This has resulted in enterprises losing their ability to accurately estimate the risk to their systems. It’s also costing them money and resources as bad patches get re-released and thus re-applied.

Adjusting our disclosure timelines is one of the few areas that we as a disclosure wholesaler can control, and it’s something we have used in the past with positive results. For example, our disclosure timeline used to be 180 days. However, based on data we tracked through vulnerability disclosure and patch release, we were able to lower that to 120 days, which helped reduce the vendor’s overall time-to-fix. Moving forward, we will be tracking failed patches more closely and will make future policy adjustments based on the data we collect.

Another thing we announced today is the creation of a new Twitter handle: @thezdibugs. This feed will only tweet out published advisories that are either a high CVSS, 0-day, or resulting from Pwn2Own. If you’re interested in those types of bug reports, we ask that you give it a follow. We’re also now on Instagram, and you can follow us there if you prefer that platform over Twitter.

Looking at our published and upcoming bug reports, we are on track for our busiest year ever – for the third year in a row. That also means we’ll have plenty of data to look at as we track incomplete or otherwise faulty patches, and we’ll use this data to adjust these timelines as needed based on what we are seeing across the industry. Other groups may have different timelines, but this is our starting point. With an estimated 1,700 disclosures this year alone, we should be able to gather plenty of metrics. Hopefully, we will see improvements as time goes on.

Until then, stay tuned to this blog for updates, subscribe to our YouTube channel, and follow us on Twitter for the latest news and research from the ZDI. 

New Disclosure Timelines for Bugs Resulting from Incomplete Patches

The August 2022 Security Update Review

9 August 2022 at 17:31

It’s the second Tuesday of the month, and the last second Tuesday before Black Hat and DEFCON, which means Microsoft and Adobe have released their latest security fixes. Take a break from packing (if you’re headed to hacker summer camp) or your normal activities and join us as we review the details of their latest patches and updates.

Adobe Patches for August 2022

For August, Adobe addressed 25 CVEs in five patches for Adobe Acrobat and Reader, Commerce, Illustrator, FrameMaker, and Adobe Premier Elements. A total of 13 of these bugs were reported through the ZDI program. The update for Acrobat and Reader addresses three Critical-rated and four Important-rated bugs. The critical vulnerabilities could allow code execution if an attacker could convince a user to open a specially crafted file. There are also seven total fixes for Commerce, including four Critical-rated bugs. Two of these could allow code execution and two could lead to a privilege escalation. The XML injection bug fixed by this has the highest CVSS of Adobe’s release at 9.1. The patch for Illustrator contains two Critical and two Important fixes for bugs submitted by ZDI Security Researcher Mat Powell. The most severe could lead to code execution when opening a specially crafted file. Mat is also responsible for the six FrameMaker bugs, five of which could lead to code execution. Finally, there’s a single Critical-rated CVE in the Premier Elements patch resulting from an uncontrolled search path element.

None of the bugs fixed by Adobe this month are listed as publicly known or under active attack at the time of release. Adobe categorizes the majority of these updates as a deployment priority rating of 3, with the Acrobat patch being the lone exception at 2.

Microsoft Patches for August 2022

This month, Microsoft released 121 new patches addressing CVEs in Microsoft Windows and Windows Components; Azure Batch Node Agent, Real Time Operating System, Site Recovery, and Sphere; Microsoft Dynamics; Microsoft Edge (Chromium-based); Exchange Server; Office and Office Components; PPTP, SSTP, and Remote Access Service PPTP; Hyper-V; System Center Operations Manager; Windows Internet Information Services; Print Spooler Components; and Windows Defender Credential Guard. This is in addition to the 17 CVEs patched in Microsoft Edge (Chromium-based) and three patches related to secure boot from CERT/CC. That brings the total number of CVEs to 141. A total of eight of these bugs were reported through the ZDI, including some (but not all) of the bugs reported during the last Pwn2Own.

The volume of fixes released this month is markedly higher than what is normally expected in an August release. It’s almost triple the size of last year’s August release, and it’s the second largest release this year.

Of the 121 new CVEs released today, 17 are rated Critical, 102 are rated Important, one is rated Moderate, and one is rated Low in severity. Two of these bugs are listed as publicly known, and one is listed as under active attack at the time of release. Let’s take a closer look at some of the more interesting updates for this month, starting with the MSDT bug under active attack:

-       CVE-2022-34713 – Microsoft Windows Support Diagnostic Tool (MSDT) Remote Code Execution Vulnerability
This is not the first time an MSDT bug has been exploited in the wild this year. This bug also allows code execution when MSDT is called using the URL protocol from a calling application, typically Microsoft Word. There is an element of social engineering to this as a threat actor would need to convince a user to click a link or open a document. It’s not clear if this vulnerability is the result of a failed patch or something new. Either way, test and deploy this fix quickly.

 -       CVE-2022-35804 – SMB Client and Server Remote Code Execution Vulnerability
The server side of this bug would allow a remote, unauthenticated attacker to execute code with elevated privileges on affected SMB servers. Interestingly, this bug only affects Windows 11, which implies some new functionality introduced this vulnerability. Either way, this could potentially be wormable between affected Windows 11 systems with SMB server enabled. Disabling SMBv3 compression is a workaround for this bug, but applying the update is the best method to remediate the vulnerability.

 -       CVE-2022-21980/24516/24477 – Microsoft Exchange Server Elevation of Privilege Vulnerability
I couldn’t pick between these three Critical-rated Exchange bugs, so I’m listing them all. Rarely are elevation of privilege (EoP) bugs rated Critical, but these certainly qualify. These bugs could allow an authenticated attacker to take over the mailboxes of all Exchange users. They could then read and send emails or download attachments from any mailbox on the Exchange server. Administrators will also need to enable Extended Protection to fully address these vulnerabilities.

 -       CVE-2022-34715 – Windows Network File System Remote Code Execution Vulnerability
This is now the fourth month in a row with an NFS code execution patch, and this CVSS 9.8 bug could be the most severe of the lot. To exploit this, a remote, unauthenticated attacker would need to make a specially crafted call to an affected NFS server. This would provide the threat actor with code execution at elevated privileges. Microsoft lists this as Important severity, but if you’re using NFS, I would treat it as Critical. Definitely test and deploy this fix quickly.

-       CVE-2022-35742 - Microsoft Outlook Denial of Service Vulnerability
This was reported through the ZDI program and is a mighty interesting bug. Sending a crafted email to a victim causes their Outlook application to terminate immediately. Outlook cannot be restarted. Upon restart, it will terminate again once it retrieves and processes the invalid message. It is not necessary for the victim to open the message or to use the Reading pane. The only way to restore functionality is to access the mail account using a different client (i.e., webmail, or administrative tools) and remove the offending email(s) from the mailbox before restarting Outlook.

Here’s the full list of CVEs released by Microsoft for August 2022:

CVE Title Severity CVSS Public Exploited Type
CVE-2022-34713 Microsoft Windows Support Diagnostic Tool (MSDT) Remote Code Execution Vulnerability Important 7.8 Yes Yes RCE
CVE-2022-30134 Microsoft Exchange Information Disclosure Vulnerability Important 7.6 Yes No Info
CVE-2022-30133 Windows Point-to-Point Protocol (PPP) Remote Code Execution Vulnerability Critical 9.8 No No RCE
CVE-2022-35744 Windows Point-to-Point Protocol (PPP) Remote Code Execution Vulnerability Critical 9.8 No No RCE
CVE-2022-34691 Active Directory Domain Services Elevation of Privilege Vulnerability Critical 8.8 No No EoP
CVE-2022-33646 Azure Batch Node Agent Remote Code Execution Vulnerability Critical 7 No No RCE
CVE-2022-21980 Microsoft Exchange Server Elevation of Privilege Vulnerability Critical 8 No No EoP
CVE-2022-24477 Microsoft Exchange Server Elevation of Privilege Vulnerability Critical 8 No No EoP
CVE-2022-24516 Microsoft Exchange Server Elevation of Privilege Vulnerability Critical 8 No No EoP
CVE-2022-35752 RAS Point-to-Point Tunneling Protocol Remote Code Execution Vulnerability Critical 8.1 No No RCE
CVE-2022-35753 RAS Point-to-Point Tunneling Protocol Remote Code Execution Vulnerability Critical 8.1 No No RCE
CVE-2022-35804 SMB Client and Server Remote Code Execution Vulnerability Critical 8.8 No No RCE
CVE-2022-34696 Windows Hyper-V Remote Code Execution Vulnerability Critical 7.8 No No RCE
CVE-2022-34702 Windows Secure Socket Tunneling Protocol (SSTP) Remote Code Execution Vulnerability Critical 8.1 No No RCE
CVE-2022-34714 Windows Secure Socket Tunneling Protocol (SSTP) Remote Code Execution Vulnerability Critical 8.1 No No RCE
CVE-2022-35745 Windows Secure Socket Tunneling Protocol (SSTP) Remote Code Execution Vulnerability Critical 8.1 No No RCE
CVE-2022-35766 Windows Secure Socket Tunneling Protocol (SSTP) Remote Code Execution Vulnerability Critical 8.1 No No RCE
CVE-2022-35767 Windows Secure Socket Tunneling Protocol (SSTP) Remote Code Execution Vulnerability Critical 8.1 No No RCE
CVE-2022-35794 Windows Secure Socket Tunneling Protocol (SSTP) Remote Code Execution Vulnerability Critical 8.1 No No RCE
CVE-2022-34716 .NET Spoofing Vulnerability Important 5.9 No No Spoofing
CVE-2022-34685 Azure RTOS GUIX Studio Information Disclosure Vulnerability Important 7.8 No No Info
CVE-2022-34686 Azure RTOS GUIX Studio Information Disclosure Vulnerability Important 7.8 No No Info
CVE-2022-30175 Azure RTOS GUIX Studio Remote Code Execution Vulnerability Important 7.8 No No RCE
CVE-2022-30176 Azure RTOS GUIX Studio Remote Code Execution Vulnerability Important 7.8 No No RCE
CVE-2022-34687 Azure RTOS GUIX Studio Remote Code Execution Vulnerability Important 7.8 No No RCE
CVE-2022-35773 Azure RTOS GUIX Studio Remote Code Execution Vulnerability Important 7.8 No No RCE
CVE-2022-35779 Azure RTOS GUIX Studio Remote Code Execution Vulnerability Important 7.8 No No RCE
CVE-2022-35806 Azure RTOS GUIX Studio Remote Code Execution Vulnerability Important 7.8 No No RCE
CVE-2022-35776 Azure Site Recovery Denial of Service Vulnerability Important 6.2 No No DoS
CVE-2022-35802 Azure Site Recovery Elevation of Privilege Vulnerability Important 8.1 No No EoP
CVE-2022-35775 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-35780 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-35781 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-35782 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-35784 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-35785 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-35786 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-35788 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-35789 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-35790 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-35791 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-35799 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-35801 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-35807 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-35808 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-35809 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-35810 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-35811 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-35813 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-35814 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-35815 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-35816 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-35817 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-35818 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-35819 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-35774 Azure Site Recovery Elevation of Privilege Vulnerability Important 4.9 No No EoP
CVE-2022-35787 Azure Site Recovery Elevation of Privilege Vulnerability Important 4.9 No No EoP
CVE-2022-35800 Azure Site Recovery Elevation of Privilege Vulnerability Important 4.9 No No EoP
CVE-2022-35783 Azure Site Recovery Elevation of Privilege Vulnerability Important 4.4 No No EoP
CVE-2022-35812 Azure Site Recovery Elevation of Privilege Vulnerability Important 4.4 No No EoP
CVE-2022-35824 Azure Site Recovery Remote Code Execution Vulnerability Important Unknown No No RCE
CVE-2022-35772 Azure Site Recovery Remote Code Execution Vulnerability Important 7.2 No No RCE
CVE-2022-35821 Azure Sphere Information Disclosure Vulnerability Important 4.4 No No Info
CVE-2022-34301 * CERT/CC: CVE-2022-34301 Eurosoft Boot Loader Bypass Important N/A No No SFB
CVE-2022-34302 * CERT/CC: CVE-2022-34302 New Horizon Data Systems Inc Boot Loader Bypass Important N/A No No SFB
CVE-2022-34303 * CERT/CC: CVE-20220-34303 Crypto Pro Boot Loader Bypass Important N/A No No SFB
CVE-2022-35748 HTTP.sys Denial of Service Vulnerability Important 7.5 No No DoS
CVE-2022-35760 Microsoft ATA Port Driver Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-33649 Microsoft Edge (Chromium-based) Security Feature Bypass Vulnerability Important 9.6 No No SFB
CVE-2022-33648 Microsoft Excel Remote Code Execution Vulnerability Important 7.8 No No RCE
CVE-2022-33631 Microsoft Excel Security Feature Bypass Vulnerability Important 7.3 No No SFB
CVE-2022-34692 Microsoft Exchange Information Disclosure Vulnerability Important 5.3 No No Info
CVE-2022-21979 Microsoft Exchange Information Disclosure Vulnerability Important 4.8 No No Info
CVE-2022-34717 Microsoft Office Remote Code Execution Vulnerability Important 8.8 No No RCE
CVE-2022-35742 Microsoft Outlook Denial of Service Vulnerability Important 7.5 No No DoS
CVE-2022-35743 Microsoft Windows Support Diagnostic Tool (MSDT) Remote Code Execution Vulnerability Important 7.8 No No RCE
CVE-2022-35762 Storage Spaces Direct Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-35763 Storage Spaces Direct Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-35764 Storage Spaces Direct Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-35765 Storage Spaces Direct Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-35792 Storage Spaces Direct Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-33640 System Center Operations Manager: Open Management Infrastructure (OMI) Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-35754 Unified Write Filter Elevation of Privilege Vulnerability Important 6.7 No No EoP
CVE-2022-35777 Visual Studio Remote Code Execution Vulnerability Important 8.8 No No RCE
CVE-2022-35825 Visual Studio Remote Code Execution Vulnerability Important 8.8 No No RCE
CVE-2022-35826 Visual Studio Remote Code Execution Vulnerability Important 8.8 No No RCE
CVE-2022-35827 Visual Studio Remote Code Execution Vulnerability Important 8.8 No No RCE
CVE-2022-35750 Win32k Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-35820 Windows Bluetooth Driver Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-30144 Windows Bluetooth Service Remote Code Execution Vulnerability Important 7.5 No No RCE
CVE-2022-35757 Windows Cloud Files Mini Filter Driver Elevation of Privilege Vulnerability Important 7.3 No No EoP
CVE-2022-34705 Windows Defender Credential Guard Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-35771 Windows Defender Credential Guard Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-34704 Windows Defender Credential Guard Information Disclosure Vulnerability Important 5.5 No No Info
CVE-2022-34710 Windows Defender Credential Guard Information Disclosure Vulnerability Important 5.5 No No Info
CVE-2022-34712 Windows Defender Credential Guard Information Disclosure Vulnerability Important 5.5 No No Info
CVE-2022-34709 Windows Defender Credential Guard Security Feature Bypass Vulnerability Important 6 No No SFB
CVE-2022-35746 Windows Digital Media Receiver Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-35749 Windows Digital Media Receiver Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-35795 Windows Error Reporting Service Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-34690 Windows Fax Service Elevation of Privilege Vulnerability Important 7.1 No No EoP
CVE-2022-35797 Windows Hello Security Feature Bypass Vulnerability Important 6.1 No No SFB
CVE-2022-35751 Windows Hyper-V Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-35756 Windows Kerberos Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-35761 Windows Kernel Elevation of Privilege Vulnerability Important 8.4 No No EoP
CVE-2022-34707 Windows Kernel Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-35768 Windows Kernel Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-34708 Windows Kernel Information Disclosure Vulnerability Important 5.5 No No Info
CVE-2022-35758 Windows Kernel Memory Information Disclosure Vulnerability Important 5.5 No No Info
CVE-2022-30197 Windows Kernel Security Feature Bypass Important 7.8 No No SFB
CVE-2022-35759 Windows Local Security Authority (LSA) Denial of Service Vulnerability Important 6.5 No No DoS
CVE-2022-34706 Windows Local Security Authority (LSA) Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-34715 Windows Network File System Remote Code Execution Vulnerability Important 9.8 No No RCE
CVE-2022-33670 Windows Partition Management Driver Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-34703 Windows Partition Management Driver Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-35769 Windows Point-to-Point Protocol (PPP) Denial of Service Vulnerability Important 7.5 No No DoS
CVE-2022-35747 Windows Point-to-Point Protocol (PPP) Denial of Service Vulnerability Important 5.9 No No DoS
CVE-2022-35755 Windows Print Spooler Elevation of Privilege Vulnerability Important 7.3 No No EoP
CVE-2022-35793 Windows Print Spooler Elevation of Privilege Vulnerability Important 7.3 No No EoP
CVE-2022-34701 Windows Secure Socket Tunneling Protocol (SSTP) Denial of Service Vulnerability Important 5.3 No No DoS
CVE-2022-30194 Windows WebBrowser Control Remote Code Execution Vulnerability Important 7.5 No No RCE
CVE-2022-34699 Windows Win32k Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-33636 Microsoft Edge (Chromium-based) Remote Code Execution Vulnerability Moderate 8.3 No No RCE
CVE-2022-35796 Microsoft Edge (Chromium-based) Elevation of Privilege Vulnerability Low 7.5 No No EoP
CVE-2022-2603 * Chromium: CVE-2022-2603 Use after free in Omnibox High N/A No No RCE
CVE-2022-2604 * Chromium: CVE-2022-2604 Use after free in Safe Browsing High N/A No No RCE
CVE-2022-2605 * Chromium: CVE-2022-2605 Out of bounds read in Dawn High N/A No No RCE
CVE-2022-2606 * Chromium: CVE-2022-2606 Use after free in Managed devices API High N/A No No RCE
CVE-2022-2610 * Chromium: CVE-2022-2610 Insufficient policy enforcement in Background Fetch Medium N/A No No SFB
CVE-2022-2611 * Chromium: CVE-2022-2611 Inappropriate implementation in Fullscreen API Medium N/A No No N/A
CVE-2022-2612 * Chromium: CVE-2022-2612 Side-channel information leakage in Keyboard input Medium N/A No No Info
CVE-2022-2614 * Chromium: CVE-2022-2614 Use after free in Sign-In Flow Medium N/A No No RCE
CVE-2022-2615 * Chromium: CVE-2022-2615 Insufficient policy enforcement in Cookies Medium N/A No No SFB
CVE-2022-2616 * Chromium: CVE-2022-2616 Inappropriate implementation in Extensions API Medium N/A No No N/A
CVE-2022-2617 * Chromium: CVE-2022-2617 Use after free in Extensions API Medium N/A No No RCE
CVE-2022-2618 * Chromium: CVE-2022-2618 Insufficient validation of untrusted input in Internals Medium N/A No No Spoofing
CVE-2022-2619 * Chromium: CVE-2022-2619 Insufficient validation of untrusted input in Settings Medium N/A No No Spoofing
CVE-2022-2621 * Chromium: CVE-2022-2621 Use after free in Extensions Medium N/A No No RCE
CVE-2022-2622 * Chromium: CVE-2022-2622 Insufficient validation of untrusted input in Safe Browsing Medium N/A No No Spoofing
CVE-2022-2623 * Chromium: CVE-2022-2623 Use after free in Offline Medium N/A No No RCE
CVE-2022-2624 * Chromium: CVE-2022-2624 Heap buffer overflow in PDF Medium N/A No No RCE

* Indicates this CVE had previously been assigned by a 3rd-party and is now being incorporated into Microsoft products.

Looking at the remaining Critical-rated fixes, many impact older tunneling protocols. There are fixes for Point-to-Point Protocol (PPP), Secure Socket Tunneling Protocol (SSTP), and RAS Point-to-Point Tunneling Protocol – all of which are correcting remote code execution (RCE) bugs. These are older protocols that should be blocked at your perimeter. However, if you’re still using one of these, it’s probably because you need it, so don’t miss these patches. There’s also a Critical-rated Hyper-V guest-to-host bug being patched this month. The update for Azure Batch won’t be automatic. According to Microsoft, “If you are not running Batch Agent version 1.9.27 or later, you need to resize your pools to zero or recreate your pool.” The final Critical-rated patch this month fixes an EoP in Active Directory. An authenticated attacker could manipulate attributes on computer accounts they own or manage and acquire a certificate from AD CS that would allow elevation to SYSTEM. This bug appears similar to other certificate-based vulnerabilities as Microsoft recommends reviewing KB5014754 for additional steps admins can take to protect their systems.

Moving on to other components, August brings 34 updates just for the Azure Site Recovery component. That makes 66 updates for this component in July and August. This month, there are two RCE bugs, one DoS, and 31 EoP vulnerabilities being fixed. All these bugs involve the VMWare-to-Azure scenario. If you use Azure Site Recovery, you will need to update to 9.50 to be protected. Speaking of Azure, there are eight fixes for RTOS GUIX Studio – six RCEs and two info disclosure bugs. It’s not clear if applications built using RTOS will need to recompile their applications after the patches are applied or not, but it wouldn’t be a bad idea. Rounding out the Azure-related bugs is an info disclosure vulnerability in Azure Sphere that could disclose contents of memory, but root privileges are required to exploit this bug, so it won’t be on anyone’s top 10 list.

There are nine other code execution bugs fixed this month, including another bug in MSDT that is not under active attack (yet). There’s also an intriguing RCE bug in the Bluetooth Service, but Microsoft provides little information on how it would be exploited – just that is limited to network adjacent attackers. There are two Office RCEs and four more in Visual Studio. In these cases, the attacker would need to convince a user to open a specially crafted file. The final RCE bugs are both browser-related. The first is in the WebBrowser Control and the other is in Edge (Chromium-based). While the Edge bug is rated Moderate, the CVSS is listed as 8.3. The lowered severity rating is due to required user interaction, but studies have shown that users click on just about any pop-ups they see.

Looking at the six security feature bypass bugs patched this month, highlighted by a CVSS 9.6 bug in Edge that bypasses a dialog feature that asks users to allow the launching of the Microsoft Store application. There’s a vulnerability in Windows Defender Credential Guard that could bypass Kerberos protection. The SFB bug in Excel bypasses the Packager Object Filters feature. The patch for Windows Hello fixes a vulnerability that bypasses the facial recognition security feature. Finally, the bug in the Windows kernel bypasses ASLR – a vital defense-in-depth measure. It would not surprise me to find this bug incorporated into future exploits, as bypassing ASLR would likely make the exploit more reliable.

Moving on to the remaining EoP bugs fixed in August, the first that jump out are the patches for the Print Spooler. Microsoft lists these as an XI of 1, which means they expect exploitation within 30 days. One of the patches fixes a privilege escalation in System Center Operations Manager: Open Management Infrastructure (OMI). An attacker could abuse it to manipulate the OMI keytab and gain elevated privileges on the machine. For the most part, the remaining privilege escalation bugs require an attacker to already have the ability to execute code on the target. They can then use one of these bugs to escalate to SYSTEM or some other elevated level.

Most months, the information disclosure patches consist primarily of bugs that only result in leaks consisting of unspecified memory contents. There are a couple of those this month, but the others are much more interesting. There are two bugs in the Windows Defender Credential Guard. Both could allow an attacker to access Kerberos-protected data. The remaining info disclosure fixes are for Exchange and could allow an attacker to read target emails. Again, based on changes made to Exchange this month, admins need to enable Extended Protection to fully remediate these vulnerabilities.

Seven different Denial-of-Service (DoS) vulnerabilities receive fixes this month, including the aforementioned Outlook and Azure Site Recovery bugs. Three others impact the older tunneling protocols mentioned above. The LSA component gets a fix for a DoS bug. This is interesting, as LSA is responsible for writing to security logs. It is feasible that attackers could use this bug to try to cover their tracks after an intrusion. There’s also a fix for the HTTP Protocol Stack (http.sys). In this case, an unauthenticated attacker could send specially crafted packets to shut down the service.

The August release is rounded out by a fix for .NET to prevent a blind XXE attack.

No new advisories were released this month. The latest servicing stack updates can be found in the revised ADV990001. The latest updates will be required to install the fixes for the secure boot bugs submitted by CERT/CC.

Looking Ahead

The next Patch Tuesday falls on September 13, and we’ll return with details and patch analysis then. I’ll also be starting a webcast on patch Wednesday to quickly recap the month’s release. You can find it on our YouTube channel. Until then, stay safe, happy patching, and may all your reboots be smooth and clean!

The August 2022 Security Update Review

Looking at Patch Gap Vulnerabilities in the VMware ESXi TCP/IP Stack

27 July 2022 at 15:14

Over the last few years, multiple VMware ESXi remote, unauthenticated code execution vulnerabilities have been publicly disclosed. Some were also found to be exploited in the wild. Since these bugs were found in ESXi’s implementation of the SLP service, VMware provided workarounds to turn off the service. VMware also disabled the service by default starting with ESX 7.0 Update 2c. In this blog post, we explore another remotely reachable attack surface: ESXi’s TCP/IP stack implemented as a VMkernel module. The most interesting outcome of this analysis is that ESXi’s TCP/IP stack is based on FreeBSD 8.2 and does not include security patches for the vulnerabilities disclosed over the years since that release of FreeBSD.

This result also prompted us to analyze the nature of vulnerabilities disclosed in other open-source components used by VMware, such as OpenSLP and ISC-DHCP. Once again, we observed that most of the disclosed vulnerabilities had upstream patches before the disclosure.

The FreeBSD Code in the ESXi TCP/IP Stack

An initial analysis was done to locate the VMkernel module implementing the TCP/IP stack. In ESXi, the module details can be enumerated using esxcfg-info or esxcli system module commands as seen below:

Checking the function names and strings available in the module, it is understood that the code is coming from FreeBSD, as shown in the following:

While the exact version of FreeBSD was not initially known, comparing the binary against the patches mentioned in advisories revealed multiple missing fixes. I performed a manual diff of FreeBSD branches 8.x, 9.x, and 10.x against the VMkernel module to narrow down the version of code used. Consider a couple of MFC (Merge From CURRENT) commits for example: 213158 and 215207. The 213158 commit was merged to FreeBSD 8.2 and later, whereas 215207 was merged to FreeBSD 8.3 and later. While 213158 was found in the VMkernel module, the 215207 commit was missing. This gave an approximate timeline of when the code was forked, which is around FreeBSD 8.2.

Porting Type Information from FreeBSD to the ESXi VMkernel Module

Once the version of the FreeBSD source is known, we can port type information from FreeBSD 8.2 to the VMkernel module. The goal here was to make function prototype and structure information available in IDA. Since creating type libraries for multiple dependent headers can be complex, I decided to rely on the FreeBSD kernel binary compiled from source with DWARF information. My first choice was to use IDA Pro’s Dump typeinfo to IDC feature. However, there were still missing structures because only assembler-level types were exported to the IDC.

The workaround for the problem is to use the TILIB idea by @rolfrolles. Using the above-mentioned technique, it is possible to create a type library from the FreeBSD 8.2 kernel binary and then load it into the VMkernel module’s IDB. This imports all the C-level types required for further analysis with the decompiler. While the Structure and Local Types view does not list all imported type information, we can apply the function prototypes as detailed in a previous blog post.

As a recap, begin by extracting the function prototype from the FreeBSD kernel as a key value pair of function_name:function_type, then iterate through the extracted type information and apply it to the VMkernel module having symbols.

Once the prototypes are applied, the Structure and Local Types views are automatically populated. Any other types required for local variables can be further added manually using the workflow mentioned in Importing types into IDB.

Figure 1 - VMkernel module before (left) and after (right) adding FreeBSD type information

Analyzing VMkernel Debug Information from VMware Workbench

VMware Workbench is an Eclipse IDE plugin provided by VMware. Amongst many other features, it also provides debug symbols for VMkernel. Jan Harrie and Matthias Luft have documented the usage of the VMkernel debug information in their research entitled Attacking VMware NSX [Slides 34 – 37 in the PDF]. The UI of the Eclipse plugin is shown below:

Figure 2 - List of VMkernel debug symbols available in VMware Workbench

Kernel modules in ESXi communicate with VMkernel using VMK APIs. By using a VMkernel build that has debug information, it becomes easier to understand the VMK API calls made by any VMkernel module, which includes the TCP/IP stack. Moreover, the type information from VMkernel can be ported to any desired VMkernel module or even to the Virtual Machine Monitor. Here is an example of type information ported to the TCP/IP module found in ESXi 6.7 Update 3 using debug information from VMkernel version 14320388:

Figure 3 - TCP/IP module before (left) and after (right) adding VMkernel type information

As soon as the function prototypes are applied to the binary, IDA helpfully propagates the type information to many of the variables found in the code. When working with code forked from FreeBSD, it is useful to place the Hex-Rays decompilation side-by-side with known FreeBSD source code to rename variables and add type information to variables that IDA did not detect automatically . However, in this case, we do not have access to local variable names or types. While some variables are given meaningful names by IDA, the rest were manually added using context information from the detected enums, structure names, and so forth.

VMware seems to have stopped publishing VMkernel debug information for more than a year now. The last public release for which I could find the debug information goes back to ESXi 6.7 16773714.

Missing FreeBSD Patches

At this point, we had enough information to perform a diff of the TCP/IP VMkernel module against the FreeBSD security advisories. Patches provided in the advisories were compared against ESXi’s version of the module to identify the missing bug fixes. Based on static analysis, patches for 16 vulnerabilities fixed in FreeBSD were found to be missing in ESXi. We reported these missing patches to VMware for further evaluation.  Shown below is the set of missing patches that we reported to VMware and their corresponding applicability to ESXi as evaluated by VMware:

CVE Disclosure Date Bug Applicable
CVE-2013-3077 8/22/13 Integer overflow in IP_MSFILTER Yes
CVE-2013-5691 9/10/13 Insufficient credential checks in network IOCTL No
CVE-2004-0230 9/16/14 Denial of Service in TCP packet processing Yes
CVE-2015-1414 2/25/15 Integer overflow in IGMP protocol Yes
CVE-2015-2923 4/7/15 Denial of Service with IPv6 Router Advertisements Yes
CVE-2015-5358 7/21/15 Resource exhaustion due to sessions stuck in LAST_ACK state Yes
CVE-2015-1417 7/28/15 Resource exhaustion in TCP reassembly No
CVE-2018-6916 3/7/18 IPSec validation and use-after-free Yes
CVE-2018-6918 4/4/18 IPSec crash or denial of service Yes
CVE-2018-6922 8/6/18 Resource exhaustion in TCP reassembly No
CVE-2018-6923 8/14/18 Resource exhaustion in IP fragment reassembly No
CVE-2019-5608 8/6/19 ICMPv6 / MLDv2 out-of-bounds memory access Yes
CVE-2019-5611 8/20/19 IPv6 remote Denial-of-Service Yes
CVE-2020-7451 3/19/20 TCP IPv6 SYN cache kernel information disclosure Yes
CVE-2020-7457 7/8/20 IPv6 socket option race condition and use after free Yes
CVE-2020-7469 12/1/20 ICMPv6 use-after-free in error message handling Yes

These issues were addressed in ESXi 7.0 Update 3f as well as ESXi 6.5 and ESXi 6.7.

Analysis of OpenSLP in ESXi  

The next component considered for analysis is the SLPD service in ESXi. ESXi’s SLP service is a fork of OpenSLP version 1.0.0. The version information and build configuration details can be fetched as below:

Just like the VMkernel modules, the SLPD service executable has symbols but not type information. Using the available function names, we observed that VMware’s forked code is not entirely based on version 1.0.0. It also has some of the functions added later, including some from version 2.0.0. There are also differences in some of the structure definitions as well as function prototypes. These observations can be made as soon as you port type information from OpenSLP and certain functions won’t decompile cleanly.

To fetch the type information, build OpenSLP from source and then use IDA Pro’s Create C header + Parse C header feature to populate the local types. The C header parses without much error. This is a quick workaround compared to creating type libraries from multiple dependent headers. Note that ESXi versions 7.0 and above run the SLPD service as a 64-bit executable. Because of this, care must be taken while using the created C header interchangeably between ESXi 7.0 and other versions. This is especially true as the header may require some modifications on data sizes, such as size_t being unsigned int vs unsigned long long.

Timeline of Upstream Patches vs Disclosures:

In the case of OpenSLP, there is enough public information regarding the vulnerabilities affecting ESXi and their relevant upstream patches, most notable being the one published by Lucas Leong on CVE-2020-3992 and CVE-2021-21974. For the scope of this blog, we will consider the following set of remote code execution vulnerabilities:

CVE VMSA Bug
CVE-2015-5177 VMSA-2015-0007 Double Free
CVE-2019-5544 VMSA-2019-0022 Heap Overflow
CVE-2020-3992 VMSA-2020-0023 Use-After-Free
CVE-2021-21974 VMSA-2021-0002 Heap Overflow

CVE-2015-5177 is a double-free vulnerability that occurs when processing a message buffer across functions: SLPDProcessMessage, ProcessDAAdvert, and SLPDKnownDAAdd. An upstream patch to fix the issue in SLPDKnownDAAdd() was already available.

Similarly, CVE-2020-3992 is a use-after-free vulnerability, again found in the handling of message buffer across functions SLPDProcessMessage, ProcessDAAdvert, and SLPDKnownDAAdd. However, this vulnerability does not affect the upstream version of OpenSLP. This bug can be traced back to CVE-2015-5177 based on the information provided in VMSA.

VMware released updates in the form of the VIB (vSphere Installation Bundle). Installing the VIBs one by one on ESXi to perform patch diffing of SLPD binary can be a tedious process. Instead, binaries can be directly extracted from the VIB to speed up the process. The relevant VIBs can be downloaded from the ESXi Patch Tracker, which lists them based on the timeline of release. Consider a diff between ESXi 6.7 build 8169922 and 8941472:

Figure 4 - ESXi Patch Tracker with VIBs

To replicate this, download the esx-base VIB to extract the slpd binary using the vmtar utility. The vmtar utility can be copied from ESXi and executed in Ubuntu since it does not have any ESXi-specific dependencies:

Similarly, in the case of the ESXi 6.7 GA ISO image, extract the S.V00 file from VMware-VMvisor-Installer-6.7.0-8169922.x86_64.iso:

A patch diff between slpd binaries confirms that CVE-2020-3992 was introduced when patching CVE-2015-5177 in ESXi versions 6.0 and above. The fix for CVE-2015-5177, in this case, was different from that of the working upstream fix in SLPDKnownDAAdd():

Figure 5 - Bindiff between ESXi 6.7.0 8169922 and 8941472

CVE-2020-3992 was in fact fixed twice (VMSA-2020-0023.1) since the initial patch did not completely address the issue. Additionally, this bug was also reported to be exploited in the wild by the Cybersecurity and Infrastructure Security Agency (CISA).

CVE-2021-21974, a heap overflow in SLPParseSrvUrl() leading to RCE, also had an upstream patch. This fix was part of a large code change in OpenSLP.

CVE-2019-5544 was the only bug that affected both the upstream and the VMware fork of OpenSLP at the time of disclosure. Though the bug has already been disclosed and fixed by many distros, the patch for this bug is still missing in the OpenSLP GitHub repository. This was another bug exploited in the wild.

Putting it all together, here is the timeline of disclosure vs availability of patches:

CVE Disclosure Date Patch Availability Patches
CVE-2015-5177 10/1/15 6/8/11 53bbd77
CVE-2019-5544 12/5/19 N/A N/A
CVE-2020-3992 10/20/20 6/8/11 53bbd77
CVE-2021-21974 2/23/21 3/1/06 3c8e45d

Analysis of ISC-DHCP in Workstation

The next component considered for analysis is the DHCP service of VMware Workstation, which is based on ISC-DHCP version 2.0. You can refer to the blog post Wandering through the Shady Corners of VMware Workstation/Fusion for an earlier analysis of this attack surface. It is noted that, though the codebase is a couple of decades old, VMware has backported fixes for known vulnerabilities. Keeping this in mind, only the recently disclosed bugs, CVE-2019-5540 and CVE-2020-3947, were analyzed.

Unlike earlier analysis where the executables had symbols, the vmnet-dhcp is completely stripped. The first task is to identify as many function names as possible to carry out the analysis. Looking for binaries with symbols led us to the very first release – VMware 1.0 Build 160. The vmnet-dhcpd binary from the first release of VMware had symbols and type information in stabs format.

For matching the available symbols with recent releases of the Workstation DHCP server, I relied on the updated version of Rizzo published by Quarkslab. Since Rizzo can be very slow on large binaries, only the string reference signatures were used in detection. With this, Rizzo identified around 69 functions using 226 matching strings available in VMware 1.0 Build 160 vmnet-dhcpd binary. A somewhat similar result can be achieved using the strings in ISC-DHCP 2.0. For anyone interested, the historical releases of ISC-DHCP can be found here.

During the patch diffing process, bug fixes in vmnet-dhcpd are easy to spot since the binary undergoes very limited changes per release. The first bug, CVE-2019-5540, is an information disclosure vulnerability due to an uninitialized field in the ICMP packet structure. This issue can be narrowed down to an upstream patch in the function icmp_echorequest().

The next bug, CVE-2020-3947, is a use-after-free vulnerability when handling the DHCPRELEASE packet. During the handling of a DHCPDISCOVER packet from a client, ISC-DHCP allocates memory in the heap. If the client identifier is long, it stores the resultant pointer as part of the lease structure. Otherwise, uid_buf is used for storage. The relevant code can be found in the ack_lease function of the server/dhcp.c source file:

Later when a DHCPRELEASE packet is received, the lease structure is adjusted. First, a copy of lease is made in the function release_lease and then supersede_lease is called. This code can be found in common/memory.c:

Note that the uid pointer is now found in both the old and the newly copied lease structures when it is passed to supersede_lease. In supersede_lease, the comp->uid pointer is freed (provided that it points to memory other than uid_buf, that is, in the case of a long client identifier):

Later, lease->uid entry is reused. See the code below assigning comp -> uid = lease -> uid, which by this time points to freed memory:

Finally, the comp structure that has a pointer to the freed uid buffer is passed to write_lease where the use-after-free happens. The bug can be triggered by adding a long dhcp-client-identifier entry to the DHCP client configuration and then initiating a DHCP request followed by a DHCP release using dhclient:

This issue was fixed in the release_lease function as part of a bigger code change by introducing a lease_copy function. The copied lease structure no longer holds a reference to the uid buffer of the old lease. Instead, a new allocation is requested and assigned. The release_lease function received further changes during later updates for handling the failover protocol. VMware’s fix for this bug is different from that of the upstream, possibly due to the divergence of the codebase.

Here is the timeline of disclosure vs availability of patches:

CVE Disclosure Date Patch Availability Patches
CVE-2019-5540 11/12/19 6/25/98 34436cc
CVE-2020-3947 3/12/20 5/17/00 20916ca

The IDA Python scripts used for the analysis can be found here.

Conclusion

Over the last few months, we analyzed three different VMware components: the ESXi networking stack, the ESXi SLPD service, and the Workstation DHCP server. The three components share the fact that they are forks of open-source code. Unlike open-source packages that can be updated to a new version with relative ease, updating a fork takes significantly more effort. This is because various challenges arise when cherry-picking patch commits.

In the ESXi FreeBSD networking stack, even the vulnerabilities with known CVE identifiers remained unfixed – the forked code was never tracked for vulnerabilities. Better tracking of FreeBSD disclosures is a good place to start and can help resolve some of the issues. Also, considering the criticality of the component, it might be possible for VMware to work with FreeBSD Security Officers to get prior information on vulnerabilities as per their Information handling policies:

The FreeBSD Security Officer has close working relationships with a number of other organizations, including third-party vendors that share code with FreeBSD…..Frequently vulnerabilities may extend beyond the scope of the FreeBSD implementation, and (perhaps less frequently) may have broad implications for the global networking community. Under such circumstances, the Security Officer may wish to disclose vulnerability information to these other organizations.”

In most cases, vendor advisories only list the supported versions of the affected software. Even if a legacy version is not listed in the advisory, the patch might still be applicable for the forked code.

In the case of OpenSLP and ISC-DHCP forks, the patch gap vulnerabilities come from bugs that do not have CVE identifiers. Some of the bug fixes have clear commit messages about the issue, whereas other fixes are done as part of large code changes or refactoring. Either way, it is a challenging process and requires a trained set of eyes to pick up security patches when the vulnerabilities are not explicitly called out. This also shows the significance of requesting CVE identifiers for security fixes since companies largely rely on them for cherry-picking patches.

As we showed, a couple of ESXi SLP patches had further issues despite the availability of working upstream fixes. To avoid this, it is important to evaluate a bug report not just against the fork but also against the upstream project. If a fix is found, developers should evaluate the upstream fix. Upstream fixes in most cases are a safe bet compared to that of custom patches, which may be written without having a comprehensive understanding of the code. However, this process of adopting patches can be further complicated if the codebases have diverged considerably.

The most important concern with forked code is the lifetime of bugs. When open-source code is used and updated as a package to the latest version, all the bug fixes are applied (i.e., vulnerabilities with or without CVE identifiers). In a forked codebase, when a patch is missed during cherry-picking, it will remain unfixed until the code is updated as a whole or someone finds and reports the issue. For example, the ISC-DHCP bugs were fixed in VMware’s DHCP server a couple of decades after the upstream fixes were available. In fact, the ISC-DHCP uninitialized memory information disclosure was fixed upstream even before the launch of CVE. Overall, forked code requires more attention compared to that of packages.

Considering the challenges of adopting security fixes and gaps in the tracking process, exploitable bugs might be still lying around without a fix. There are different types of patch gaps as well, so expect to hear more about these in the future. Until then, you can find me on Twitter @RenoRobertr, and follow the team for the latest in exploit techniques and security patches.

Looking at Patch Gap Vulnerabilities in the VMware ESXi TCP/IP Stack

Riding the InfoRail to Exploit Ivanti Avalanche

19 July 2022 at 13:59

Back in 2021, I stumbled upon a proof of concept describing an arbitrary file read vulnerability in the Ivanti Avalanche mobile device management tool. As I was not aware of this product, I decided to take a quick look at the vendor’s website to learn more:

“Avalanche Enterprise Mobile Device Management manages some of the most demanding, high-profile supply chain mobility solutions in the world. So, we understand the pressure you're under to maximize worker (and device) uptime.”

“Manage all mobile devices in one place. Smartphones, barcode scanners, wearables and more—configure, deploy, update, and maintain them all in one system.”

“30,000 organizations. Over 10 million devices.”

As the product specification seemed to be both intriguing and encouraging, I decided to give it a shot and look for some vulnerabilities.

I was able to quickly identify a chain of three vulnerabilities in the Ivanti Avalanche Web Application:

- ZDI-21-1298 (CVE-2021-42124): Session takeover vulnerability, which requires user interaction.
- ZDI-21-1300 (CVE-2021-42126): privilege escalation vulnerability, which allows an attacker to gain administrative privileges.
- ZDI-21-1299 (CVE-2021-42125) – Remote code execution vulnerability, which can be exploited from the level of an administrator account.

Even though this chain is powerful, its first part heavily depends on factors that are not within the attacker’s control. We can do better, right?

The Inspiration

Later, I identified several interesting facts concerning Ivanti Avalanche:

- It contains multiple XStream 1.4.12 jar packages in its directories.
- It implements multiple ObjectGraph classes, which wrap the XStream serializer.
- Some of those classes define an allowlist of classes permitted for deserialization, while others lack such an allowlist.

This led me to suspect that there are multiple untrusted deserialization issues in the product. However, I was not yet able to determine how to reach those deserialization routines. Fortunately, I decided to pursue the matter further, and it turned out to be a long, exciting journey. It allowed me to not only exploit the XStream deserialization issues but to significantly increase the attack surface and find many more 0-days.

This blog post describes the first part of my Ivanti Avalanche research, where I identified the Ivanti Avalanche custom network protocol and abused it to perform several remote code executions. Moreover, it describes a cool race condition vulnerability that leads to an authentication bypass.

Identifying Ivanti Avalanche Services

To begin, let’s have a look at the Avalanche services:

Figure 1 - Ivanti Avalanche Services

We find we are dealing with the Tomcat Web Application plus other services. “Wavelink Information Router” seems to be the most interesting of them, due to the following description: “Coordinates communication between Wavelink processes…”.

At this stage, it all seemed complicated. Because of this, I used the following methods to gain some more insight:
• Network traffic analysis
• Static analysis
• Log file analysis

After a while, I was able to see a bigger picture. It seemed that the Avalanche Web Application is not able to perform tasks by itself, not even a login operation. However, it can freely use different services to perform tasks. The Information Router, also known as the InfoRail service, stands in between, and is responsible for the distribution of messages between the services. The InfoRail service listens on TCP port 0.0.0.0:7225 by default.

Figure 2 - Inter-Services communication

As can be seen in the above diagram, the communication flow is straightforward. The Web Backend creates a message and sends it to the InfoRail service, which forwards it to the appropriate destination service. The destination service handles the message and returns the response to the Web Backend, once more via the InfoRail service. In the default installation, all these services are running on the same host. However, it is possible to place some of these services on remote machines.

On the other hand, it is not easy to get more detailed information about the messages. Network traffic analysis was not of much use, as the messages seem to be obfuscated or encrypted. In order to learn something more about them, I had to conduct a detailed code analysis.

The following section presents an overview of the InfoRail protocol and all the basics needed to:
• Recreate the protocol and messages
• Understand its basics
• Understand the payload delivery mechanism

InfoRail Protocol Basics

A typical InfoRail message consists of three main parts:
• Preamble
• Header
• Optional XML payload

The following picture presents a message structure:

Figure 3 - Message Structure

The InfoRail Preamble

The preamble always has a length of 24 bytes. It consists of the following parts:
• Bytes 1-4: Length of the whole message
• Bytes 5-8: Length of the header
• Bytes 9-12: Length of the payload
• Bytes 13-16: Length of the uncompressed payload (payload can be optionally compressed)
• Bytes 17-20: Message ID (typically an incremented number, starting from 1)
• Byte 21: Protocol version (typically 0x10)
• Bytes 22-23: Reserved • Byte 24: Encryption flag (payload and header can be optionally encrypted) – 0 or 1

The InfoRail Header

The header of the typical message consists of multiple keys together with their corresponding values. Those keys and values are included in the header in the following way:
• 3 null bytes
• 0x02 byte
• 3 null bytes
• 1 byte which provides the length of a key (e.g. 0x08)
• 3 null bytes
• 1 byte which provides the length of a value (e.g. 0x06)
• Key + value

Here’s an example key and value:

         \x00\x00\x00\x02\x00\x00\x00\x08\x00\x00\x00\x06h.msgcat999999

As was mentioned before, a header can contain multiple keys. The most important ones that appear in most or all messages are:
h.msgcat - in typical requests, it is equal to 10 (request)
h.msgsubcat - information about the request type, thus it is crucial for the payload processing
h.msgtag - usually stores the JSESSIONID cookie, although no method that verifies this cookie was spotted, thus this value can be random.
h.distlist - specifies one or more services to which the message will be forwarded by InfoRail

The header must be padded with null bytes to a multiple of 16 bytes, due to the optional encryption that can be applied.

The Payload

As was mentioned before, the majority of messages contain an XML payload. An XStream serializer is used for the payload serialization and deserialization operations.

Different serialized objects can be transferred depending on the target service and the message subcategory. However, in most cases we are dealing with the RequestPayload object . The following snippet presents an example of the XML that is sent during an authentication operation. In this case, Avalanche Web Backend sends this XML to the Enterprise Server service, which then verifies user credentials.

RequestPayload.xml

As you can see, this message contains a serialized UserCredentials object, which consists of the loginName, encrypted password, domain, and clientIpAddress. You can also see that the RequestPayload contains the web cookie (sessionId). However, this cookie is never verified, so it can be set to any MD5 hash. As the payload can be optionally encrypted (and compressed), it must be padded to a multiple of 16 bytes.

Typically, every service implements its own ObjectGraph class, which defines the instance of the XStream serializer and configures it. Here’s a fragment of an example implementation:

ObjectGraphPart.java

When the service receives the XML payload, it deserializes it with the ObjectGraph.fromXML method.

Encryption

As was mentioned before, the header and the payload of the message can be encrypted. Furthermore, the payload can be compressed. InfoRail does not use the SSL/TLS protocol for encryption. Instead, it manually applies an encryption algorithm using a hardcoded encryption key.

As both the encryption algorithm and the encryption key can be extracted from the source code, the potential attacker can perform both the decryption and encryption operations without any obstacles.

Distribution to Services

The InfoRail service needs to know where to forward the received message. This information is stored in the h.distlist key of the message header. Values that can be used are stored in the IrConstants class. Variables that start with IR_TOPIC define the services where the message can be forwarded. The following code snippet presents several hardcoded variables:

DistributionVariables.java

If the sender wants the message to be forwarded to the license server, the h.distlist value must be set to 255.3.2.8.

Message Processing and Subcategories

This is probably the most important part of the protocol description. As was mentioned before, the message category is included in the message header under the h.msgsubcat key. As seen in the last line of the code snippet below, services protect themselves against the handling of an unknown message and, if the provided message subcategory is not implemented, the message is dropped.

Message processing may be implemented in slightly different ways depending on the service. Here, we are going to take a brief look at the Avalanche Notification Server. The following snippet represents the processMessage method found in the MessageDispatcher class:

processMessage.java

At [1], the message subcategory is retrieved from the header. Then, it is passed to the MessageProcessorVector.getProcessor method to obtain a reference to the appropriate message handler

At [2], the switch-case statement begins.

If the category is equal to 10 (request), the processInfoRailRequest method is invoked at [3]. Its arguments contain the handler that was retrieved at step [1]. We can have a quick look at this method here:

processInfoRailRequest.java

Basically, if the handler is not null, the code will invoke the handler.ProcessMessage method.

Finally, we must investigate how handlers are retrieved. The most important part is as follows:

MessageProcessorVector.java

At [1], a HashMap<Integer, IMessageProcessor> is defined.

At [2] and subsequent lines, the code invokes the setProcessor method. It accepts the message subcategory integer and the corresponding object that implements IMessageProcessor, such as AnsCredentialsHandler.

At [3], the setProcessor method is defined. It inserts the subcategory and appropriate object into the HashMap defined at [1].

At [4], getProcessor retrieves the handler based on the provided subcategory.

To summarize, there is a HashMap that stores the message subcategories and their corresponding handler objects. If we send a message to the Avalanche Notification Server with the subtype equal to 3706, the AnsTestHandler.processMessage method will be invoked.

Let’s have a look at one example of a message handler, AnsTestHandler:.

AnsTestHandler.java

At [1], the SUBCATEGORY variable is defined. It is common for the message processors to define such a variable.

At [2], the processMessage method is defined.

At [3], it retrieves the XML payload from the message.

At [4], it deserializes the payload with the ObjectGraph.fromXML method. It then casts it to AnsTestPayload, although the casting occurs after the deserialization. According to that, if the ObjectGraph does not implement any additional protections (such as an allowlist), we should be able to do harm here.

Success! We have identified the message processing routine. Moreover, we were able to quickly map the subcategory to the corresponding fragment of code that will handle our message. It seems that right now, we should be able to craft our own message.

Is There Any Authentication?

At this point, it seemed that I had everything necessary to send my own message. However, when I sent one, I saw no reaction from the targeted service. I looked at the InfoRail service log file and spotted these interesting lines:

Figure 4 InfoRail Log Files – Dropping the Unauthenticated Message

It seems that I had missed an important part: authentication. Having all the details regarding the protocol and encryption, I was able to quickly identify a registration message in the network traffic. It is one of the rare examples where the payload is not stored in the XML form. The following screenshot presents a fragment of a registration message:

Figure 5 - Fragment of an Exemplary Registration Message

Several important things can be spotted here:
         -- reg.appident – specifies the name of the service that tries to register.
         -- reg.uname / reg.puname – specifies something that looks like a username.
         -- reg.cred / reg.pcred – specifies something that looks like a hashed password.

After a good deal of code analysis, I determined the following:
         -- Uname and puname are partially random.
         -- Cred and pcred values are MD5 hashes, based on the following values:
                  -- Username (.anonymous.0.digits).
                  -- Appropriate fragment of the key, which is hardcoded in the source code.

Once more, the only secret that is needed is visible in the source code. The attacker can retrieve the key and construct his own, valid registration message.

Finally, we can properly register with the InfoRail service and send our own messages to any of the Avalanche services.

Just Give Me Those Pwns Please – Code Execution on Four Services

At this stage, one can verify the services that do not implement a allowlist in the ObjectGraph class. I identified 5 of them:

- Data Repository Service (ZDI-CAN-15169).
- StatServer Service (ZDI-CAN-15130).
- Notification Server Service (ZDI-CAN-15448).
- Certificate Management Server Service (ZDI-CAN-15449).
- Web File Server Service (ZDI-CAN-15330).

We have five XStream deserialization endpoints that will deserialize anything we provide. One can immediately begin to consider ways to exploit this deserialization. For starters, XStream is very transparent about its security. Their security page (available here) presents multiple gadgets based on classes available in the Java runtime. Sadly, no suitable gadget worked for the first four services that I tried to exploit, as the required classes were not loaded.

Going further, one can have a look at Moritz Bechler’s “Java Unmarshaller Security” paper:

XStream tries to permit as many object graphs as possible – the default converters are pretty much Java Serialization on steroids. Except for the call to the first non-serializable parent constructor, it seems that everything that can be achieved by Java Serialization can be with XStream – including proxy construction.

 Proxy construction does not seem to be a thing in the newer versions of XStream. However, we should still be able to exploit it with ysoserial gadgets. Ysoserial gadgets for XStream were not available back then, so I created several myself. They can be found in this GitHub repository.

 Using my ysoserial XStream gadgets, I was successful in getting remode code execution in four Avalanche services. Here is a summary of the services I was able to exploit, and the required gadgets:

- StatServer: Exploited using AspectJWeaver and CommonsBeanutils1
- Data Repository: Exploited using C3P0 and CommonsBeanutils1
- Certificate Management Server: Exploited using CommonsBeanutils1
- Avalanche Notification Server: Exploited using CommonsBeanutils1

For no particular reason, let’s focus on the StatServer. To begin, we must find the topic and subcategory of some message that will deserialize the included XML payload. According to that, the InfoRail protocol message headers should contain the following keys and values:
h.distlist = 255.3.2.12
h.msgsubcat = 3502 (GetMuCellTowerData message)

In this example, we will make use of the AspectJWeaver gadget, which allows us to upload files. Below is the AspectJWeaver gadget for the XStream:

AspectJWeaver.xml

Several things can be highlighted in this gadget:
• The iConstant tag contains the Base64 file content.
• The folder tag contains a path to the upload directory. I am targeting the Avalanche Web Application root directory here.
• The key tag specifies the name of the file.

Having all the data needed, we can start the exploitation process:

Figure 6 - StatServer Exploitation - Upload of Web shell

The following screenshot presents the uploaded web shell and the execution of the whoami command.

Figure 7 - StatServer Exploitation - Webshell and Command Execution

Success! To sum up this part, an attacker who can send messages to Avalanche services can abuse the XStream deserialization in 4 different services.

I also got remote code execution on a fifth serviceHowever, exploiting this one was way trickier.

Exploiting JNDI Lookups Before It Was Cool

Java Naming and Directory Interface (JNDI) Lookups have a long history, and a lot of researchers were familiar with this vector long before the Log4Shell vulnerability. One of the proofs for that is CVE-2021-39146 – an XStream deserialization gadget that triggers a lookup. It has occurred to be the only XStream gadget that worked against the Web File Server service, for which I was not able to craft a valid ysoserial gadget.

Still, we are dealing with a fresh Java version. Thus, we are not able to abuse remote class loading. Moreover, the attacker is not able to abuse the LDAP deserialization vector (described here [PDF]). Using the JNDI injection, we can deliver the serialized payload, which will be then deserialized by our target. However, we are not aware of any deserialization gadgets that could be abused in the Web File Server.  If there were any gadgets, we would not need the JNDI lookup in the first place. Luckily, there are several interesting JAR packages included in the Web File Server Classpath.

Figure 8 - Web File Server - Tomcat JARs

As you can see, the Web File Server loads several Tomcat JAR packages. You might perhaps also be familiar with the great technique discovered by Michael Stepankin, which abuses unsafe reflection in Tomcat BeanFactory to execute arbitrary commands through JNDI Lookup. The original description can be found here.

In summary, we can execute the following attack:

  1. Set up malicious LDAP server, which will serve the malicious BeanFactory. We will use the Rogue JNDI tool.
  2. Register with the InfoRail service.
  3. Send the message containing the CVE-2021-39146 gadget, targeting the Web File Server pointing to the server defined in step 1.
  4. The Web File Server makes an LDAP lookup and retrieves data from the malicious server.
  5. Remote code execution.

The following screenshot presents the setup of the LDAP server:

Figure 9 - Setup of Rogue Jndi

The next snippet presents the CVE-2021-39146 gadget, which was used for this Proof of Concept:

jndiGadget.xml

If everything goes well and the lookup was performed successfully, Rogue JNDI should show the following message and the code should be executed on the targeted system.

Figure 10 - Triggered JNDI Lookup

To summarize, we were able to abuse the custom Ivanti Avalanche protocol and XML message deserialization mechanisms to exploit five different services and get remote code execution with SYSTEM privileges. I have found more deserialization vulnerabilities in Ivanti Avalanche, but I am leaving them for the second part of the blog post. Right now, I would like to stay with the protocol and inter-services communication.

Abusing a Race Condition in the Communication and Authentication Messages

As detailed above, the various Avalanche services communicate with each other with the help of InfoRail. When a service provides a response, the response is again forwarded via the InfoRail service. The idea for this research was: is it possible for an attacker to spoof a response? If so, it may be possible to abuse Ivanti Avalanche behavior and perform potentially malicious actions.

I focused on the authentication operation, which is presented in the following scheme (read from top to bottom):

Figure 11 - Authentication Scheme

When a user authenticates through the Avalanche Web Application login panel, the backend transfers the authentication message to the Enterprise Server. This service verifies credentials and sends back an appropriate response. If the provided credentials were correct, the user gets authenticated.

During this research, I learned two important things:
• The attacker can register as any service.
• The authentication message is distributed amongst every instance of the registered Enterprise Server.

According to that, the attacker can register himself as the Enterprise Server and intercept the incoming authentication messages. However, this behavior does not have much of an immediate consequence, as the transferred password is hashed and encrypted.

The next question was whether it is possible to deliver the attacker’s own response to the Avalanche Web and whether it will be accepted or not. It turns out that yes, it is possible! If you would like to deliver your own response, you must properly set two values in the message header:
Origin – The topic (ID) of the Avalanche Web backend that sent the message.
MsgId – The message ID of the original authentication message.

Both values are relatively easy to get, and thus the attacker can provide his own response to the message. It will be accepted by the service, which is waiting for the response. An example attack scenario is presented in the following figure (read from top to bottom ).

Figure 12 - Race Condition Scheme

The attack scenario works as follows:
         -- The attacker tries to log into the Web Application with the wrong credentials.
         -- Web Application sends the authentication message.
         --The InfoRail service sends the message to both Enterprise Servers: the legitimate one and the malicious one.
         --Race time:
                  --The legitimate server responds with the “wrong credentials” message.
                  --The malicious server responds with the “credentials OK” message.          --If the attacker’s server was first to deliver the message, it is forwarded to the Avalanche Web Application.
         --The attacker gets authenticated.

Please note that the “Login message” targeting the attacker’s server is not present here on purpose (although it is in reality transmitted to the attacker). I wanted to highlight the fact, that this issue can be exploited without a possibility to read messages. In such a case, the attacker has to brute-force the already mentioned message ID value. It complicates the whole attack, but the exploitation is still possible.

To summarize this part, the attacker can set up his own malicious Enterprise Server and abuse a race condition to deliver his own authentication response to the Web Application. There are two more things to investigate: what does the response message look like and are we able to win the race?

Authentication Handling

The following snippet presents an example response to a login message. Please note that those messages are way bigger during legitimate usage. However, for the Proof of Concept, I have minimized them and stored only those parts that are needed for exploitation.

The response message consists of several important parts:
• It contains a responseObject tag, which is a serialized User object.
• It contains a responseCode tag, which will be important.

At some point during authentication, the Web Backend invokes the UserService.doLogin method:

doLogin.java

At [1], the UserCredentials object is instantiated. Then, its members are set.

At [2], the authenticate method is called, and the object initialized at [1] is passed as an argument:

authenticate.java

At [1], the UserLogin object is initialized.

At [2], the UserCredentials object is serialized.

At [3], the message is being sent to the Enterprise Server, and the Web Backend waits for the response.

At [4], the responseCode included in the response is verified. We want it to be equal to 0.

At [5], the userLogin.authenticated is set to True.

At [6], the userLogin.currentUser is set to the object that was included in the responseObject.

At [7], the method returns the userLogin object.

Basically, the response should have a responseCode equal to 0. It should also include a properly serialized User object in the responseObject tag.

Finally, we analyze the fragment of UserBean.loginInner method that was responsible for the invocation of the doLogin function.

loginInner.java

At [1], the doLogin method is invoked. It retrieves the object of UserLogin type (see the returns of previous code snippets).

At [2], it sets this.currentUser to the userLogin.currentUser (the one obtained from the response).

At [3], it sets various other settings. These will not be relevant for us.

One very important thing to note: the Web Backend does not compare the username provided in the login panel and the username retrieved by the Enterprise Server. Accordingly, the attacker can:
• Trigger the authentication with the username “poc”.
• Win the race and provide the user “amcadmin” in the response.
• The attacker will then be authenticated as the “amcadmin”.

To summarize, it seems that there are no obstacles for the attacker and his response should be handled by the Web Backend without any problems. Next, we turn our focus to winning the race.

Winning the Race

In a default installation, the Enterprise Server and InfoRail services are located on the same host as the Web Backend. This makes the exploitation of the race condition harder, as the legitimate communication is handled by the local interface, which is much faster than communication through an external network interface.

Still, the attacker has some advantages. For example, he does not have to generate dynamic responses, as the response payload can be hardcoded in the exploit. The following table presents a general overview of actions that must be performed by both the attacker and the legitimate Enterprise Server.

Attacker Enterprise Server
·       Get the message ID from the original Login message and place it in the header. ·       Get the message ID from the original Login message and place it in the header.
·      Send static response. ·       Decrypt and verify the user’s credentials.
  ·       Retrieve the user’s details and create the User object.
  ·       Dynamically create the response.

The remote attacker needs to perform far fewer operations and can prepare his response more rapidly. It makes the race winnable. One may ask – what if the attacker’s position in the network too disadvantageous and he still has no chance to win the race? Even then, there is an effective solution.

The unauthenticated attacker could modify the Avalanche System Settings. This is due to a separate vulnerability that allows to bypassing domain authentication (ZDI-CAN-15919). The remote attacker could enable the LDAP-based authentication and set any address for the LDAP server configuration. In such a scenario, the legitimate Enterprise Server will first try to access this “rogue” authentication server. This will give the attacker an additional second or two (or even more if played properly). In this way, an attacker can gain more time to win the race, should this be necessary

Exploitation

Having all the pieces, the race condition vulnerability can be exploited. The following video shows an example of the attacker providing wrong credentials via the panel but was still successfully authenticating as the “amcadmin” user.

Conclusion

When you don’t have ideas for further research, make sure that you have discovered the complete attack surface of your recent targets. When you find a spot that was not already studied by others, you might find a path to discovering a whole new set of exciting vulnerabilities.

Keep an eye out for the second part of this blog, where I will share some details about my favorite vulnerabilities in the Ivanti Avalanche services. It will cover one more deserialization vulnerability, cool chains leading to the remote code execution, and a pretty rare information disclosure vulnerability.

Until then, you can follow me @chudypb  and the team @thezdi on Twitter for the latest in exploit techniques and security patches.

Riding the InfoRail to Exploit Ivanti Avalanche

CVE-2022-30136: Microsoft Windows Network File System v4 Remote Code Execution Vulnerability

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.

CVE-2022-30136: Microsoft Windows Network File System v4 Remote Code Execution Vulnerability

The July 2022 Security Update Review

12 July 2022 at 17:26

It’s once again Patch Tuesday, which means the latest security updates from Adobe and Microsoft have arrived. Take a break from your regularly scheduled activities and join us as we review the details of their latest security offerings.

Adobe Patches for July 2022

For July, Adobe addressed 27 CVEs in four patches for Acrobat and Reader, Photoshop, RoboHelp, and Adobe Character Animator. A total of 24 of these bugs were reported through the ZDI program. The update for Acrobat and Reader addresses a combination of 22 different Critical- and Important-rated bugs. The most severe of these could allow code execution if an attacker convinces a target to open a specially crafted PDF document. While there are no active attacks noted, Adobe does list this as a Priority 2 deployment rating. The update for Photoshop fixes one Critical- and one Important-rated bug. The Critical bug is a use-after-free (UAF) that could lead to code execution. The fix for Character Animator addresses two Critical-rated code execution bugs – one a heap overflow and the other an out-of-bounds (OOB) read. Finally, the patch for RoboHelp corrects a single Important-rated cross-site scripting (XSS) bug.

None of the bugs fixed by Adobe this month are listed as publicly known or under active attack at the time of release. Adobe categorizes most of these updates as a deployment priority rating of 3, with the Acrobat patch being the lone exception at 2.

Microsoft Patches for July 2022

For July, Microsoft released 84 new patches addressing CVEs in Microsoft Windows and Windows Components; Windows Azure components; Microsoft Defender for Endpoint; Microsoft Edge (Chromium-based); Office and Office Components; Windows BitLocker; Windows Hyper-V; Skype for Business and Microsoft Lync; Open-Source Software; and Xbox. This is in addition to the two CVEs patched in Microsoft Edge (Chromium-based). That brings the total number of CVEs to 87.

While this higher volume is expected for a July release, there are still no fixes available for the multiple bugs submitted during the last Pwn2Own competition. And after a brief respite last month, there are additional updates for the Print Spooler. Looks like this component will be back to a monthly release schedule.

Of the 84 new CVEs released today, four are rated Critical, and 80 are rated Important in severity. One of these bugs was submitted through the ZDI program. None of the new bugs patched this month are listed as publicly known, but one of the updates for CSRSS is listed as under active attack. Let’s take a closer look at some of the more interesting updates for this month, starting with the CSRSS bug under active attack:

-       CVE-2022-22047 – Windows CSRSS Elevation of Privilege
This bug is listed as being under active attack, but there’s no information from Microsoft on where the vulnerability is being exploited or how widely it is being exploited. The vulnerability allows an attacker to execute code as SYSTEM, provided they can execute other code on the target. Bugs of this type are typically paired with a code execution bug, usually a specially crafted Office or Adobe document, to take over a system. These attacks often rely on macros, which is why so many were disheartened to hear Microsoft’s delay in blocking all Office macros by default.

-       CVE-2022-30216 – Windows Server Service Tampering Vulnerability
This patch corrects a tampering vulnerability in the Windows Server Service that could allow an authenticated attacker to upload a malicious certificate to a target server. While this is listed as “Tampering”, an attacker who could install their own certificate on a target system could use this bug for various purposes, including code execution. While tampering bugs don’t often get much attention, Microsoft does give this its highest exploit index rating, meaning they expect active exploits within 30 days. Definitely test and deploy this patch quickly – especially to your critical servers.

-       CVE-2022-22029 – Windows Network File System Remote Code Execution Vulnerability
This is the third month in a row with a Critical-rated NFS bug, and while this one has a lower CVSS than the previous ones, it could still allow a remote, unauthenticated attacker to execute their code on an affected system with no user interaction. Microsoft notes multiple exploit attempts may be required to do this, but unless you are specifically auditing for this, you may not notice. If you’re running NFS, make sure you don’t ignore this patch.

-       CVE-2022-22038 - Remote Procedure Call Runtime Remote Code Execution Vulnerability
This bug could allow a remote, unauthenticated attacker to exploit code on an affected system. While not specified in the bulletin, the presumption is that the code execution would occur at elevated privileges. Combine these attributes and you end up with a potentially wormable bug. Microsoft states the attack complexity is high since an attacker would need to make “repeated exploitation attempts” to take advantage of this bug, but again, unless you are actively blocking RPC activity, you may not see these attempts. If the exploit complexity were low, which some would argue since the attempts could likely be scripted, the CVSS would be 9.8. Test and deploy this one quickly.

Here’s the full list of CVEs released by Microsoft for July 2022:

CVE Title Severity CVSS Public Exploited Type
CVE-2022-22047 Windows CSRSS Elevation of Privilege Vulnerability Important 7.8 No Yes EoP
CVE-2022-22038 Remote Procedure Call Runtime Remote Code Execution Vulnerability Critical 8.1 No No RCE
CVE-2022-30221 Windows Graphics Component Remote Code Execution Vulnerability Critical 8.8 No No RCE
CVE-2022-22029 Windows Network File System Remote Code Execution Vulnerability Critical 8.1 No No RCE
CVE-2022-22039 Windows Network File System Remote Code Execution Vulnerability Critical 7.5 No No RCE
CVE-2022-30215 Active Directory Federation Services Elevation of Privilege Vulnerability Important 7.5 No No EoP
CVE-2022-23816 * AMD: CVE-2022-23816 AMD CPU Branch Type Confusion Important N/A No No Info
CVE-2022-23825 * AMD: CVE-2022-23825 AMD CPU Branch Type Confusion Important N/A No No Info
CVE-2022-30181 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-33641 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-33642 Azure Site Recovery Elevation of Privilege Vulnerability Important 4.9 No No EoP
CVE-2022-33643 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-33650 Azure Site Recovery Elevation of Privilege Vulnerability Important 4.9 No No EoP
CVE-2022-33651 Azure Site Recovery Elevation of Privilege Vulnerability Important 4.9 No No EoP
CVE-2022-33652 Azure Site Recovery Elevation of Privilege Vulnerability Important 4.4 No No EoP
CVE-2022-33653 Azure Site Recovery Elevation of Privilege Vulnerability Important 4.9 No No EoP
CVE-2022-33654 Azure Site Recovery Elevation of Privilege Vulnerability Important 4.9 No No EoP
CVE-2022-33655 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-33656 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-33657 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-33658 Azure Site Recovery Elevation of Privilege Vulnerability Important 4.4 No No EoP
CVE-2022-33659 Azure Site Recovery Elevation of Privilege Vulnerability Important 4.9 No No EoP
CVE-2022-33660 Azure Site Recovery Elevation of Privilege Vulnerability Important 4.9 No No EoP
CVE-2022-33661 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-33662 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-33663 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-33664 Azure Site Recovery Elevation of Privilege Vulnerability Important 4.9 No No EoP
CVE-2022-33665 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-33666 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-33667 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-33668 Azure Site Recovery Elevation of Privilege Vulnerability Important 4.9 No No EoP
CVE-2022-33669 Azure Site Recovery Elevation of Privilege Vulnerability Important 4.9 No No EoP
CVE-2022-33671 Azure Site Recovery Elevation of Privilege Vulnerability Important 4.9 No No EoP
CVE-2022-33672 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-33673 Azure Site Recovery Elevation of Privilege Vulnerability Important 6.5 No No EoP
CVE-2022-33674 Azure Site Recovery Elevation of Privilege Vulnerability Important 8.3 No No EoP
CVE-2022-33675 Azure Site Recovery Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-33677 Azure Site Recovery Elevation of Privilege Vulnerability Important 7.2 No No EoP
CVE-2022-33676 Azure Site Recovery Remote Code Execution Vulnerability Important 7.2 No No RCE
CVE-2022-33678 Azure Site Recovery Remote Code Execution Vulnerability Important 7.2 No No RCE
CVE-2022-30187 Azure Storage Library Information Disclosure Vulnerability Important 4.7 No No Info
CVE-2022-22048 BitLocker Security Feature Bypass Vulnerability Important 6.1 No No SFB
CVE-2022-27776 * HackerOne: CVE-2022-27776 Insufficiently protected credentials vulnerability might leak authentication or cookie header data Important N/A No No Info
CVE-2022-22040 Internet Information Services Dynamic Compression Module Denial of Service Vulnerability Important 7.3 No No DoS
CVE-2022-33637 Microsoft Defender for Endpoint Tampering Vulnerability Important 6.5 No No Tampering
CVE-2022-33632 Microsoft Office Security Feature Bypass Vulnerability Important 4.7 No No SFB
CVE-2022-22036 Performance Counters for Windows Elevation of Privilege Vulnerability Important 7 No No EoP
CVE-2022-33633 Skype for Business and Lync Remote Code Execution Vulnerability Important 7.2 No No RCE
CVE-2022-22037 Windows Advanced Local Procedure Call Elevation of Privilege Vulnerability Important 7.5 No No EoP
CVE-2022-30202 Windows Advanced Local Procedure Call Elevation of Privilege Vulnerability Important 7 No No EoP
CVE-2022-30224 Windows Advanced Local Procedure Call Elevation of Privilege Vulnerability Important 7 No No EoP
CVE-2022-22711 Windows BitLocker Information Disclosure Vulnerability Important 6.7 No No Info
CVE-2022-30203 Windows Boot Manager Security Feature Bypass Vulnerability Important 7.4 No No SFB
CVE-2022-30220 Windows Common Log File System Driver Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-30212 Windows Connected Devices Platform Service Information Disclosure Vulnerability Important 4.7 No No Info
CVE-2022-22031 Windows Credential Guard Domain-joined Public Key Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-22026 Windows CSRSS Elevation of Privilege Vulnerability Important 8.8 No No EoP
CVE-2022-22049 Windows CSRSS Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-30214 Windows DNS Server Remote Code Execution Vulnerability Important 6.6 No No RCE
CVE-2022-22043 Windows Fast FAT File System Driver Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-22050 Windows Fax Service Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-22024 Windows Fax Service Remote Code Execution Vulnerability Important 7.8 No No RCE
CVE-2022-22027 Windows Fax Service Remote Code Execution Vulnerability Important 7.8 No No RCE
CVE-2022-30213 Windows GDI+ Information Disclosure Vulnerability Important 5.5 No No Info
CVE-2022-22034 Windows Graphics Component Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-30205 Windows Group Policy Elevation of Privilege Vulnerability Important 6.6 No No EoP
CVE-2022-22042 Windows Hyper-V Information Disclosure Vulnerability Important 6.5 No No Info
CVE-2022-30223 Windows Hyper-V Information Disclosure Vulnerability Important 5.7 No No Info
CVE-2022-30209 Windows IIS Server Elevation of Privilege Vulnerability Important 7.4 No No EoP
CVE-2022-22025 Windows Internet Information Services Cachuri Module Denial of Service Vulnerability Important 7.5 No No DoS
CVE-2022-21845 Windows Kernel Information Disclosure Vulnerability Important 4.7 No No Info
CVE-2022-30211 Windows Layer 2 Tunneling Protocol (L2TP) Remote Code Execution Vulnerability Important 7.5 No No RCE
CVE-2022-30225 Windows Media Player Network Sharing Service Elevation of Privilege Vulnerability Important 7.1 No No EoP
CVE-2022-22028 Windows Network File System Information Disclosure Vulnerability Important 5.9 No No Info
CVE-2022-22023 Windows Portable Device Enumerator Service Security Feature Bypass Vulnerability Important 6.6 No No SFB
CVE-2022-22022 Windows Print Spooler Elevation of Privilege Vulnerability Important 7.1 No No EoP
CVE-2022-22041 Windows Print Spooler Elevation of Privilege Vulnerability Important 6.8 No No EoP
CVE-2022-30206 Windows Print Spooler Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-30226 Windows Print Spooler Elevation of Privilege Vulnerability Important 7.1 No No EoP
CVE-2022-30208 Windows Security Account Manager (SAM) Denial of Service Vulnerability Important 6.5 No No DoS
CVE-2022-30216 Windows Server Service Tampering Vulnerability Important 8.8 No No Tampering
CVE-2022-30222 Windows Shell Remote Code Execution Vulnerability Important 8.4 No No RCE
CVE-2022-22045 Windows.Devices.Picker.dll Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-33644 Xbox Live Save Service Elevation of Privilege Vulnerability Important 7 No No EoP
CVE-2022-2294 * Chromium: CVE-2022-2294 Heap buffer overflow in WebRTC High N/A No Yes RCE
CVE-2022-2295 * Chromium: CVE-2022-2295 Type Confusion in V8 High N/A No No RCE

* Indicates this CVE had previously been assigned by a 3rd-party and is now being incorporated into Microsoft products.

Please note that Google is aware that an exploit for one of the Chromium bugs (CVE-2022-2294) exists in the wild. If you’re using Microsoft Edge (Chromium-based), make sure it gets updated as soon as possible.

Looking at the rest of the release, the first thing that stands out is the 32(!) patches for the Azure Site Recovery service. Two are remote code execution (RCE) bugs while the rest are elevation of privilege (EoP) issues. This is primarily a cloud-based service, but there are some on-prem components. Don’t expect an automatic update for these bugs. In all cases, you will need to upgrade to version 9.49 to remediate these vulnerabilities. Instructions for this can be found here. It’s incredibly unusual to see so many CVEs addressed in a single month for a single component, and it’s not clear why Microsoft chose to address these bugs in this manner. Regardless of why, if you rely on Azure Site Recovery, make sure you update all the necessary components.

There are two other Critical-rated bugs still to cover. There’s a second Critical-rated NFS vulnerability in addition to the one previously discussed. This is very similar to the other one but rates a slightly lower CVSS. It’s still Critical and the CVSS is questionable, so don’t think it’s any less dangerous. The highest CVSS patch this month belongs to a bug in Windows Graphic Component. These types of bugs usually manifest by either opening a file or viewing an image.

The remaining Critical-rated bugs impact some critical business functions. The first is a patch for the DNS server component. While certainly worth paying attention to, it does require the attacker to have elevated privileges. There’s an RCE bug in Windows Shell, but it requires a local attacker to interact with the logon screen. As always, don’t ignore physical security. There’s a code execution bug in Skype for Business and Lync (remember those?), but there are several prerequisites that make exploitation less likely. There’s a patch for the Layer 2 Tunneling Protocol (L2TP). It’s not clear how many people are using L2TP these days, but if you’re one of them, make sure you get this patch installed. Speaking of outdated methods of communication, there are two RCE bugs in the Windows Fax service receiving patches.

There are 52 fixes for EoP bugs, which includes the 30 Azure Site Recovery bugs we’ve already mentioned. In addition to the one under active attack, there are two other EoP bugs in CSRSS. For the most part, the rest of these bugs require an attacker to already have the ability to execute code on the target. They can then use one of these bugs to escalate to SYSTEM or some other elevated level. An exception to this is the bug in the Media Player Network Sharing service, which could be leveraged to delete registry keys. There’s also a patch for IIS to address a bug that could allow attackers to bypass authentication on an affected IIS server. The Group Policy bug requires the attacker to have privileges to create Group Policy Templates. Microsoft reminds us to regularly audit these groups, and that’s good advice for many reasons. There’s a patch for the Xbox Live Save Service, but it’s not clear what privileges an attacker would gain if they exploited this bug. Microsoft does list the attack vector as local, so perhaps multiple user profiles on the same Xbox would be impacted? And finally, after getting a month off, there are four new patches for the Print Spooler. We will likely continue to see additional print spooler fixes for the foreseeable future.

There are three fixes for denial-of-service (DoS) bugs in this month’s release, and all are impactful. The first impacts the Security Account Manager (SAM). While Microsoft doesn’t state the impact of this bug, a DoS on the SAM would likely lead to problems logging on to a domain. The other DoS patches fix bugs in IIS. The first covers the Cachuri module, which provides user-mode caching of URL information. The other is in the dynamic compression module, which (as its name implies) allows IIS to compress responses coming from various handlers. It doesn’t seem like either of these would lead to a complete website shutdown, but they would certainly degrade services.

In addition to the tampering bug mentioned above, there’s another tampering issue in Microsoft Defender for Endpoint. However, this bug requires the attacker to authenticate to the management console appliance and to have an integration token.

Physical access is a common factor in three of the four security feature bypass bugs getting fixed this month. The first is a BitLocker bypass that allows an attacker with physical access to a powered-off system to gain access to encrypted data. Similarly, the bug in Boot Manager allows an attacker with physical access to bypass Secure Boot and access the pre-boot environment. The bypass in the Windows Portable Device Enumerator service allows an attacker to attach a USB storage device to a system where Group Policy failed to apply. The final SFB occurs when opening a specially crafted Office file.

The July release contains new fixes for seven information disclosure bugs. Most of these only result in leaks consisting of unspecified memory contents, but there are a couple of notable exceptions. The bug in BitLocker could allow a local attacker to view raw, unencrypted disk sector data. Considering BitLocker’s purpose, you could almost consider this a security feature bypass. One of the Hyper-V bugs could let an attacker on a guest OS gain data from the Hyper-V host. The bug in the Azure Storage Library allows an attacker to decrypt data on the client side and disclose the content of the file or blob. There’s also a CVE assigned by HackerOne that could leak authentication or cookie header data via curl. This was originally patched in April 2022 and is now being incorporated into Microsoft products that use curl.

Finally, there are two information disclosure bugs covering AMD CPU Branch Type Confusion issues. These are related to the “Hertzbleed” vulnerabilities first documented in Intel processors last month. While interesting from an academic perspective, exploits using speculative execution side channels haven’t had much of an impact in the real world. 

No new advisories were released this month. The latest servicing stack updates can be found in the revised ADV990001.

Looking Ahead

The next Patch Tuesday falls on August 9, and I’ll be at Black Hat in Las Vegas to present on determining risk in an era of low patch quality. I’ll still be able to publish details and patch analysis of the August release, but please come by for the presentation if you’re at the conference. Until then, stay safe, happy patching, and may all your reboots be smooth and clean!

The July 2022 Security Update Review

CVE-2022-23088: Exploiting a Heap Overflow in the FreeBSD Wi-Fi Stack

16 June 2022 at 16:38

In April of this year, FreeBSD patched a 13-year-old heap overflow in the Wi-Fi stack that could allow network-adjacent attackers to execute arbitrary code on affected installations of FreeBSD Kernel. This bug was originally reported to the ZDI program by a researcher known as m00nbsd and patched in April 2022 as FreeBSD-SA-22:07.wifi_meshid. The researcher has graciously provided this detailed write-up of the vulnerability and a proof-of-concept exploit demonstrating the bug.


Our goal is to achieve kernel remote code execution on a target FreeBSD system using a heap overflow vulnerability in the Wi-Fi stack of the FreeBSD kernel. This vulnerability has been assigned CVE-2022-23088 and affects all FreeBSD versions since 2009, along with many FreeBSD derivatives such as pfSense and OPNsense. It was patched by the FreeBSD project in April 2022.

The Vulnerability

When a system is scanning for available Wi-Fi networks, it listens for management frames that are emitted by Wi-Fi access points in its vicinity. There are several types of management frames, but we are interested in only one: the beacon management subtype. A beacon frame has the following format:

In FreeBSD, beacon frames are parsed in ieee80211_parse_beacon(). This function iterates over the sequence of options in the frame and keeps pointers to the options it will use later.

One option, IEEE80211_ELEMID_MESHID, is particularly interesting:

There is no sanity check performed on the option length (frm[1]). Later, in function sta_add(), there is a memcpy that takes this option length as size argument and a fixed-size buffer as destination:

Due to the lack of a sanity check on the option length, there is an ideal buffer overflow condition here: the attacker can control both the size of the overflow (sp->meshid[1]) as well as the contents that will be written (sp->meshid).

Therefore, when a FreeBSD system is scanning for available networks, an attacker can trigger a kernel heap overflow by sending a beacon frame that has an oversized IEEE80211_ELEMID_MESHID option.

Building a “Write-What-Where” Primitive

Let’s look at ise->se_meshid, the buffer that is overflown during the memcpy. It is defined in the ieee80211_scan_entry structure:

Here, the overflow of se_meshid allows us to overwrite the se_ies field that follows. The se_ies field is of type struct ieee80211_ies, defined as follows:

We will be interested in overwriting the last two fields: data and len.

Back in sta_add(), not long after the memcpy, there is a function call that uses the se_ies field:

This ieee80211_ies_init() function is defined as:

The data parameter here points to the beginning of the beacon options in the frame, and len is the full length of all the beacon options. In other words, the (data,len) couple describes the options buffer that is part of the frame that the attacker sent:

Figure 1 - The Options Buffer

As noted in the code snippet, the ies structure is fully attacker-controlled thanks to the buffer overflow.

Therefore, at $1:

       -- We can control len, given that this is the full size of the options buffer, and we can decide that size by just adding or removing options to our frame.
       -- We can control the contents of data, given that this is the contents of the options buffer.
       -- We can control the ies->data pointer, by overflowing into it.

We thus have a near-perfect write-what-where primitive that allows us to write almost whatever data we want at whatever kernel memory address we want just by sending one beacon frame that has an oversized MeshId option.

Constraints on the Primitive

A few constraints apply to the primitive:

  1. The FreeBSD kernel expects there to be SSID and Rates options in the frame. That means that there are 2x2=4 bytes of the options buffer that we cannot control. In addition, our oversized MeshId option has a 2-byte header, so that makes 6 bytes we cannot control. For convenience and simplicity, we will place these bytes at the beginning of the options buffer.

  2. Our oversized MeshId option must be large enough to overwrite up to the ies->data and ies->len fields, but not more. This equates to a length of 182 bytes for the MeshId option, plus its 2-byte header. To accommodate the MeshId option plus the two options mentioned above, we will use an options buffer of size 188 bytes.

  3. The ies->data and ies->len fields we overwrite are respectively the last 8 and 4 bytes within the options buffer, so they too are constrained.

  4. The ies->len field must be equal to len for the branch at $0 not to be taken.

The big picture of what the frame looks like given the aforementioned constraints:

Figure 2 - The Big Picture

Maintaining stability of the target

Let’s say we send a beacon frame that uses the primitive to overwrite an area of kernel memory. There is going to be a problem at some point when the kernel subsequently tries to free ies->data. This is because ies->data is supposed to point to a malloc-allocated buffer, which may no longer be true after our overwrite.

To maintain stability and avoid crashing the target, we can send a second, corrective beacon frame that overflows ies->data to be NULL and ies->len to be 0. After that, when the kernel attempts to free ies->data, it will see that the pointer is NULL, and won’t do anything as a result. This allows us to maintain the stability of the target and ensure our primitive doesn’t crash it.

Choosing what to write, and where to write it

Now we have a nice write-what-where primitive that we can invoke with just one beacon frame plus one corrective frame. What exactly can we do with it now?

A first thought might be to use the primitive to overwrite the instructions that the kernel executes in memory. (Un)fortunately, in FreeBSD, the kernel text segment is not writable, so we cannot use our primitive to directly overwrite kernel instructions. Furthermore, the kernel implements W^X, so no writable pages are executable.

However, the page tables that map executable pages are writable.

Injecting an implant

Here we are going to inject an implant into the target's kernel that will process "commands" that we send to it later on via subsequent Wi-Fi frames — a full kernel backdoor, if you will.

The process of injecting this implant will take four beacon frames.

This is a bit of a bumpy technical ride, so fasten your seatbelt.

Frame 1: Injecting the payload

Background: the direct map is a special kernel memory region that contiguously maps the entire physical memory of the system as writable pages, except for the physical pages of read-only text segments.

We use the primitive to write data at the physical address 0x1000 using the direct map:

Figure 3 - Frame 1

0x1000 was chosen as a convenient physical address because it is unused. The data we write is as follows:

Figure 4 - Frame 1

The implant shellcode area contains the instructions of our implant. The rest of the fields are explained below.

Frame 2: Overwriting an L3 PTE

Quick Background: x64 CPUs use page tables to map virtual addresses to physical RAM pages, in a 4-level hierarchy that goes from L4 (root) to L0 (leaf). Refer to the official AMD and Intel specifications for more details.

In this step, we use the primitive to overwrite an L3 page table entry (PTE) and make it point to the L2 PTE that we wrote at physical address 0x1000 as part of Frame 1. We crafted that L2 PTE precisely to point to our three L1 PTEs, which themselves point to two different areas: (1) two physical pages of the kernel text segment, and (2) our implant shellcode.

In other words, by overwriting an L3 PTE, we create a branch in the page tables that maps two pages of kernel text as writable and our shellcode as executable:

Figure 5 - Frame 2

At this point, our shellcode is mapped into the target’s virtual memory space and is ready to be executed. We will see below why we're mapping the two pages of the kernel text segment.

The attentive reader may be concerned about the constraints of the primitive here. Nothing to worry about: the L3 PTE space is mostly unpopulated. We just have to choose an unpopulated range where overwriting 188 bytes will not matter.

Frame 3: Patching the text segment

In order to jump into our newly mapped shellcode, we will patch the beginning of the sta_input() function in the text segment. This function is part of the Wi-Fi stack and gets called each time the kernel receives a Wi-Fi frame, so it seems like the perfect place to invoke our implant.

How can we patch it, given that the kernel text segment is not writable? By mapping as writable the text pages that contain the function. This is what we did in frames 1 and 2, with the first two L1 PTEs, that now give us a writable view of the instruction bytes of sta_input():

Figure 6 - Our writable view of sta_input()

Back on topic, we use the primitive to patch the first bytes of sta_input() via the writable view we created in frames 1 and 2, and replace these bytes with:

This simply calls our shellcode. However, the constraints of our primitive come into play:

  1. The first constraint of the primitive is that the first 6 bytes that we overwrite cannot be controlled. Overwriting memory at sta_input would not be great, as it would put 6 bytes of garbage at the beginning of the function, causing the target to crash.

However, if we look at the instruction dump of sta_input, we can see that it actually has a convenient layout:

What we can do here is overwrite memory at sta_input-6. The 6 bytes of garbage will just overwrite the unreachable NOPs of the previous sta_newstate() function, with no effect on execution.

With this trick, we don’t have to worry about these first 6 bytes, as they are effectively discarded.

  1. The second constraint of the primitive is that we are forced to overwrite exactly 182 bytes, so we cannot overwrite the first few bytes only. This is not really a problem. We can just fill the rest of the bytes with the same instruction bytes that are there in memory already.

  2. The third constraint of the primitive is that the last 12 bytes that we write are the ies->data and ies->len fields, and these don’t disassemble to valid instructions. That’s a problem because these bytes are within sta_input(). If the kernel tries to execute these bytes, it won’t be long before it crashes. To work around this, we must have corrective code in our implant. When called for the first time, our implant must correct the last 12 bytes of garbage that we wrote into sta_input(). Although slightly annoying, this is not complicated to implement.

With all that established, we’re all set. Our implant will now execute each time sta_input() is called, meaning, each time a Wi-Fi frame is received by the target!

Frame 4: Corrective frame

Finally, to maintain the stability of the target, we send a final beacon frame where we overflow ies->data to be NULL and ies->len to be 0.

This ensures that the target won’t crash.

Subsequent communication channel

With the aforementioned four frames, we have a recipe to reliably inject an implant into the target’s kernel. The implant gets called in the same context as sta_input():

Notably, the second argument, m, is the memory region containing the buffer of the frame that the kernel is currently processing. The implant can therefore inspect that buffer (via %rsi) and act depending on its contents.

In other words, we have a communication channel with the implant. We can therefore code our implant as a server backdoor and send commands to it via this channel.

Full steps

Let’s recap:

  1. A heap buffer overflow vulnerability exists in the FreeBSD kernel. An attacker can trigger this bug by sending a beacon frame with an oversized MeshId option.
  2. Using that vulnerability, we can implement a write-what-where primitive that allows us to perform one kernel memory overwrite per beacon frame we send.
  3. We can use that primitive three times to inject an implant into the target’s kernel.
  4. A fourth beacon frame is used to clean up ies->data and ies->len, to prevent a crash.
  5. Finally, our implant runs in the kernel of the target and acts as a full backdoor that can process subsequent Wi-Fi frames we send to it.

The Exploit

A full exploit can be found here. It injects a simple implant that calls printf() with the strings that the attacker subsequently sends. To use this exploit from a Linux machine that has a Wi-Fi card called wifi0, switch the card to monitor mode with:

Then, build and run the exploit for the desired target. For example, if you wish to target a pfSense 2.5.2 system:

Please exercise caution - this will exploit all vulnerable systems in your vicinity.

Once you have done this, look at the target’s tty0 console. You should see: “Hello there, I’m in the kernel”.


Thanks again to m00nbsd for providing this thorough write-up. They have contributed multiple bugs to the ZDI program over the last few years, and we certainly hope to see more submissions from them in the future. Until then, follow the team for the latest in exploit techniques and security patches.

CVE-2022-23088: Exploiting a Heap Overflow in the FreeBSD Wi-Fi Stack

The June 2022 Security Update Review

14 June 2022 at 17:25

It’s once again Patch Tuesday, which means the latest security updates from Adobe and Microsoft have arrived. Take a break from your regularly scheduled activities and join us as we review the details of their latest security offerings.

Adobe Patches for June 2022

This month, Adobe released six patches addressing 46 CVEs in Adobe Illustrator, InDesign, InCopy, Bridge, Robohelp, and Animate. A total of 40 of these CVEs were reported by ZDI vulnerability researcher Mat Powell. The largest update belongs to Illustrator, which addresses 17 total CVEs. The most severe of these bugs could allow code execution if an affected system opens a specially crafted file. Many of these bugs fall into the Out-Of-Bounds (OOB) Write category. The update for Adobe Bridge fixes 12 bugs, 11 of which are rated Critical. The patch for InCopy fixes eight Critical-rated bugs, all of which could lead to arbitrary code execution. Similarly, the InDesign patch fixes seven Critical-rated arbitrary code execution bugs. For both InDesign and InCopy, the bugs are a mix of OOB Read, OOB Write, heap overflow, and Use-After-Free (UAF) vulnerabilities. The lone bug fixed by the Animate patch is also a Critical-rated OOB Write that could lead to arbitrary code execution. Finally, the Robohelp patch fixes a Moderate-rated privilege escalation bug caused by improper authorization.

None of the bugs fixed by Adobe this month are listed as publicly known or under active attack at the time of release. Adobe categorizes these updates as priority 3.

Microsoft Patches for June 2022

For June, Microsoft released 55 new patches addressing CVEs in Microsoft Windows and Windows Components; .NET and Visual Studio; Microsoft Office and Office Components; Microsoft Edge (Chromium-based); Windows Hyper-V Server; Windows App Store; Azure OMI, Real Time Operating System, and Service Fabric Container; SharePoint Server; Windows Defender; Windows Lightweight Directory Access Protocol (LDAP); and Windows Powershell. This is in addition to the 4 CVEs patched in Microsoft Edge (Chromium-based), and the new update for MSDT. That brings the total number of CVEs to 60.

Of the 55 new CVEs released today, three are rated Critical, 51 are rated Important, and one is rated Moderate in severity. None of the new bugs patched this month are listed as publicly known or under active attack at the time of release, however, we do have an update for MSDT, which is public and reported to be under active attack.

It's also interesting to note is what is not included in today’s release. This is the first month in recent memory without an update for the Print Spooler. We’ll see if that trend continues or if this reprieve is only temporary. Finally, there are no fixes listed for any of the bugs disclosed during Pwn2Own Vancouver.

Before we take a deeper dive into this month’s release, let’s take just a minute to remember Internet Explorer, which will go out of support tomorrow. The ubiquitous browser has served up websites to users since 1995, and while it’s doubtful anyone will miss it, it certainly had a good run. If you’re worried about your legacy apps still functioning, IE Mode in Microsoft Edge will be supported through at least 2029. With nostalgia out of the way, let’s take a closer look at some of the more interesting updates for this month, starting with the much anticipated fix for MSDT:

-       CVE-2022-30190 - Microsoft Windows Support Diagnostic Tool (MSDT) Remote Code Execution Vulnerability
Although it’s difficult to see from the Security Update Guide, Microsoft did release an update to address the much discuss “Follina” vulnerability in MSDT. This bug has been reported to be under active attack, so priority should be given to the testing and deployment of this update.

-       CVE-2022-30136 - Windows Network File System Remote Code Execution Vulnerability
This CVSS 9.8 bug looks eerily similar to CVE-2022-26937 – an NFS bug patched last month and one we blogged about last week. This vulnerability could allow a remote attacker to execute privileged code on affected systems running NFS. On the surface, the only difference between the patches is that this month’s update fixes a bug in NFSV4.1, whereas last month’s bug only affected versions NSFV2.0 and NSFV3.0. It’s not clear if this is a variant or a failed patch or a completely new issue. Regardless, enterprises running NFS should prioritize testing and deploying this fix.

 -       CVE-2022-30163 - Windows Hyper-V Remote Code Execution Vulnerability
This bug could allow a user on a Hyper-V guest to run their code on the underlying Hyper-V host OS. The update doesn’t list the privileges the attacker’s code would run at, but any guest-to-host escape should be taken seriously. Microsoft notes that attack complexity is high since an attacker would need to win a race condition. However, we have seen many reliable exploits demonstrated that involve race conditions, so take the appropriate step to test and deploy this update.

-       CVE-2022-30148 - Windows Desired State Configuration (DSC) Information Disclosure Vulnerability
Most info disclosure bugs simply leak unspecified memory contents, but this bug is different. An attacker could use this to recover plaintext passwords and usernames from log files. Since DSC is often used by SysAdmins to maintain machine configurations in an enterprise, there are likely some sought-after username/password combos that could be recovered. This would also be a great bug for an attacker to move laterally within a network. If you’re using DSC, make sure you don’t miss this update.

Here’s the full list of CVEs released by Microsoft for June 2022:

CVE Title Severity CVSS Public Exploited Type
CVE-2022-30163 Windows Hyper-V Remote Code Execution Vulnerability Critical 8.5 No No RCE
CVE-2022-30139 Windows Lightweight Directory Access Protocol (LDAP) Remote Code Execution Vulnerability Critical 7.5 No No RCE
CVE-2022-30136 Windows Network File System Remote Code Execution Vulnerability Critical 9.8 No No RCE
CVE-2022-30184 .NET and Visual Studio Information Disclosure Vulnerability Important 5.5 No No Info
CVE-2022-30167 AV1 Video Extension Remote Code Execution Vulnerability Important 7.8 No No RCE
CVE-2022-30193 AV1 Video Extension Remote Code Execution Vulnerability Important 7.8 No No RCE
CVE-2022-29149 Azure Open Management Infrastructure (OMI) Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-30180 Azure RTOS GUIX Studio Information Disclosure Vulnerability Important 7.8 No No Info
CVE-2022-30177 Azure RTOS GUIX Studio Remote Code Execution Vulnerability Important 7.8 No No RCE
CVE-2022-30178 Azure RTOS GUIX Studio Remote Code Execution Vulnerability Important 7.8 No No RCE
CVE-2022-30179 Azure RTOS GUIX Studio Remote Code Execution Vulnerability Important 7.8 No No RCE
CVE-2022-30137 Azure Service Fabric Container Elevation of Privilege Vulnerability Important 6.7 No No EoP
CVE-2022-22018 HEVC Video Extensions Remote Code Execution Vulnerability Important 7.8 No No RCE
CVE-2022-29111 HEVC Video Extensions Remote Code Execution Vulnerability Important 7.8 No No RCE
CVE-2022-29119 HEVC Video Extensions Remote Code Execution Vulnerability Important 7.8 No No RCE
CVE-2022-30188 HEVC Video Extensions Remote Code Execution Vulnerability Important 7.8 No No RCE
CVE-2022-21123 * Intel: CVE-2022-21123 Shared Buffer Data Read (SBDR) Important N/A No No Info
CVE-2022-21125 * Intel: CVE-2022-21125 Shared Buffers Data Sampling (SBDS) Important N/A No No Info
CVE-2022-21127 * Intel: CVE-2022-21127 Special Register Buffer Data Sampling Update (SRBDS Update) Important N/A No No Info
CVE-2022-21166 * Intel: CVE-2022-21166 Device Register Partial Write (DRPW) Important N/A No No Info
CVE-2022-30164 Kerberos AppContainer Security Feature Bypass Vulnerability Important 8.4 No No SFB
CVE-2022-30166 Local Security Authority Subsystem Service Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-30173 Microsoft Excel Remote Code Execution Vulnerability Important 7.8 No No RCE
CVE-2022-30154 Microsoft File Server Shadow Copy Agent Service (RVSS) Elevation of Privilege Vulnerability Important 5.3 No No EoP
CVE-2022-30159 Microsoft Office Information Disclosure Vulnerability Important 5.5 No No Info
CVE-2022-30171 Microsoft Office Information Disclosure Vulnerability Important 5.5 No No Info
CVE-2022-30172 Microsoft Office Information Disclosure Vulnerability Important 5.5 No No Info
CVE-2022-30174 Microsoft Office Remote Code Execution Vulnerability Important 7.4 No No RCE
CVE-2022-30168 Microsoft Photos App Remote Code Execution Vulnerability Important 7.8 No No RCE
CVE-2022-30157 Microsoft SharePoint Server Remote Code Execution Vulnerability Important 8.8 No No RCE
CVE-2022-30158 Microsoft SharePoint Server Remote Code Execution Vulnerability Important 8.8 No No RCE
CVE-2022-29143 Microsoft SQL Server Remote Code Execution Vulnerability Important 7.5 No No RCE
CVE-2022-30160 Windows Advanced Local Procedure Call Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-30151 Windows Ancillary Function Driver for WinSock Elevation of Privilege Vulnerability Important 7 No No EoP
CVE-2022-30189 Windows Autopilot Device Management and Enrollment Client Spoofing Vulnerability Important 6.5 No No Spoofing
CVE-2022-30131 Windows Container Isolation FS Filter Driver Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-30132 Windows Container Manager Service Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-30150 Windows Defender Remote Credential Guard Elevation of Privilege Vulnerability Important 7.5 No No EoP
CVE-2022-30148 Windows Desired State Configuration (DSC) Information Disclosure Vulnerability Important 5.5 No No Info
CVE-2022-30145 Windows Encrypting File System (EFS) Remote Code Execution Vulnerability Important 7.5 No No RCE
CVE-2022-30142 Windows File History Remote Code Execution Vulnerability Important 7.1 No No RCE
CVE-2022-30147 Windows Installer Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-30140 Windows iSCSI Discovery Service Remote Code Execution Vulnerability Important 7.1 No No RCE
CVE-2022-30165 Windows Kerberos Elevation of Privilege Vulnerability Important 8.8 No No EoP
CVE-2022-30155 Windows Kernel Denial of Service Vulnerability Important 5.5 No No DoS
CVE-2022-30162 Windows Kernel Information Disclosure Vulnerability Important 5.5 No No Info
CVE-2022-30141 Windows Lightweight Directory Access Protocol (LDAP) Remote Code Execution Vulnerability Important 8.1 No No RCE
CVE-2022-30143 Windows Lightweight Directory Access Protocol (LDAP) Remote Code Execution Vulnerability Important 7.5 No No RCE
CVE-2022-30146 Windows Lightweight Directory Access Protocol (LDAP) Remote Code Execution Vulnerability Important 7.5 No No RCE
CVE-2022-30149 Windows Lightweight Directory Access Protocol (LDAP) Remote Code Execution Vulnerability Important 7.5 No No RCE
CVE-2022-30153 Windows Lightweight Directory Access Protocol (LDAP) Remote Code Execution Vulnerability Important 8.8 No No RCE
CVE-2022-30161 Windows Lightweight Directory Access Protocol (LDAP) Remote Code Execution Vulnerability Important 8.8 No No RCE
CVE-2022-30135 Windows Media Center Elevation of Privilege Vulnerability Important 7.8 No No EoP
CVE-2022-30152 Windows Network Address Translation (NAT) Denial of Service Vulnerability Important 7.5 No No DoS
CVE-2022-32230 * Windows SMB Denial of Service Vulnerability Important N/A No No DoS
CVE-2022-22021 Microsoft Edge (Chromium-based) Remote Code Execution Vulnerability Moderate 8.3 No No RCE
CVE-2022-2007 * Chromium: Use after free in WebGPU High N/A No No RCE
CVE-2022-2008 * Chromium: Out of bounds memory access in WebGL High N/A No No RCE
CVE-2022-2010 * Chromium: Out of bounds read in compositing High N/A No No RCE
CVE-2022-2011 * Chromium: Use after free in ANGLE High N/A No No RC

* Indicates this CVE had previously been assigned by a 3rd-party and is now being incorporated into Microsoft products.

Looking at the rest of the release we that more than half of the patches this month deal with remote code execution. Seven of these deal with LDAP vulnerabilities, which is at least a decrease from the 10 LDAP patches last month. The most severe of these clocks in with a CVSS of 9.8 but would require the MaxReceiveBuffer LDAP policy to be set to a value higher than the default value. This doesn’t seem to be a common scenario. Still, the volume of bugs in LDAP over the last couple of months could indicate a broad attack surface in the component. Speaking of fertile attack surfaces, there are another six fixes for code execution bugs in the AV1 and HEVC media codecs. If you are connected to the Internet, you should automatically get updates from the Windows Store. However, if you are using these optional components in a disconnected environment, you’ll need to get these through either the Microsoft Store for Business or the Microsoft Store for Education. The same holds true for the patch addressing the RCE in the Photos App.

There are three RCE bugs receiving fixes in the Azure RTOS GUIX Studio, which provides developers a design for developing GUIs for IoT applications. What’s not clear is whether these apps will also need updates after installing these patches. There are a few RCE bugs in Office components, including a couple of interesting SharePoint bugs. Most of these require a user to open a specially crafted file. The SQL Server bug sounds pretty nasty but requires authentication. That should lessen the impact. Still, admins will need to carefully review the listed chart to determine which GDR and CU updates they require. This release includes patches impacting the iSCSI Discovery Service, Encrypting File System (EFS), and the File History component. All require some form of authentication, and the iSCSI and File History bugs require user interaction.

Moving on, there are 12 patches to address elevation of privilege (EoP) vulnerabilities. Most of these require an attacker to log on to a system and run specially crated code. There are, however, a couple of patches that stand out. The update for Azure Open Management Infrastructure (OMI) impacts multiple different Azure and SCOM components. Admins will need to touch most of these to ensure the bug is fully addressed, which will add to their workload. The patch for Azure Service Fabric doesn’t fix any bugs. Instead, it enforces the path to least privilege on Linux clusters. The bug in Kerberos affects servers with both Credential Security Service Provider (CredSSP) and Remote Credential Guard (RCG) installed. An attacker could elevate privileges and then spoof the Kerberos logon process when an RCG connection is made via CredSSP. Finally, the patch for the File Server Shadow Copy Agent Service (RVSS) only affects systems where the File Server VSS Agent Service is installed. However, on those systems, the patch alone isn’t enough. Admins must install the updates on Application and File Servers. Failure to do so could negatively impact backups and cause them to fail. See this KB article for more details.

The June release contains fixes for three Denial-of-Service (DoS) bugs. The DoS in the kernel could crash the OS, but it’s not clear how severe the bug in NAT could be. If it shut down NAT completely, it could devastate impacted enterprises. If you use NAT, treat this as a Critical update. Rapid7 also contributed a CVE in a Windows SMB that Microsoft had initially classified as a stability bug. This was silently fixed in the May 2022 updates and is being documented publicly here.

There’s a single security feature bypass being fixed this month in Kerberos AppContainer. If exploited, an attacker could bypass the Kerberos service ticketing feature that performs user access control checks. There’s also a single spoofing bug in this release for the Windows Autopilot Device Management component. There are a mountain of caveats to this bug, so if you’re using this management tool, read the bulletin carefully to determine if your systems are affected.

The release is rounded out by 11 information disclosure bugs. As previously mentioned, most of these only result in leaks consisting of unspecified memory contents. There are a couple of exceptions. The Office bug could expose device information such as resource IDs, SAS tokens, and user properties. The bug in .NET and Visual Studio could be used to intercept the API key intended for NuGet.org.

Finally, there are four info disclosure bugs addressing Intel Processor MMIO stale data vulnerabilities. An attacker could use these bugs to read privileged data across trust boundaries. Microsoft has also released Advisory ADV220002 detailing these bugs, and Intel has also released further details about this class of vulnerabilities.

Looking Ahead

The next Patch Tuesday falls on July 12, and we’ll return with details and patch analysis then. Until then, stay safe, happy patching, and may all your reboots be smooth and clean!

The June 2022 Security Update Review

CVE-2022-26937: Microsoft Windows Network File System NLM Portmap Stack Buffer Overflow

In this excerpt of a Trend Micro Vulnerability Research Service vulnerability report, Guy Lederfein and Jason McFadyen of the Trend Micro Research Team detail a recently patched code execution vulnerability in the Microsoft Windows operating system. The bug was originally discovered and reported to Microsoft by Yuki Chen. A stack buffer overflow vulnerability exists in Windows Network File System. A remote attacker can exploit this vulnerability by sending specially crafted RPC packets to a server, resulting in code execution in the context of SYSTEM. The following is a portion of their write-up covering CVE-2022-26937, with a few minimal modifications.


A stack buffer overflow vulnerability exists in Windows Network File System. The vulnerability is due to improper handling of crafted RPC responses to Portmap requests made by the Network Lock Manager (NLM) RPC program.

A remote attacker can exploit this vulnerability by sending malicious RPC calls to a target server. Successful exploitation may result in arbitrary code execution under the context of SYSTEM. Unsuccessful exploitation results in a crash of the target system.

The Vulnerability

Microsoft Windows ships with several network features designed to communicate and interact with non-Windows files 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.

The Network Lock Manager (NLM) protocol is an extension of NFS versions 2 and 3, which provides a System V style of advisory file and record locking over the network. Since NFS versions 2 and 3 are stateless protocols, the NLM protocol was developed to manage the state of locks on files stored on NFS shares. The NLM protocol supports both synchronous and asynchronous procedures to implement locking and file-sharing functionality. Similar to NFS, NLM also uses ONC RPC to exchange control messages.

ONC RPC uses XDR packets, which can be transmitted over UDP or TCP. Over UDP, the XDR packet is contained within the UDP payload. Over TCP, XDR packets are preceded by a Fragment header (as illustrated in the following table). The most significant bit of the Fragment header indicates whether the packet is the last fragment, and the remaining 31 bits are the length of the Fragment that follows. The Fragment itself contains the XDR packet.

The structure of an ONC RPC call is as follows:

The Program field of the RPC message specifies what RPC service the message is sent to. Windows NFS server implements the NLM protocol via RPC with Program type set to 100021. It supports multiple RPC procedures, which can be specified in the Procedure field in the RPC message. A list of synchronous and asynchronous procedures supported by the NLM protocol version 3 follows:

Microsoft Windows runs the RPCBIND RPC program, which implements the Port Mapper protocol, documented in RFC 1833. The RPCBIND program converts RPC program numbers into universal addresses, which can then be used by programs to communicate over UDP or TCP. Briefly, the way it works is that when a program wishes to use RPC, it registers its ports with the host's Port Mapper. A client that wishes to issue RPC calls connects to the Port Mapper, uses various RPC calls such as GETPORT, GETADDR etc. to obtain a port on which the RPC service is available, and connects to the desired RPC service. Standard RPC program numbers have been defined and maintained by IANA and they include portmapper (100000), nfs (100003), mount daemon (100005) and hundreds of other less commonly used programs. Only the portmapper service and NFS service have standard ports of 111 and 2049 respectively.

Windows implements the RPCBIND protocol via RPC with Program type set to 100000. It supports multiple RPC procedures, which can be specified in the Procedure field in the RPC message. One of the procedures supported by the RPCBIND program when Program Version is set to 3 or 4, is GETADDR, which is procedure number 3. The reply to this RPC call contains the Universal Address associated with the callee. The format for the returned Universal Address is XDR_String, which has the following format:

A stack buffer overflow vulnerability exists in Windows Network File System. More specifically, the vulnerability is due to incorrect handling of the Universal Address field returned in GETADDR RPC replies. When Windows NFS responds to an NLM call in an asynchronous manner, the NlmGetClientAddressAndConnection() function is called. This flow is triggered either as a response to an asynchronous NLM call, such as NLM_TEST_MSG, NLM_LOCK_MSG, NLM_UNLOCK_MSG, or when the server sends an `NLM_GRANTED` call to the client, after a previous (synchronous or asynchronous) call by the client to create a lock returned the status `LCK_BLOCKED`. If the IPv6 protocol is used for communication over the ONC RPC protocol, the server will issue a GETADDR RPC call to the client to retrieve its IP address. When the Universal Address field returned by the client in the GETADDR reply is processed by the NFS server, the field is copied using memmove() into a buffer of size 96 bytes. In addition, this buffer is later referenced at an index equal to the Universal Address field’s string size and set to 0. However, the NlmGetClientAddressAndConnection() function does not verify the size of the returned Universal Address string. Therefore, if the string provided by the client is 96 bytes or longer, the buffer will be written past its boundary, resulting in the stack buffer overflow condition.

A remote attacker can exploit this vulnerability by sending an NLM request triggering an asynchronous response by the NFS server. When the server sends a GETADDR RPC request, the attacker can respond with a crafted GETADDR reply. Successful exploitation may result in arbitrary code execution under the context of SYSTEM. Unsuccessful exploitation results in a crash of the target system.

Source Code Walkthrough

The following code snippet was taken from nfssvr.sys version 10.0.17763.1999. Comments added by Trend Micro have been highlighted.

 In function NlmGetClientAddressAndConnection():

Detecting Attacks

ONC RPC uses XDR packets, which can be transmitted over UDP or TCP. Over UDP, the XDR packet is contained within the UDP payload. Over TCP, XDR packets are preceded by a Fragment header (as illustrated in the following table). The most significant bit of the Fragment header indicates whether the packet is the last fragment, and the remaining 31 bits are the length of the Fragment that follows. The Fragment itself contains the XDR packet.

The detection device must inspect all outgoing ONC RPC calls, which have the following structure:

The detection device must check if the Message Type field is 0 (Call), the Program field is 100000 (portmap), the Program Version field is larger than 2, and the Procedure field is equal to 3 (GETADDR). If found, the device must inspect the Program-specific data object. This object uses the rpcb structure, which has the following format:

If the Program Number field is set to 100021 (NLM), the detection device must inspect all incoming ONC RPC replies, which have the following structure:

The detection device must check if the XID field is equal to the XID field of the GETADDR RPC call detected, and the Message Type field is 1 (Reply). If found, the device must inspect the Program-specific data object. This object uses the XDR_String structure, which has the following format:

If the String Length field is larger than 95, the traffic should be considered suspicious; an attack exploiting this vulnerability is likely underway.

Conclusion

This bug was patched by Microsoft in May 2022 and assigned CVE-2022-26937. In their write-up, they also list disabling NFSV2 and NFSV3 as a method to mitigate attacks. However, this could lead to a loss of functionality. Applying the security update is the best method to fully address this vulnerability.

Special thanks to Guy Lederfein and Jason McFadyen 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.

CVE-2022-26937: Microsoft Windows Network File System NLM Portmap Stack Buffer Overflow

Is exploiting a null pointer deref for LPE just a pipe dream?

A lot of blog posts I have read go over interesting vulnerabilities and exploits but do not typically share the process behind discovery. I want to show how sometimes just manually poking around can quickly uncover vulnerabilities you might miss with other approaches to vulnerability discovery.

In my previous blog, I highlighted a tool named IO Ninja and shared why it is helpful when working with Inter-Process Communications (IPC). In this blog, I would like to show you how this tool helped me find two vulnerabilities: CVE-2021-4198 and CVE-2021-4199 in Bitdefender’s antivirus software on Windows. The exploit I wrote targets a named pipe used by the Vulnerability.scan.exe process. The first vulnerability results in a denial-of-service on almost any process within the AV. The second results in local privilege escalation by exploiting a link following issue.

Now you might be thinking, wait a minute... how does a tool that lets you communicate with named pipes allow you to find a link following vulnerability? That is what we are going to dive into next.

The pipelist tool from Sysinternals reveals that Bitdefender uses several pipes for IPC.

Figure 1 – Output of the pipelist utility from the Sysinternals tool suite.

bdservicehost.exe is one of the executables that runs as SYSTEM after installing Bitdefender. It uses these pipes to communicate with other processes on the system and might be an interesting target.

Figure 2 – List of named pipes used by bdservicehost.exe

Using IO Ninja, we can spawn a pipe server as our standard user to see if we can trigger a connection from the client. Without reading any code, we can poke around the agent GUI to see what IPC connections are being created and what the traffic looks like.

Figure 3 - Bitdefender Total Security GUI

The screenshot below shows that we receive a connection from the client of the pipe that sends data to our named pipe server every time we open the agent GUI. This can be done by double clicking the Bitdefender icon in the system tray or opening it from the start menu.

Figure 4 - Connection from client to our named pipe server

What is interesting here is that the connection remains open. This allows us to send data back to the client. I took the first 16 bytes of data that was being sent to the server and echoed it back to the client multiple times to see if anything interesting would happen. I was also looking to see if the pipe connection would remain open after sending the data.

Figure 5 - Pipe client disconnects after sending data to it

After sending several messages, the client disconnects, and we get a popup box from Bitdefender informing the user that something went wrong within the AV. Take note of the “x” at the top right for dismissing the dialog box. This will become relevant later.

Figure 6 - Bitdefender telling us that we broke something.

After seeing this message, I knew that debugging information in some shape or form must be getting saved or logged.  I fired up Process Monitor from Sysinternals to see if a crash dump file, which I can further analyze in a debugger, was created.

As it turns out, an executable named “BDReinit.exe”, which is Bitdefender’s own crash handler, produces a crash dump file for us on the system.

Figure 7 – Process Monitor showing crash dump files being created by BDReinit.exe.

Another interesting discovery here was finding out that the folder to which the .dmp file is being written to is readable and writeable by standard users.

Figure 8 - Permissions of the directory storing the dump files.

Unfortunately, after looking at the dump file, I concluded the crash alone was not very interesting, and the process being crashed runs as our current user. At this point, I knew I had a potential local DoS on the AV but there had to be more to chew on here.

Figure 9 - NULL pointer dereference: CVE-2021-4198

After crashing this first process “seccenter.exe,” which is Bitdefender’s main GUI interface, I realized that I was still getting connections to my named pipe server. I was able to crash almost any process related to the AV by simply spamming the incoming pipe connections with those 16 bytes as soon as a client connected. I sat in front of my computer, watching the AV processes fall like dominos one after the other in process explorer.

I knew that kicking off a “Vulnerability Scan” in the GUI would spawn vulnerability.scan.exe, which ran as SYSTEM. I quickly tried to see if I could also crash this privileged process.

Figure 10 - Process Monitor showing crash dump files being created by BDReinit.exe, this time running as SYSTEM.

Ahh, the same “BDReinit.exe” process runs again, but this time it runs as SYSTEM. Based on the file name of the dump, we know we can also crash “Vulnerability.scan.exe,” and it writes the dump to disk as SYSTEM.

When looking for link following vulnerabilities, there are a few directories that are of immediate interest.

         C:\ProgramData
         C:\windows\temp
         C:\Users\[standard user]\AppData

I often look for privileged file writes and delete operations in these directories.

In this case, a .dmp file is being written to this directory as SYSTEM when a highly privileged process that is part of the AV crashes. This alone is not very interesting as we do not control the contents of the dump being written, and it’s the same exact crash from before.

I further analyzed the Process Monitor log and discovered that “BDReinit.exe” was doing two very dangerous things. First, it was writing a very permissive DACL to a file with a predictable name in a different directory. This directory also allowed a standard user read and write access, and the DACL write happened every time a crash occurred.

Figure 11 - Read and write access for everyone

The permissive DACL would get written to this file as SYSTEM if you crashed a process running as SYSTEM within Bitdefender. In this case, I just chose to again crash “Vulnerability.scan.exe” because of how easy it was to trigger. All I had to do was kick off a vulnerability scan in the GUI, and I would get a connection to my named pipe server from this process.

Figure 12 - Kicking off a vulnerability scan

Figure 13 - BDReinit.exe ACL write after crashing Vulnerability.scan.exe

One of my favorite parts about logic bugs like this is that exploiting them is typically very quick and easy. All we need to do to escalate to SYSTEM is redirect the permissive DACL write to a DLL used by the system, modify the contents of that DLL, and then have it get loaded. To do this redirection we just need one symbolic link and a target DLL.

One great candidate for the job is:

         C:\Windows\System32\spool\Drivers\x64\3\PrintConfig.dll

This is because a standard user can easily trigger a print job which will force svchost.exe to load our modified DLL as SYSTEM.

Figure 14 - Creating Symbolic link

Figure 15 - Redirecting BDReinit.exe DACL write

Figure 16 - Svchost.exe Loading modified DLL

Putting this all together, the following screenshot demonstrates executing code at SYSTEM using the techniques described.

Figure 17 - Putting it all together

The second major issue I found was related to the crash dump itself. If you clicked the “x” at the top right of the popup box I showed earlier, “BDReinit.exe” or “BdSubWiz.exe” which is the submission wizard, would delete the crash dump as your current user. If the user waited or ignored it for a while, the dialog box would timeout and delete the dump file as SYSTEM if the process that crashed was running as SYSTEM!

Figure 18- Log of BDReinit.exe arbitrary file deletion PoC

In the above screenshot, you can see how we can redirect this highly privileged file deletion to any file on the system. You can also use the techniques described in this blog to achieve privilege escalation and execute code at SYSTEM. Again, this is because the crash dump was being written and deleted from a location that our standard user had read and write access to regardless of the user that was running the crashed process. Furthermore, the files in that folder were not protected at all, so deleting them and replacing one with our link before the timeout was not an issue.

Figure 19 - Unrestricted file permissions

Conclusion

Sometimes vulnerability discovery isn’t super methodical and that’s okay! I did not spend any time reversing the functions responsible for IPC in this application to figure out what data to send over the pipe. However, I identified an attack surface and started poking around. This led me to an entirely different attack surface where there were some critical vulnerabilities.

I hope this blog inspires and enables you to do the same with your targets. Furthermore, I hope it reminds you to look at custom crash handlers and their dialog boxes – both for bugs and to make sure you aren’t unintentionally giving away your research. 😀

Below is a Procmon filter I use that you can download and import to search for link-following vulnerabilities. Just be sure to either change your username to “lowpriv,” or edit the filter before you use it. You can download it here.

Keep an eye out for future blogs where I will share details on other vulnerabilities I have found. Until then, you can follow me @izobashi and the team @thezdi on Twitter for the latest in exploit techniques and security patches.

Happy hunting!

 

Tools used:

-       IO Ninja
-       SysInternals
-       Symboliclink Testing Tools

Advisories:

https://www.bitdefender.com/support/security-advisories/incorrect-permission-assignment-for-critical-resource-vulnerability-in-bdreinit-exe-va-10017/

https://www.bitdefender.com/support/security-advisories/messaging_ipc-dll-null-pointer-dereference-in-multiple-bitdefender-products-va-10016/

Other Resources:       

https://www.zerodayinitiative.com/blog/2021/11/17/mindshare-using-io-ninja-to-analyze-npfs

https://decoder.cloud/2019/11/13/from-arbitrary-file-overwrite-to-system/

https://www.zerodayinitiative.com/blog/2022/3/16/abusing-arbitrary-file-deletes-to-escalate-privilege-and-other-great-tricks

Is exploiting a null pointer deref for LPE just a pipe dream?

Pwn2Own Vancouver 2022 - The Results

18 May 2022 at 19:08

Pwn2Own Vancouver for 2022 is underway, and the 15th anniversary of the contest has already seen some amazing research demonstrated. Stay tuned to this blog for updated results, picture, and videos from the event. We’ll be posting it all here - including the most recent Master of Pwn leaderboard.

Jump to Day One results; Jump to Day Two results; Jump to Day Three results

Here are the current standings for the Master of Pwn:

Current as of May 20, 12:00 Pacific

Day One - May 18, 2022

SUCCESS - Hector “p3rr0” Peralta was able to demonstrate an improper configuration against Microsoft Teams. He earns $150,000 and 15 Master of Pwn points.

Hector “p3rr0” Peralta demonstrates a improper configuration bug on Microsoft Teams by launching calc.

SUCCESS - Billy Jheng Bing-Jhong (@st424204), Muhammad Alifa Ramdhan (@n0psledbyte), and Nguyễn Hoàng Thạch (@hi_im_d4rkn3ss) of STAR Labs successfully used an OOB Read and OOB Write to achieve escalation on Oracle Virtualbox. They earn $40,000 and 4 Master of Pwn points.

SUCCESS - Masato Kinugawa was able to execute a 3-bug chain of injection, misconfiguraton and sandbox escape against Microsoft Teams, earning $150,000 and 15 Master of Pwn points.

SUCCESS - Manfred Paul (@_manfp) successfully demonstrated 2 bugs - prototype pollution and improper input validation - on Mozilla Firefox, earning him $100,000 and 10 Master of Pwn points.

Manfred Paul (left) demonstrates his 2 bug vulnerability submission on Mozilla Firefox to ZDI Analysts Hossein Lotfi and Michael DePlante.

SUCCESS - Marcin Wiązowski was able to execute an out-of-bounds write escalation of privilege on Microsoft Windows 11, earning $40,000 and 4 Master of Pwn points, and high praise on the accompanying whitepaper from the Microsoft team.

SUCCESS - Team Orca of Sea Security (security.sea.com) was able to execute 2 bugs on Ubuntu Desktop - an Out-of-Bounds Write (OOBW) and Use-After-Free (UAF) - earning $40,000 and 4 Master of Pwn points.

Team Orca of Sea Security successfully demonstrates their OOBW and UAF on Ubuntu Desktop.

SUCCESS - Daniel Lim Wee Soong (@daniellimws), Poh Jia Hao (@Chocologicall), Li Jiantao (@CurseRed) & Ngo Wei Lin (@Creastery) of STAR Labs successfully demonstrated their zero-click exploit of 2 bugs (injection and arbitrary file write) on Microsoft Teams. They earn $150,000 and 15 Master of Pwn points.

SUCCESS - Manfred Paul (@_manfp) successfully scored his second win of the day with an out-of-band write on Apple Safari, earning him another $50,000 and 5 additional Master of Pwn points.

SUCCESS - Phan Thanh Duy (@PTDuy and Lê Hữu Quang Linh (@linhlhq of STAR Labs earned $40K and 4 Master of Pwn points for a Use-After-Free elevation of privilege on Microsoft Windows 11.

SUCCESS - Keith Yeo (@kyeojy) earned $40K and 4 Master of Pwn points for a Use-After-Free exploit on Ubuntu Desktop.

Day Two - May 19, 2022

SUCCESS and BUG COLLISION - On the first attempt of the day, David BERARD and Vincent DEHORS from @Synacktiv were able to demonstrate 2 unique bugs (Double-Free & OOBW) with collision on a known sandbox escape on a Tesla Model 3 Infotainment System. They earn $75,000 and 7.5 Master of Pwn points, and although they don't win the car outright, they have made enough to go pick one up themselves!

First attempt of the day at Tesla. From left to right: 2 representatives from Tesla (standing and seated), ZDI Analyst Michael DePlante, Sr. Director of Vulnerability Research (ZDI) Brian Gorenc, David BERARD and Vincent DEHORS of Synacktiv.

FAILURE - On the second attempt of day 2, namnp was unable to get their exploit of Microsoft Windows 11 working within the time allotted.

SUCCESS - Bien Pham (@bienpnn) was able to execute a Use After Free bug leading to elevation of privilege on Unbuntu Desktop, earning $40,000 and 4 Master of Pwn points.

Local elevation of privilege on Ubuntu Desktop courtesy of Bien Pham.

FAILURE - @Jedar_LZ was unable to get today's second Tesla attempt working within the time allotted. On a positive note, @thedzi decided to acquire the details of the exploit and disclose them to Tesla.

SUCCESS - T0 was able to successfully show an improper access control bug leading to elevation of privilege on Microsoft Windows 11 - earning $40,000 and 4 Master of Pwn points.

SUCCESS - On the final attempt of Day 2, Zhenpeng Lin (@Markak_), Yueqi Chen (@Lewis_Chen_), and Xinyu Xing (@xingxinyu) of Team TUTELARY from Northwestern University successfully demonstrated a Use After Free bug leading to elevation of privilege on Ubuntu Desktop. This earns him $40,000 and 4 Master of Pwn points.

From left: Yueqi Chen of Team TUTELARY of Northwestern University with ZDI Analysts Tony Fuller and Bobby Gould.

Day Three - May 20, 2022

FAILURE - On the first attempt of day 3, Team DoubleDragon: Yonghwi Jin (@jinmo123) of Theori, and Yongjin Kim (@adm1nkyj1) of Enki was unable to get their exploit of Microsoft Teams working within the time allotted. All is not lost though, in that Team Double Dragon was able to get their research into the regular ZDI process.

SUCCESS - nghiadt12 from Viettel Cyber Security was able to successfully show an escalation of privilege via Integer Overflow on Microsoft Windows 11 - earning $40,000 and 4 Master of Pwn points.

EOP via Integer Overflow on Windows 11 courtesy of nghiadt12 from Viettel Cyber Security

SUCCESS - Billy Jheng Bing-Jhong (@st424204) STAR Labs was able to successfully demonstrate a Use-After-Free exploit on Ubuntu Desktop - earning another $40,000 and 4 Master of Pwn points.

SUCCESS - vinhthp1712 successfully achieved Elevation of Privilege via Improper Access Control on Microsoft Windows 11. vinhthp1712 earns $40,000 and 4 Master of Pwn points.

SUCCESS - On the final attempt of the competition, Bruno PUJOS (@brunopujos) from REverse Tactics successfully achieved Elevation of Privilege via Use-After-Free on Microsoft Windows 11. Bruno earns $40,000 and 4 Master of Pwn points.

Bruno PUJOS from REverse Tactics drops an EOP via UAF on Microsoft Windows 11.

That concludes the regular scheduled programming for our event! This year, we had a total of 21 attempts from 17 contestants with Trend Micro and ZDI awarding $1,155,000! We can’t wait to share more details in the near future about our fall event, so stay tuned!

As always, follow us on Twitter for the latest results, update, and breaking news.

Thanks again to our partners Tesla, Zoom, and Microsoft as well as our sponsor VMware. Thanks also to the researchers who participate and to the vendors for providing fixes for what was discovered and reported during the contest. As a reminder, vendors have 90 days to produce a fix for all vulnerabilities disclosed.

Pwn2Own Vancouver 2022 - The Results

Pwn2Own Vancouver 2022 - The Schedule

17 May 2022 at 23:47

Welcome to Pwn2Own Vancouver 2022! This year marks the 15th anniversary of the contest, and we plan on celebrating by putting some amazing research on display. For this year’s event, we have 17 contestants attempting to exploit 21 targets across multiple categories. As always, we began our contest with a random drawing to determine the order of attempts. If you missed it, you can watch the replay here.

The complete schedule for the contest is below (all times Pacific [GMT -7:00]).

Note: All times subject to change - You can see the results and live updates here once they become available. Entries marked with a 📷 icon will be live-streamed on YouTube, Twitch, and Twitter.

Wednesday, May 18, 2022

0930: Hector “p3rr0” Peralta targeting Microsoft Teams in the Enterprise Communications category

📷  1030: Billy Jheng Bing-Jhong (@st424204), Muhammad Alifa Ramdhan (@n0psledbyte), and Nguyễn Hoàng Thạch (@hi_im_d4rkn3ss) of STAR Labs targeting Oracle VirtualBox with a guest-to-host escape in the Virtualization category

📷  1200: Masato Kinugawa targeting Microsoft Teams in the Enterprise Communications category

📷  1300: Manfred Paul (@_manfp) targeting Mozilla Firefox (including sandbox escape) in the Web Browser category

1330: Marcin Wiązowski targeting Microsoft Windows 11 in the Local Elevation of Privilege category

1400: Team Orca of Sea Security (security.sea.com) targeting Ubuntu Desktop in the Local Elevation of Privilege category

1450: Daniel Lim Wee Soong (@daniellimws), Poh Jia Hao (@Chocologicall), Li Jiantao (@CurseRed) & Ngo Wei Lin (@Creastery) of STAR Labs targeting Microsoft Teams in the Enterprise Communications category

📷  1550: Manfred Paul (@_manfp) targeting Apple Safari in the Web Browser category

📷  1650: Keith Yeo (@kyeojy) targeting Ubuntu Desktop in the Local Elevation of Privilege category

1720: Phan Thanh Duy (@PTDuy) and Lê Hữu Quang Linh (@linhlhq) of STAR Labs targeting Microsoft Windows 11 in the Local Elevation of Privilege category

Thursday, May 19, 2022

 📷  1000: David BERARD and Vincent DEHORS from @Synacktiv target the Tesla Model 3 Infotainment System (with Sandbox Escape) in the Automotive category

 1100: namnp targeting Microsoft Windows 11 in the Local Elevation of Privilege category

 📷  1130: Bien Pham (@bienpnn) targeting Ubuntu Desktop in the Local Elevation of Privilege category

 📷 1300: @Jedar_LZ targeting the Tesla Model 3 Diagnostic Ethernet (with Root Persistence) in the Automotive category

 1400: T0 targeting Microsoft Windows 11 in the Local Elevation of Privilege category

 📷  1430: TUTELARY from Northwestern University targeting Ubuntu Desktop in the Local Elevation of Privilege category

 Friday, May 20, 2022

 📷  1000: Team DoubleDragon: Yonghwi Jin (@jinmo123) of Theori, and Yongjin Kim (@adm1nkyj1) of Enki targeting Microsoft Teams in the Enterprise Communications category

 1030: nghiadt12 from Viettel Cyber Security targeting Microsoft Windows 11 in the Local Elevation of Privilege category

📷  1100: Billy Jheng Bing-Jhong (@st424204) of STAR Labs targeting Ubuntu Desktop in the Local Elevation of Privilege category

1300: vinhthp1712 targeting Microsoft Windows 11 in the Local Elevation of Privilege category

📷  1330: Bruno PUJOS (@brunopujos) from REverse Tactics targeting Microsoft Windows 11 in the Local Elevation of Privilege category

 📷  1520: Award Ceremony

Pwn2Own Vancouver 2022 - The Schedule

❌