ZDI-18-1372 – The Elegant Bypass

December 21, 2018 | Abdul-Aziz Hariri

In October, I blogged about a new attack surface that I found a while ago in Adobe Reader DC. I was able to reach that attack surface through the Catalog plugin, which exposed a nice set of JavaScript APIs. Adobe responded to the bugs I submitted not only by patching the parsing bugs, but also by disabling the Catalog JavaScript API that triggered the file format parsing. 

At that point, the parsing code was still enabled in Adobe Reader, but triggering the parsing was not as straight forward as it previously was. I was skeptical whether or not bugs in the indexing parser were worth researching anymore. I even did a quick look and detailed all the possibilities that can be used to trigger the parsing. My sad end result was that there is no way to parse the indexing files from JavaScript with normal Doc object privileges. The only way to accomplish that is by executing a privileged API, thus making the whole attack surface useless. I didn’t immediately start reviving my 2015 JavaScript API bypass research. However, if I thought that 3 years later I’d be able to bypass the JavaScript API restrictions like I did a couple of weeks ago, then I’m sure that I’d have taken the Indexing issue more seriously.

Regardless, when the Catalog bugs went public, Sebastian Apelt (@bitshifter123) reached out and mentioned that he was also researching the indexing attack surface. Interestingly, Sebastian approached the attack surface from the Search plugin rather than the Catalog plugin. What was fascinating about Sebastian’s research is figuring out a way to bypass the restrictions Adobe thought they had in place to prevent parsing the Indexing files from JavaScript.

The Bypass

In the Adobe Acrobat JavaScript Reference , the “query” method of the “search” object is marked with an “S” for security restricted. Basically, there are four ways to call this method from JavaScript:

1.     search.query(<word>)
2.     search.query(<word>, "Index", <idx-path>)
3.     search.query(<word>, "Folder", <idx-path>)
4.     search.query(<word>, "ActiveDoc")

Methods 2 and 3 are security restricted, as mentioned in the JS API documentation. Thus, the functionality to load indexes from a certain path (including UNC paths) can’t be triggered without elevated privileges.

Method 1 can be executed without elevated permissions, though the parsing of any embedded search index does not happen! This was likely a design decision to not open up the Onix search API to potentially malicious embedded indexes.

However, using method 4 with the parameter “ActiveDoc”, Acrobat Reader DC and Acrobat DC first save the embedded index to the folder C:\Users\<USER>\AppData\LocalLow\Adobe\Acrobat\DC\Search, and then start parsing it! Thus, using the “ActiveDoc” parameter, an attacker gets the opportunity to hit the whole Onix parsing engine.

The proof of concept file Poc.pdf can be used to confirm the described behavior. It is a PDF with an embedded search index. The following JavaScript snippet within that document executes all 4 possible search.query method calls mentioned above:

The following steps should be taken to confirm hitting the Onix parsing engine:

1.     Delete all files from folder C:\Users\<USER>\AppData\LocalLow\Adobe\Acrobat\DC\Search to avoid loading a cached index file
2.     Open Acrobat Reader DC
3.     Attach debugger and set a (deferred) breakpoint on onix32!ixCreateIndexManager (This method gets called first whenever idx-file parsing starts)
4.     Now open poc.pdf
a.     You will get 4 alerts before each of the possible search.query method calls
b.     You will NOT hit onix32!ixCreateIndexManager calling search.query with method 1
c.     You will NOT hit onix32!ixCreateIndexManager calling search.query with methods 2 and 3 (which will throw exceptions)
d.     But you will hit onix32!ixCreateIndexManager when calling search.query with method 4! Also, you will notice that during the 4th call the embedded index file(s) will be written to the search folder

The poc will force the search dialog to popup and kick off a search in the PDF, thus triggering the parsing code that was not hittable before.

Conclusion

It’s amazing how much individual research can expose. Even the vendor thought that the attack surface was mitigated. Anyway, Adobe finally figured out a scientific way to fix the bugs in this attack surface - killing the whole parsing code. Yup, they basically ended up disabling the parsing code. While this change likely impacts performance, and certainly impacts functionality, sometimes the best way to “fix” a security problem is simply to remove the offending feature. That takes the term “attack surface reduction” to a whole new level.

Until next time. 

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