Onix: Finding Pokémon in your Acrobat (Revealing a new attack surface)October 02, 2018 | Abdul-Aziz Hariri
Finding new targets to audit is always fun. At the same time, it can be a challenging task –especially if we’re going to start auditing the target from scratch. It can also be quite tedious and time consuming. While going through the ups and downs of auditing a new target, I usually take some time off to check the status of my old buddies. And by old buddies I mean targets that I’m already familiar with. One of the targets that I always go back to and one that has a sweet spot in my heart is Adobe Acrobat Pro DC. The fact that it has so many features integrated, from image to document parsing and a lot more, makes it a great target.
Every year in preparation for Pwn2Own in March, I usually fly to Austin the week before the event to help with the preparation and setup. While waiting for the laptops to finish setup, I decided to have another look at Adobe Acrobat Pro DC, but this time I decided to look at new attack surfaces – ones that I’ve never touched or audited.
Everyone has their own approaches to finding new attack surfaces in a given target. That day I decided to keep it simple: investigate and audit the oldest DLLs. And that’s what I did. I went and sorted the DLL’s in Acrobat’s directory by date and found this gem:
Great, so far so good – but how is this library used? And what’s the attack surface there?
Onix32 is used to create index files. These index files are complex proprietary binary file formats. Adobe uses the API exposed by Onix32 to do things like create indexes, open indexes, search, etc.
The biggest question is this: How do these index files get parsed inside Adobe? I started looking at different plugins that Acrobat has and stumbled across
Catalog.api. The great thing about the Catalog object is that it exposes a JS API that we can interact with from inside a PDF:
…great? How does this even relate to Onix32? Well, on to some RE…
One of the functions the Catalog plugin is responsible for is opening indexes. It does that using the Onix32 API
You can even create sample index files for fuzzing purposes from the GUI interface, which is what I did initially.
Most of the index handling done from inside Catalog happens from inside one function I called
Armed with all this juicy information, I started thinking of ways to find vulnerabilities. I figured out that there are two things that can be done here:
1 - Audit the
Onix32.dll API usage inside
Catalog.api for vulnerabilities
2 - Write a wrapper for
Onix32.dll and fuzz the API from the DLL directly
Going after API usage vulnerabilities inside
Catalog.api at this point is trivial, given the amount of reversing done. In the end, I was able to find these remote code execution and info disclosure vulnerabilities: ZDI-18-958, ZDI-18-599, and ZDI-18-467.
We can also approach it differently from a fuzzing perspective by mimicking the way Catalog used the API’s. That by itself should not be a problem, because LexTek is generous enough to provide us with API documentation and even data types they’ve used:
The API reference can be found here.
Writing a wrapper for Onix32.dll to fuzz the API from the DLL should not be a problem at this point either, since we know how the API’s can be used, thanks to the help of LexTek’s documentation and code examples. I’ll leave this as an exercise for the readers. In the meanwhile, here’s a teaser of how fast it is to fuzz the DLL directly is:
Anyway, the vulnerability was in one of the Onix32.dll API’s, specifically in calling
ixStartRetrievalSession when parsing a malformed index file. While the end result is an untrusted pointer dereference, the bug in its nature is quite unique.
The vulnerability is basically an overflow of the
IndexManagerT object. Using a malformed crafted index file, we can overflow the
IndexManagerT object until we overwrite a
FileClassT pointer, which would later be dereferenced from inside
So how did I control this bug? In a ridiculous way. The value that we were overflowing with seems to be a counter of some sort that is fetched by calculating the number of certain objects. Luckily, I was able to increase this counter in a unique way – by replicating objects inside the index file:
The end result was as good as a Shawarma sandwich:
I thought we knew each other quite well, Acrobat. It turns out you’re always hiding stuff. It’s quite amazing how much you can find in targets that you thought you knew quite well. Finding new attack surfaces in an application is a bittersweet mix of pleasure and challenge at the same time. There are many more details about this research that we’re planning on releasing in the future (along with Sebastian) and possibly presenting the material somewhere. We’ve only scratched the surface here, and it seems as big as the entire Johto region. As always, kudos to Sebastian Apelt for taking things to the next level and pumping more bugs!
Pokémon © 2002-2018 Pokémon. © 1995-2018 Nintendo/Creatures Inc./GAME FREAK inc. TM, ® and Pokémon character names are trademarks of Nintendo.