Normal view

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

MindShaRE: Using IO Ninja to Analyze NPFS

18 November 2021 at 17:14

In this installment of our MindShaRE series, ZDI vulnerability researcher Michael DePlante describes how he uses the IO Ninja tool for reverse engineering and software analysis. According to its website, IO Ninja provides an “all-in-one terminal emulator, sniffer, and protocol analyzer.” The tool provides many options for researchers but can leave new users confused about where to begin. This blog provides a starting point for some of the most commonly used features. 


Looking at a new target can almost feel like meeting up with someone who’s selling their old car. I’m the type of person who would want to inspect the car for rust, rot, modifications, and other red flags before I waste the owner’s or my own time with a test drive. If the car isn’t super old, having an OBD reader (on-board diagnostics) may save you some time and money. After the initial inspection, a test drive can be critical to your decision. 

Much like checking out a used car, taking software for test drives as a researcher with the right tools is a wonderful way to find issues. In this blog post, I would like to highlight a tool that I have found incredibly handy to have in my lab – IO Ninja.

Lately, I have been interested in antivirus products, mainly looking for local privilege escalation vulnerabilities. After looking at several vendors including Avira, Bitdefender, ESET, Panda Security, Trend Micro, McAfee, and more, I started to notice that almost all of them utilize the Named Pipe Filesystem (NPFS). Furthermore, NPFS is used in many other product categories including virtualization, SCADA, license managers/updaters, etc.

I began doing some research and realized there were not many tools that let you locally sniff and connect to these named pipes easily in Windows. The Sysinternals suite has a tool called Pipelist and it works exactly as advertised. Pipelist can enumerate open pipes at runtime but can leave you in the dark about pipe connections that are opening and closing frequently. Another tool also in the Sysinternals suite called Process Explorer allows you to view open pipes but only shows them when you are actively monitoring a given process. IO Ninja fills the void with two great plugins it offers.

An Introduction to IO Ninja  

When you fire up IO Ninja and start a new session, you’re presented with an expansive list of plugins as shown below. I will be focusing on two of the plugins under the “File Systems” section in this blog: Pipe Monitor and Pipe Server.  

Before starting a new session, you may need to check the “Run as Administrator” box if the pipes you want to interact with require elevated privileges to read or write. You can inspect the permissions on a given pipe with the accesschk tool from the Sysinternals Suite:

The powerful Pipe Monitor plugin in IO Ninja allows you to record communication, as well as apply filters to the log. The Pipe Server plugin allows you to connect to the client side of a pipe. 

IO Ninja: Pipe Monitor

The following screenshot provides a look at the Pipe Monitor plugin that comes by default with IO Ninja.

In the above screenshot, I added a process filter (*chrome*) and started recording before I opened the application. You can also filter on a filename ( name of the pipe), PID, or file ID. After starting Chrome, data started flowing between several pipe instances. This is a terrific way to dynamically gather an understanding of what data is going through each pipe and when those pipes are opened and closed. I found this helpful when interacting with antivirus agents and wanted to know what pipes were being opened or closed based on certain actions from the user, such as performing a system scan or update. It can also be interesting to see the content going across the pipe, especially if it contains sensitive data and the pipe has a weak ACL.

It can also help a developer debug an application and find issues in real-time like unanswered pipe connections or permission issues as shown below. 

Using IO Ninja’s find text/bin feature to search for “cannot find”, I was able to identify several connections in the log below where the client side of a connection could not find the server side. In my experience, many applications make these unanswered connections out of the box.

What made this interesting was that the process updatesrv.exe, running as NT AUTHORITY\SYSTEM, tried to open the client side of a named pipe but failed with ERROR_FILE_NOT_FOUND. We can fill the void by creating our own server with the name it is looking for and then triggering the client connection by initiating an update within the user interface.

As a low privileged user, I am now able to send arbitrary data to a highly privileged process using the Pipe Server plugin. This could potentially result in a privilege escalation vulnerability, depending on how the privileged process handles the data I am sending it.

IO Ninja: Pipe Server

