Wednesday, January 20, 2010

The Acrobat JavaScript Blacklist Framework

Adobe recently announced and released the Adobe Reader and Acrobat JavaScript Blacklist Framework. I've had a little bit of time to play with it and would just like to share my thoughts.
First of all, I am very pleased with this new blacklisting feature. Until now, when we knew about 0-day being actively exploited in the wild using JavaScript in some manner, we would just turn off JavaScript in Adobe products (Reader, Acrobat, etc...) all together. Personally, I could live without having JavaScript in my documents, but that's a totally different discussion. I understand why some people might want that feature for their PDF documents and why for them at least, turning JavaScript completely off would not be an option. So let's say, for example, that you are running Adobe Reader 9.2.0 which is vulnerable to the DocMedia.newPlayer JavaScript API bug. You decide that it is in your best interest not to allow that method from ever executing. How would you go about blocking that? The official document put out by Adobe says: the "JavaScript Blacklist can be in two locations" on a 32-bit Windows system:
- HKLM\SOFTWARE\Adobe\<product>\<version>\JavaScriptPerms\tBlackListand- HKLM\SOFTWARE\Policies\Adobe\<product>\<version>\FeatureLockDown\cJavaScriptPerms\tBlackList
The first key is "modified by Acrobat and Adobe Reader patches whenever an API is deemed vulnerable" (this feature is currently in testing with a select group of beta testers). I decided to modify the second registry key. The manual configuration of this registry key was tricky since...it did not exist on my system with Adobe 9.2.0 installed. Thankfully it's not hard to create a registry key, and I did just that. Note that everything you type is case-sensitive when it comes to the registry keys related to the blacklist, from the value name to the values themselves. I spent a ridiculous amount of time trying to figure out why the blacklist wasn't working. It was because I had manually created a key called tBlacklist instead of tBlackList.
Now came the time to test the effectiveness of the blacklist. I entered the Javascript API function docmedia.newplayer in the registry as indicated in the document by Adobe. I typed in:
docmedia.newplayer
How to verify if I had typed it in correctly? There was obviously no confirmation that I had blacklisted docmedia.newplayer. I went through the options of Adobe Reader and nowhere was there a mention that docmedia.newplayer was blacklisted. What was I going to do to next? Wait until I received a PDF that had code to exploit the vulnerability to see if the blacklist worked as it was supposed to? I decided to create a simple, harmless PDF that invoked that function to see if the API call would get blocked. I could successfully open the file without the function being blocked. This time, I quickly pinpointed the reason for that: API functions are case-sensitive and entering docmedia.newplayer is not the same as entering DocMedia.newPlayer.
My concern was then that obfuscation techniques in Javascript could fool and circumvent the blacklist blocking. I tried basic evasions techniques:
  • obfuscation function names, function contents
  • lexical transformation
  • control transformation
  • data transformation (data structure)
There was no fooling Adobe Reader into executing the blocked function. It seems like Adobe Reader is hooking the function calls and is not going through the code trying to perform a string match. As of today, there isn't an official list of Adobe Javascript API functions to block, but I'd suggest adding the following to your blacklist just because these functions have been heavily exploited in the past several months: Util.printf (CVE-2008-2992) Collab.getIcon (CVE-2009-0927) Spell.customDictionaryOpen (CVE-2009-1493) Doc.syncAnnotScan (CVE-2009-2990) Doc.getAnnots (CVE-2009-1492) DocMedia.newPlayer (CVE-2009-4324) Very often, malware will escape Javascript code in order to avoid detection. The code is unescaped and evaluated at runtime. Therefore, these two function are commonly seen in malware and usually used one right after the other:
unescape()eval()
Unfortunately, these functions cannot be blacklisted through the Acrobat Javascript Blacklist Framework. Maybe it's just because they aren't, per se, Adobe Javascript API functions? We would love to be able to do that in the future, though. I also wanted to blacklist these two function because they have been exploited in the past:
app.CheckForUpdate (CVE-2008-2042)Collab.collectEmailInfo (CVE-2007-5659)
Turns out these are unpublicized Adobe Javascript functions and perhaps because of their nature, cannot be blocked/blacklisted. Finally, here's the blacklist that I propose, should you want to use it:
Collab.getIcon|DocMedia.newPlayer|Util.printf|Spell.customDictionaryOpen|Doc.syncAnnotScan|Doc.getAnnots
And here are simple harmless PDF files to test the implementation of your blacklist. Upon the functions being successfully blocked, you will see a yellow bar displaying "A JavaScript that this document uses is disabled for security reasons".
Add to Technorati Favorites Digg! This

3 comments:

Didier Stevens said...

I've a video of the framework in action here:
http://blog.didierstevens.com/2010/01/11/adobe-reader-javascript-blacklist-framework/

And I've been trying to redefine unescape via Folder Level JavaScript, but this doesn't work because of the different context.

If I find no other way, I'll do it with a patch in memory.

Pedram said...

Definitely a step in the right direction.

@DidierStevens: In memory patching is a great approach but eventually all JavaScript engines need a simple mechanism to blacklist the seemingly-only-used-by-malware API calls like eval() and unescape().

Jim Hebert said...

Great post!

The two API's you mention not successfully blacklisting, no longer exist in the 9.x release. So, rather than hit the blacklist, attempting to call those 2 functions simply errors out for lack of any such function. It looks from your article like you were testing with 9.x.

app.CheckForUpdate does not exist past version 7. Since version 7 does not have the blacklist feature, there's no platform where you can experiment with blocking that. :-)

Collab.collectEmailInfo OTOH you should be able to see the Blacklist working in the current release of 8.x. (Assuming of course you replicate your blacklist registry key at the appropriate path for where v8 will look.)

Thanks for giving the Blacklist stuff a hard look, and, for helping get the word out about it. We appreciate it!

--jim
(Jim Hebert, Adobe Secure Software Engineering)

PS One last note, about the 2 different places you can put things on the blacklist -- to me it comes down to what strategy you want to employ.

* If you just want to blacklist certain API's while there's an unfixed vulnerability floating around, but, you'd like the Updater to take care of un-blacklisting them for you at the time of installing the fix for that API, the location that the installer touches is the right choice. (As it says on http://kb2.adobe.com/cps/504/cpsid_50431.html -- "APIs are also removed from the blacklist whenever a fix for a vulnerability is provided by the current patch.")

If this is a person's strategy, then they would also probably not be as interested in permanently blacklisting the API's proposed at the bottom of the blog post, since fixes are out for all of those.

* If on the other hand you take a deeper theory of, if there was 1 vuln in this API, there could always be more, and, it's useless attack surface in my environment, so, let's permanently disable it, then the other registry location makes sense. And, the list proposed at the end of the blog post would make sense for people approaching it in that way.

Thanks again!