 Welcome to the early morning shift. Thanks, everybody, for showing up. For the half of you that are not hungover, I hope you enjoy the talk. For the half of you that are hungover, we're going to try to talk really, really softly so we don't hurt your head. This is abusing Adobe Reader's JavaScript APIs. We've got a lot to cover, so we're going to start going right away. A quick agenda of what we're going to be doing. We're going to introduce ourselves, talk about ourselves for about 45 minutes, and then we'll go over the content last five minutes. It'll be great. So we've been doing a lot of research in Adobe Reader over the last six months, trying to understand the attack surface. And what we're going to show you guys today is an overview of a part of the attack surface that most people do not know about and what you can do with it. We're going to talk about how you can go find these vulnerabilities yourselves. And then we're going to talk about how you put it all together, chain the various bugs that you need and the APIs that you need to gain remote code execution on Adobe Reader. So first we'll introduce ourselves. My name is Brian Gorenz. I'm the manager of vulnerability research inside of HP Security Research Organization. I run a program called the Zero Day Initiative, which is the world's largest and one of the oldest vendor agnostic bug bounty programs. We're entering our 10th year of buying vulnerabilities and buying exploits, and we spent over $10 million on bugs over these last years. We do a lot, I work with researchers around the world to procure vulnerabilities, root cause vulnerabilities, and send them to vendors to get them fixed. Sometimes they fix them, sometimes they don't, and we have a long history of making sure everybody's aware of the vulnerabilities that we purchase. I also organized the ever-popular Pondone hacking competition, which this last year gave away almost a million dollars for exploits against the hardest attack surfaces out there in the industry. We had one individual win $250,000 for a set of three exploits this year. I got to work with Jayzl and Abdul back here, along with several members of my team working on the Adobe Research Project that we were doing, and I'll let them introduce themselves. Hello. I'm Abdul. I'm a security researcher working for the zero-day initiative program. Been working for the ZDI for a little bit more than three years. I do a lot of food cause analysis, bug hunting, and exploit development. And recently I have been operating Reader in a regime of high memory pressure. Jayzl. I'm Jayzl, and I prefer to go by wandering glitch. I also work at ZDI, spend a fair amount of time on root-causing vulnerabilities, and then using what I learned to augment my own vulnerability discovery and exploit development. And I use Python assembly to prevent people from operating in regimes of high memory pressure. In case that doesn't make any sense, you should check out the ZDI Black Hat talk. Yes, we've done a lot of research over the past year as well in Internet Explorer, so that's a good paper to read. So we also do a lot of research, and you can see here on the slides some of that research that we've done. These are all of the bugs we've discovered in Adobe Reader since we started this research back in December 2014. Like I said, we do a lot of internal research. We started researching it back about six, seven months ago just to kind of get an understanding of how it worked. We've discovered what, it's about 91 vulnerabilities. In fact, we found, or at least Abdul found one on the plane. So we'll be submitting that. True story, true story. It really covers a whole spectrum of vulnerabilities that exist in the product itself. But the majorities of these CVEs and ZDI cans that you see on the slide are what we call JavaScript API restriction bypasses. So we'll kind of go into detail about what that is and how they occur and what you can do with them. So before we get started, we kind of want to call out some prior research that if you are going to spend a lot of time looking at JavaScript APIs and what you can do with them, we recommend. First is a set of research done by Molnar back in 2014. And he was really the first researcher to highlight the issue of the JavaScript restriction bypasses. And he kind of goes into detail about how all of it works. And he provides you a proof of concept that will allow you to bypass the restrictions that we'll talk about. And then disclose information on a box. So he could read files off of a computer and send them out to a server using this restriction bypass. And it really is required reading, in my opinion, to get started in this research. And hopefully our paper will also be required reading when it's done. There was also a presentation released by MWR Labs where they asked the question, why bother basically auditing popular software? And that's a good question. Most of the researchers out there kind of are scared to go after some of these bigger pieces of software thinking that all the low hanging fruit is gone. But as you can see from the previous slide, you can find a lot of bugs if you start looking at the software and kind of reading the research that's out there. And they kind of provided a really nice overview of the attack surface and all the attack vectors that are available. And Adobe Reader also highlighted the JavaScript restriction bypass bugs. So this research, like I said, started in December 2014. And the reason we started because honestly we were not getting a lot of Adobe Reader bugs and we knew that they were being used. So we wanted to kind of get a better understanding of what existed in this product and how it could be leveraged. And we basically hit every type of bug that, you know, every, well, probably every CWE that exists, right? We took a varied approach when doing this auditing. First we started out writing a bunch of fuzzers, trying to find memory corruption bugs used after freeze. We followed that up with binary analysis of the shared memory sections. We really released a blog recently about a privilege escalation that existed in the shared memory region. Then we did some code analysis on the JavaScript APIs that you'll see in a second. And we kind of trained each other internally trying to find as many bugs as possible with the main goal of trying to kill off as much as possible. Because we do purchase bugs and so, you know, the more that we kill, the better it is for us, money-wise. But, you know, internal discoveries we found basically every type. Use after freeze memory leaks or, yeah, memory leaks use after freeze privilege escalations, logic bugs, sandbox, byspaces, you name it, we found it. So we're specifically looking at the JavaScript APIs today which offer a rich set of functionality for document authors. These APIs allow you to process forms, control multimedia events, do communication with databases basically all there to give end users really complex, really a lot of options to make complex documents. But it's also a perfect avenue for attackers. If they think outside of the box, you're able to go, you know, kind of leverage these weaknesses within these APIs to do a lot of really interesting stuff. Now, there are mitigations that are built into the APIs and we're going to talk about those right now. It's this idea of privileged versus non-privileged methods. Now, some of the APIs that exists have security restrictions on them. And they can only be executed in what's called a privileged context. So what exactly is a privileged context? Well, a privileged context is really three points within Adobe Reader. One is when you're executing at the console, one, which you'll see a picture of the console later in the slides, then there's the batch processing, then there's during application and initialization events. And if you're trusting the document certificate is when you can actually use these privileged and security restricted APIs. For example, a non-privileged API would be mouseup events, mousedown events and things like that. Things that can be processed within the dock context. An example of a privileged API or a security restricted API is what you see on the slide, which is launch URL. This is not supposed to be executed from the dock context and only be executed when you're doing some sort of automation. If you try to execute a security restricted API from the dock context, you're going to get a security warning like you see on the screen. And you'll see that actually in action shortly when we try to execute one of these APIs from the dock context. So it will pop up to the user and if you're an exporter you probably don't want that to happen. You want everything to happen in the background without people knowing about it. So you want to kind of remove that obstacle from your exploit. There's also the idea of trusted functions. And this is where you're trying to execute privileged functionality from a non-privileged context. Well, why would you want to do that? Well, in certain cases you need those privileged functions for your workflow, right? So you need to launch a URL for some batch for some reason during your batch processing. And so you do this using what's called a trusted function or app.trusted function. And you can see it on the slide there. Hopefully you guys can see it in the back. That AN verify comments is actually a trusted function. And in this function you're going to leverage the privileged APIs. There's this idea of a code block where you've got app begin-priv and app end-priv. And in between those two calls you can actually execute these privileged APIs. And so you can see here on the slide, app.alert is executing in a privileged context and we're going to use this later on when we're actually looking for privilege escalation. But not this exact one, but that idea. There's also the idea of a folder level scripts. Now folder level scripts are available to end users for when they want to use, when they want to use them for automation purposes and they want to use those trusted functions and leverage those privileged APIs. And so these are available in Adobe Reader and you can actually put a set of JavaScript in the JavaScript folder. As you can see on the screen we kind of show it. And in that folder you're going to put your folder level scripts and they'll be available to you in the dot context when Adobe Reader is loaded. And in there you can actually implement trusted functions and use those privileged APIs. Luckily for us, Adobe provides us a set of JavaScript APIs and you can see them on the slide. It's the JS byte code win.bin. And inside of there is a set of APIs that do use these trusted functions. And this will be loaded up into Adobe Reader at the inside root and exposed to the doc when the document is opened. So what you see here is an example of what that code looks like. So you can actually, that JS byte code win.bin is actually compiled SpiderMonkey XDR byte code. And one of the best parts about Molnar's research back in the day was that he actually provided us a decompiler. So you can actually decompile this byte code and go get the code off of that GitHub location and that's kind of where you want to start. You're going to decompile that byte code and you're going to find interesting trusted functions in there. And so when it's actually decompiled, it's pretty messy so you want to pass it through a beautifying process so that you can actually read the code. And you can see here is an example of the color convert function that's inside of there. There's about 27,000 lines of JavaScript within this bin. And this is your place to start auditing. So if we think about this for a second and we are going to be auditing this code and how are we going to actually leverage an attack, we need to kind of, we want to be able to execute some sort of privileged API from within the .context. You want to be able to reach these functions that Adobe considers security restricted just from within the document. This is not something that they normally allow. And so what we're going to do now with in a couple seconds here is we're going to show you how to go through this code and find these vulnerabilities and chain them together so that you can do some interesting things. So before we look at how we manage to find these, you first have to understand that there are a few places in JavaScript as part of the language itself that will implicitly call functions or at least potentially implicitly call functions. So if we look at this snippet of code, this function funk, it takes an argument called argument. And there are three places here where we are potentially unexpectedly calling a function. The first is in the if conditional, if argument dot attribute. And that can potentially either retrieve that property or could execute a getter or accessor method if one is defined. The second is within the called app.alert, you're adding arguments to a string. And so if argument is not a string, then two string has to be called on it. And then the last one is right after the if. And that's where we're setting a value on argument dot attribute. And in that case, we'd be calling, we'd be either replacing that property or calling the setter or mutator method. And this is, this will be vital in a couple of slides. And the main thing to note here is that we can use this to replace properties or just execute code within a potentially different context. For the next couple of slides, we essentially have the setup in the last two lines where we have some object that has some attributes set to a value. Now that's done before we ever get any control and that's essentially out of our hands. What we do have control over is the empty line under it as well as the call to the function. And so the next two slides will basically be replacing that empty line. So the first is define getter and define setter with two underscores before and after them. The way both of these work is you call this function on any object and give it a, give it two arguments. The first is the property name and the second is a function that will actually return the value. In define getter's case, you can use this to overload and essentially replace an attribute that may already exist even if that attribute doesn't let you overwrite it. You can also execute other functions or do anything at this point. After that, there's define setter and as you can imagine, this is the mutator method. In this case, you can do conversions on the input argument or just deny access to ever change that value. The other way, because this is based on spider monkey, is to use the proto attribute. Unlike browsers which have prototype, this only has proto with two underscores before and after. And in this case, all you're doing is creating a dictionary with updated keys and updated values and then setting proto to the original object such that when anything tries to access a preexisting attribute, it'll fall through and still access it. But when it tries to access the properties you care about, it'll get your special value. So as far as getting system level execution, and by system level, I mean within the root context, which is a more privileged context, you have to somehow execute arbitrary JavaScript within, well, outside your context. The easiest way to do that is to grep for eval. And as you can see, there are a bunch of results. That's actually less readable than I was hoping. But essentially you have calls to eval on potentially untrusted input. The first one there is a call to eval on long entry dot char at. That's the one we'll be focusing on in a couple of slides. And long entry is supplied to that function. And char at is a function that, as the name implies, returns a character. So what we'll do is overwrite or overload that and instead replace it with a custom function so that we can execute arbitrary code there. Once we've done that, we then have to look for ways of escalating privileges within JavaScript. And we do that by grepping for app.beginpriv. The key thing to note here is that we can't just look for app.beginpriv for every match we find. We then have to look to make sure it's within a function that is being sent to app.trusted function. Because if it's not being called from a trusted function, then the user will still get prompted. Within app.beginpriv, there'll be a subsequent call to app.enpriv. And somewhere in between there, we're going to look for some sort of method invocation that we can overload. So here's an example of where we get the system level eval. And it's in AF par state. You can see the second argument is long entry. And all the way at the bottom, we can see that call to eval. So what we can do is just set up a custom hash with a char app that will execute the bulk of the JavaScript payload. Here we are going to replace a, we have a place we can replace a property with a privilege function. This is cb shared review security dialogue. And it's a trusted function, as you can see, when it's being set. And at the very second and last line, you can see the call to beginpriv. And then the last line is a call to collab.is.center URL. So what we can do is replace collab.is.center URL property with app.launch.url. And then since c source URL is a trusted, there is a input argument, it'll just call it directly and we'll be able to escalate from there. So altogether, the first thing we do is set up a system level eval and issue the bulk of our payload. Within the bulk of our payload, we'll replace that call to is.center URL so that we can call app.launch.url or any privileged call. And then we'll trigger it. And here's what it looks like. This is CVE 2015, 3073. Easiest way is probably to look at the bottom. So we start off by calling AF par state. That first argument can be ignored. That's just to hit the vulnerable code. The interesting thing being that we're sending the O object four times. And if you look a couple lines earlier, you can see that we are setting O to be, to have a char attribute where that function will return the exploit function and then call it. The exploit function itself is defining a getter to replace collab within the system level context. And then it's calling CVE shared reviews security dialogue to trigger it. So here we're going to see the normal behavior. This is what it looks like in Adobe reader DC when it's patched. And you can see that all we're doing within the PDF is a call to app.launch.url, Google.com. And it's prompting the user as it's supposed to do. Whereas when we chain everything together, we end up launching, in this case, four browsers. The reason it's four is because we're passing that O argument four times to the function. And that was a privilege execution. So here in the vulnerable version, this is what the JavaScript debugger looks like. It's a little weird to read. Basically the first line in every other line after that is where we are executing JavaScript. So we're executing collab and it's telling us it's a collab object. On the third line, we're replacing collab and setting it to app. And the fifth line is saying let's access collab again and you can see that it's being returned as the app object. So we're replacing it and that's persisting. In Adobe Reader DC after the patch, we're doing the exact same thing. Only now that last line has changed. It is no longer persisting. It's staying as collab because they've blocked our ability to replace that object. So all in all, in order to execute privileged API, we get execution within the system level context by finding those evals. And then within the block that we're going to execute in that eval, we replace a property such that we can call some privileged API. We use launch URL here. But Abdul is about to go over another set that works out better for full RCE. All right. So this whole bypass, JS bypass stuff is awesome. So let's go back to Molaern's bug. Sorry. Can you hear me now? All right. So going back to Molaern's bug. So in their advisory, Adobe stated that this bug basically leads to information disclosure. And that's cool. So we knew that we were able to leak information out of this bug, extract information, read files, and then send it to whatever server we want. But we still needed to take this to the next level if it was possible. So you guys can imagine if you were able to actually get RCE out of this stuff, like it's just logical JavaScript stuff, no memory corruption. It's just freaking awesome. So the main challenge here was to gain RCE through the JavaScript, create JavaScript that whatever Jayzl discussed. But in order to achieve this, we have to find the right APIs that would allow us to actually do interesting stuff. So it was clear for us that we needed a way to dump a file on disk. And we needed to do this through the JavaScript API. So you know, I started doing like going through the JavaScript API reference that Adobe provided. And started like looking for interesting APIs. And that was a big fail. It was a big fail because most of the documented APIs were really hardened. So there were a lot of restrictions on file types, file contents, and stuff like that. So eventually I was like, screw this, I'm going to get back to memory corruption and fuzzing. And that's it. So one day I decided to write a fuzz module for the collab object. So being a little lazy as I am, I went back to the JavaScript reference API. And then I had a look at the collab object. Basically there, as you guys can see the screenshot, there were like three methods documented in that API reference. So I was like, okay, this is going to be easy. I can implement a fuzz module for this. But I was kind of more curious about the collab object. So I went in console inside Adobe reader and decided to dump all the methods, the actual methods that were inside the collab. And this is what I found. So basically there were like 128 methods. So if we do the math, it's like 125 undocumented methods. So, you know, I have no idea, seriously Adobe. So with 125 undocumented functions, we decided to have a closer look at like the right. So while I was going through the list of functions, I noticed that there are like some interesting ones, which are highlighted right there, which I would later reference as the URI family. So I wasn't like super convinced that this is that the whole, these APIs were not really explored by anyone. So I ran a search on Google and I got nothing, no information, nothing like no documentation whatsoever, no description, nothing. All I got are these two hits. And basically these just describe, they just like list the functions or the methods inside collab. And one of these hits where I report by the Australian Ministry of Defense. So you guys can figure. Right. So I'm going to go over these or the interesting APIs. Just describe them briefly and stuff. So the first one is URI put data. Basically it takes two arguments, the C file URI and the OData. So basically this function, what it does is it takes a data object and it writes it to the path that you supply it to. The delete folder, as the name implies, it takes one argument with the path and deletes that folder that you give it as the path. Create folder, same thing, takes one argument which is the path and just creates a folder at that path. URI enumerate files, it takes a path as well and basically just lists everything inside that path that you give it. And finally the URI delete file, as the name implies, it doesn't create coffee, basically it just takes a path and just like deletes the file. So you guys can see that Adobe provided like such an awesome set of API that you can do whatever you guys want. So internally we talked about it as like some kind of government agency back door, whatever. Right, so just a quick overview of the whole URI stuff. Basically these APIs are used for collaboration. Collaboration is a feature provided by Adobe that would do like, that would allow us to do some shared reviews and stuff like that. It's worth noting that delete folder, delete file, put data and create folder are all privileged APIs. So you guys cannot exclude them from the normal doc context. So they have to be chained by one of the bypasses that Jason discussed. The only one that's not privileged is URI enumerate files. So you guys can run it from the doc context. Right, so these functions have one thing in common which is the first argument which is the path. Basically the path should be a UNC path and the UNC path should be of a specific format, basically SMB or file, SMB slash slash or file slash slash. So these APIs are not perfect. Basically they fail at sanitizing the path and the old school trick of SMB slash slash slash slash C dollar sign, whatever works like a champ. URI put data has two major fails. The first one is it doesn't check the file type that it's going to write to and it doesn't check the file for sure. And the next big fail is that it doesn't really check the contents of the data object. So if you guys can provide PE file data inside the data object and write it to an EXE file, it doesn't complain. So basically you guys have an ideal API that will allow you to write whatever you want, whatever file type, whatever you want. Thank you, Adobe. All right, so what do we have here so far? So we know that our problem of finding an API that would allow us to dump a file on disk is solved. But if we have a closer look at URI put data, specifically the second argument which is the data object, that's an interesting piece of information. So basically being the lazy ass I am just to go back to documentation just to understand how the data object looks like or how to actually get a reference of a data object or anything like that. And I found nothing as usual. But during my experiments I noticed that if you supply a stream object instead of that data object, then URI put data would not complain. Which is awesome. Because we can create stream objects in multiple ways. So you guys can see in my screenshot right there. I basically created a stream object out of a string and then supplied it as the second argument for URI put data. And basically it showed it to whatever SMB path I gave it. Which is cool. All right. So what we know as well is that we can attach files to PDF documents. We can attach whatever files we want, whatever file types and stuff like that. And we also know that we can extract the file contents in and store them in a stream object using documented APIs as well. So what we should do is that we should change the URI put data with one of the bypasses, of course, supplying a stream object to it and then we can write whatever we want on this. So then what? We know we can dump files and stuff. But how can we get RCE out of this? So basically there are two ways to get RCE. So the first way, I call it the Chalky way. So basically because Chalky is obsessed with log off, log ends, payloads. So basically we can just like write our file to the startup folder and then just wait for a log off and log in. So the second way, which is my favorite way, and then of course the cleaner way, which is writing at the LL and forcing Acrobat to load it right away. And that is possible in specific scenarios where you load a PDF in a specific way. Internally we call this the Moliniawi way. Basically Moliniawi is one of our colleagues, so he's obsessed with clean exploits. So basically we went with the Moliniawi way. And by the way, Ponto in 2015 was a blast. All right, so this table shows the vulnerable versions of Reader and Acrobat Pro. So basically Reader and Reader DC are vulnerable in all versions, but there are limited stuff that we can do on Windows OS due to the sandbox technology that they have. So it limits our ability to write files on disk and stuff like that, but we can still exploit Mac or SX with no problem. Acrobat Pro and Acrobat Pro DC is vulnerable on all versions because it doesn't have a sandbox. So you guys might be asking question why we didn't enable like specific version numbers and stuff. Well, it's because the first time we tested this it was version 11.0.10 and then Adobe patched it and then we broke the patch and then Adobe patched it again and then Adobe and then we broke the patch again and it's still not patched like in process. So everything's vulnerable basically. All right, so let's put this all together. Now we know that Adobe Acrobat Pro doesn't have a sandbox, so it's the easiest target to exploit. So basically our exploit, so these are the steps for the exploit basically just attach our payload to the PDF and then we should write a JavaScript code that basically executes when the document opens. So this JavaScript code should be composed of the following, a code that extracts the contents of the payload and saves it in a stream object. Then we have to bypass the GS privileges to execute URI put data and then dump the DLL and then have Acrobat basically load that DLL. So I have a demo here that demonstrates this exploit which runs on Windows 8.1. It exploits Acrobat Pro 11.0.10 and the exploit basically dumps the DLL and have Acrobat Pro load that DLL and just pop calc. Of course. So it dumped the DLL, you guys cannot see it, but there you go. So it's not over yet. So basically we paid a visit to Reader on MacOS X and this is the latest version of Reader on MacOS X and pops calc. As you guys can see, this is the latest. Patched. There you go. And by the way, this works on 64 bit too. All right. So I'm going to hand it to Brian so he can just wrap this up. Thank you very much. So much taller than I am. All right. So in conclusion, I mean really what we wanted to start off with is kind of an idea of, you know, go after an application that we hadn't really been getting a lot of submissions in. And we did this and we looked at prior research. We looked at the occasional submission that would come in. And our goal was to take that to the next level. Like the existing research that existed at the time would only allow you to disclose information on a server. But we wanted to take that to make sure that we could get remote code execution so that people would treat these vulnerabilities with the criticality that they are. And so what we did, we also wanted to kind of challenge ourselves. We are actually mostly memory corruption exploiters and reverse engineers looking for memory corruption bugs and use after freeze. So we wanted to do this in a way where there would be no memory corruption. We wanted to use logic errors or logic issues inside of an application so that the exploits would basically run clean. You saw in the videos that were on the slides that there was no crashing at all. The things ran really smoothly, really cleanly. And shows just kind of the power of these type of exploits. So our plan of attack was to obtain an arbitrary eval by using the JavaScript overloading and redefinition capabilities. We wanted to chain that eval with a privilege escalation through these app.trusted functions. Then we wanted to leverage the undocumented APIs that existed in Adobe Reader to execute our malicious code. And we were able to do all three of these things to actually produce some pretty interesting stuff. Then we wanted to profit from that. And well, because we're a bug bounty program and we can't sell to ourselves, we decided to submit it to DEF CON so that the corporation would pay for us to come to Vegas. And that kind of thing. But yeah, so we wanted to share with the community we are a bug bounty program. And so if you decide to take this research and look inside some of the inner bits of Adobe Reader and you do find vulnerabilities, there are quite a few in there. We do purchases and we do pay quite a bit of money for them. So if you're interested, zerodayinitiative.com will submit the programs. These individuals on the stage and a couple over there will do all the analysis. So send them as much bugs as possible so that they have to do a lot of work. Outside of that, we are celebrating our 10-year anniversary as a program. And so up on the stage, we have these challenge coins. They're actually our dual use technology. They are a challenge coin. And they are also a bottle opener. So get them before the Wasnar takes them away. For you exploiters out there, you get that job. All right. Thank you very much. I hope you enjoyed the presentation. We'll be taking questions and come on up. We have a bunch of these bottle openers to give out and coins. And I hope you guys have a good DEF CON.