The Pipe Server plugin is powerful as it allows you to send data to specific client connections from the server side of a pipe. The GUI in IO Ninja allows you to select which conversation you’d like to interact with by selecting from a drop-down list of Client IDs. Just like with the Pipe Monitor plugin, you can apply filters to clean up the log. Below you’ll find a visual from the Pipe Server plugin after starting the server end of a pipe and getting a few client connections.  

In the bottom right of the previous image, you can see the handy packet library. Other related IO Ninja features include a built-in hex editor, file- and script-based transmission, and packet templating via the packet template editor.

The packet template editor allows you to create packet fields and script custom actions using the Jancy scripting language. Fields are visualized in the property grid as shown above on the bottom left-hand side of the image, where they can be edited. This feature makes it significantly easier to create and modify packets when compared to just using a hex editor.

Conclusion

This post only scratches the surface of what IO Ninja can do by highlighting just two of the plugins offered. The tool is scriptable and provides an IDE that encourages users to build, extend or modify existing plugins.  The plugins are open source and available in a link listed at the end of the blog. I hope that this post inspires you to take a closer look at NPFS as well as the IO Ninja tool and the other plugins it offers.

Keep an eye out for future blogs where I will go into more detail on vulnerabilities I have found in this area. Until then, you can follow me @izobashi and the team @thezdi on Twitter for the latest in exploit techniques and security patches.

Additional information about IO Ninja can be found on their website. All of IO Ninja’s plugins are open source and available here.

Additional References

If you are interested in learning more you can also check out the following resources which I found helpful.

Microsoft - Documentation: Named Pipes

Gil Cohen - Call the plumber: You have a leak in your named pipe

0xcsandker - Offensive Windows IPC Internals 1: Named Pipes

MindShaRE: Using IO Ninja to Analyze NPFS

CVE-2021-28632 & CVE-2021-39840: Bypassing Locks in Adobe Reader

21 October 2021 at 16:12

Over the past few months, Adobe has patched several remote code execution bugs in Adobe Acrobat and Reader that were reported by researcher Mark Vincent Yason (@MarkYason) through our program. Two of these bugs, in particular, CVE-2021-28632 and CVE-2021-39840, are related Use-After-Free bugs even though they were patched months apart. Mark has graciously provided this detailed write-up of these vulnerabilities and their root cause.


This blog post describes two Adobe Reader use-after-free vulnerabilities that I submitted to ZDI: One from the June 2021 patch (CVE-2021-28632) and one from the September 2021 patch (CVE-2021-39840). An interesting aspect about these two bugs is that they are related – the first bug was discovered via fuzzing and the second bug was discovered by reverse engineering and then bypassing the patch for the first bug.

CVE-2021-28632: Understanding Field Locks

One early morning while doing my routine crash analysis, one Adobe Reader crash caught my attention:

After a couple of hours minimizing and cleaning up the fuzzer-generated PDF file, the resulting simplified proof-of-concept (PoC) was as follows:

PDF portion (important parts only):

JavaScript portion:

The crash involved a use-after-free of CPDField objects. CPDField objects are internal AcroForm.api C++ objects that represent text fields, button fields, etc. in interactive forms.

In the PDF portion above, two CPDField objects are created to represent the two text fields named fieldParent and fieldChild. Note that the created objects have the type CTextField, a subclass of CPDField, which is used for text fields. To simplify the discussion, they will be referred to as CPDField objects.

An important component for triggering the bug is that fieldChild should be a descendant of fieldParent by specifying it in the /Kids key of the fieldParent PDF object dictionary (see [A] above) as documented in the PDF file format specification:

img01.jpg

Another important concept relating to the bug is that to prevent a CPDField object from being freed while it is in use, an internal property named LockFieldProp is used. Internal properties of CPDField objects are stored via a C++ map member variable.

If LockFieldProp is not zero, it means that the CPDField object is locked and can't be freed; if it is zero or is not set, it means that the CPDField object is unlocked and can be freed. Below is the visual representation of the two CPDField objects in the PoC before the field locking code (discussed later) is called: fieldParent is unlocked (LockFieldProp is 0) and is in green, and fieldChild is also unlocked (LockFieldProp is not set) and is also in green:

img02.jpg

On the JavaScript portion of the PoC, the code sets up a JavaScript callback so that when the “Format” event is triggered for fieldParent, a custom JavaScript function callback() will be executed [2]. The JavaScript code then triggers a “Format” event by setting the textSize property of fieldParent [3]. Internally, this executes the textSize property setter of JavaScript Field objects in AcroForm.api.

One of the first actions of the textSize property setter in AcroForm.api is to call the following field locking code against fieldParent:

The above code locks the CPDField object passed to it by setting its LockFieldProp property to 1 [AA].

After executing the field locking code, the lock state of fieldParent (locked: in red) and fieldChild (unlocked: in green) are as follows:

img03.jpg

Note that in the later versions of Adobe Reader, the value of LockFieldProp is a pointer to a counter instead of being set with the value 1 or 0.

Next, the textSize property setter in AcroForm.api calls the following recursive CPDField method where the use-after-free occurs:

On the first call to the above method, the this pointer points to the locked fieldParent CPDField object. Because it has no associated widget [aa], the method performs a recursive call [cc] with the this pointer pointing to each of fieldParent's children [bb].

Therefore, on the second call to the above method, the this pointer points to the fieldChild CPDField object, and since it has an associated widget (see [B] in the PDF portion of the PoC), a notification will be triggered [dd] that results in the custom JavaScript callback() function to be executed. As shown in the previous illustration, the locking code only locked fieldParent while fieldChild is left unlocked. Because fieldChild is unlocked, the removeField("fieldChild") call in the custom JavaScript callback() function (see [1] in the JavaScript portion of the PoC) succeeds in freeing the fieldChild CPDField object. This leads to the this pointer in the recursive method to become a dangling pointer after the call in [dd]. The dangling this pointer is later dereferenced resulting in the crash.

This first vulnerability was patched in June 2021 by Adobe and assigned CVE-2021-28632.

CVE-2021-39840: Reversing Patch and Bypassing Locks

I was curious to see how Adobe patched CVE-2021-28632, so after the patch was released, I decided to look at the updated AcroForm.api.

Upon reversing the updated field locking code, I noticed an addition of a call to a method that locks the passed field’s immediate descendants:

With the added code, both fieldParent and fieldChild will be locked and the PoC for the first bug will fail in freeing fieldChild:

img04.jpg

While assessing the updated code and thinking, I arrived at a thought: since the locking code only additionally locks the immediate descendants of the field, what if the field has a non-immediate descendant?... a grandchild field! I quickly modified the PoC for CVE-2021-28632 to the following:

PDF portion (important parts only):

JavaScript portion:

And then loaded the updated PoC in Adobe Reader under a debugger, hit go... and crash!

The patch was bypassed, and Adobe Reader crashed at the same location in the previously discussed recursive method where the use-after-free originally occurred.

Upon further analysis, I confirmed that the illustration below was the state of the field locks when the recursive method was called. Notice that fieldGrandChild is unlocked, and therefore, can be freed:

img05.jpg

The recursive CPDField method started with the this pointer pointing to fieldParent, and then called itself with the this pointer pointing to fieldChild, and then called itself again with the this pointer pointing to fieldGrandChild. Since fieldGrandChild has an attached widget, the JavaScript callback() function that frees fieldGrandChild was executed, effectively making the this pointer a dangling pointer.

This second vulnerability was patched in September 2021 by Adobe and assigned CVE-2021-39840.

Controlling Field Objects

Control of the freed CPDField object is straightforward via JavaScript: after the CPDField object is freed via the removeField() call, the JavaScript code can spray the heap with similarly sized data or an object to replace the contents of the freed CPDField object.

When I submitted my reports to ZDI, I included a second PoC that demonstrates full control of the CPDField object and then dereferences a controlled, virtual function table pointer:

Conclusion

Implementation of object trees, particularly those in applications where the objects can be controlled and destroyed arbitrarily, is prone to use-after-free vulnerabilities. For developers, special attention must be made to the implementation of object reference tracking and object locking. For vulnerability researchers, they represent opportunities for uncovering interesting vulnerabilities.


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

CVE-2021-28632 & CVE-2021-39840: Bypassing Locks in Adobe Reader

❌
❌