 give uh, Ben and Cody another great round of applause and congratulations for making it. Well hi, uh, my name is Ben, I also have Cody here with me, uh, I'll let him do a little bit of introduction and say, uh, my head of hacker operations at Hacker One, um, somewhere in the top 20 on Hacker One, I don't know how, but somewhere in there. I found some cool bugs on Snapchat, Yahoo, DoD, Airbnb, um, we'll definitely talk about Snapchat in a little bit. I also do a lot of social media stuff on YouTube, Twitter, Twitch, whatever, other social media, it's all the same at Nahomsec, and I'll let Cody introduce himself before we get started. Yeah, so my name is Cody Brochus, I am the head of hacker education at Hacker One, um, I am, unlike Ben, not in the top 20 on Hacker One, uh, but top 400 doesn't have the same ring to it. Um, I, uh, talked to BlackHat back in 2012 about hacking hotel locks, I worked on hacking the Nintendo Switch, hacked iTunes, bunch of other stuff, um, my focus is all in reversing, but today we're talking about web stuff, uh, and I am available on Twitter at Dakin. He's also a unicorn and I have proof for this in our talk, so I'll shorten a sec. So, uh, again we're gonna talk about SSRF, um, this is the long description on OWASP, um, server side request forgery, you abuse functionality, you can update resources, read them, uh, tons of stuff you can do. If you're on the cloud like AWS, you can hit the cloud metadata, pull some keys. So TLDR, you're just making a request from the target host, uh, and in some cases you can run stuff like JavaScript server side. Um, if you're not familiar with the cloud metadata stuff, um, that IP address is wrong, um, don't go to it, it's supposed to be 169, uh, 254, 169, 254, um, but if you go there, there's a lot of good information, um, it gives you the host name, the internal IP address, external IP address, uh, some other information, but the best part of it is it also could give you access to the keys and the secret keys to the kingdom. Um, so once you get to that, it's pretty much game over and more than likely you can escalating, start doing more stuff. There's basic examples, um, the best one is you go to a website, uh, they want you to fetch your avatar. Uh, you can do that from an external host. Uh, you give it a URL, it's going to fetch that image. Um, sometimes it looks like something like this. You go to the API. Um, the API makes a call, which is that URL. And, um, it's not always straightforward like this, but you can do stuff like the file wrapper and point it to a file, read the local file on that machine, you can use some other protocols, and you can also, uh, hit internal host obviously, um, which we'll show in a little bit. But it's not always this easy, there's always a, um, the step that you're going to think about that you're missing and all this. There's always some blocker, uh, some filtering maybe, uh, depending on what company you're going after. Uh, and then this talk, we're going to talk about some of the hurdles we came across and how we were able to bypass them. So there's also a lot of CVEs out there. Um, so I'm really, really good ones recently. Um, best, best example is Jira to this day, it's still vulnerable. This is from, uh, I believe this is Alyssa's, uh, blog on the DoD program. Uh, there was this close public on Hacker One. Uh, this came out in 2017 and it was still vulnerable two weeks ago on other companies that I was hacking on. Um, it's still out there. Um, perfect example of what I showed earlier. You pretty much are hitting an API. Um, this is, uh, icon dash URL and you give it a, you know, uh, webpage, external webpage at Google in this case and it fetches it for you and then you switch that to metadata, um, to, to, uh, fetch the internal host name and obviously it comes back and gives you that internal, um, host name. Pretty straightforward, pretty dangerous stuff. Um, but this is pretty old. Recently last year, uh, Orange, if you're here, shout out to you for this. Um, he did the same exact thing to Jenkins. So if you find a Jenkins instance on off, you hit this URL, you point it to the, uh, AWS or any cloud metadata and you can pull the keys. Uh, and this is straight from his blog. So if you want to look it up, just type in Jenkins, Orange, Sci, uh, SSRF and it will come up. So, pretty straightforward stuff. Um, nothing you have to really bypass or fight in order to get, um, you know, metadata or whatever you're looking for. But there are a lot of problems when that's not the case. So example, uh, the developers may have blocked access to the AWS metadata, IP address directly, um, but you can, you know, point your own domain, you can have your domain pointing to the metadata, you hit it with the API or whatever you're exploiting works. So that's solution one, um, sometimes it's only whitelisted to the target application. So if you're hacking on site.com, you can only use resources on site.com, but you want to SSRF that, you go find an open redirect and you use it against the application. So you use your own functionality against themselves. Also there is times that, uh, I want to say nine out of ten times SSRFs that we find and they're the fun ones or the most impactful ones is when you have no output where you can't see the answer to it. You can't see what the response is from the server, but it allows you to, uh, execute JavaScript server side, which we'll talk about a lot, um, eventually. So there are a lot of, uh, valuable assets out there for this whole PDF, uh, generation, uh, PDF exploitation to work. Uh, access on a target is always helpful, especially if there is a PDF generator on that page. So if you have XSS on this application on the right top corner says download PDF, print PDF, you hit that, it prints the PDF with an XSS embedded inside. And if you play around with it, you can also exploit it. So you can confirm it to see if you, it's, uh, actually rendering that, um, HTML or JavaScript server side by giving it something like a script document, right? One, two, three. If it works, writes one, two, three. Confirmation that it's there, uh, and you move onto the next phase. Uh, you can also, you know, do iframe image, uh, if it's pretty straightforward. If they let you do that, you can just do iframe, source equals to whatever you want to fetch. You don't even have to use JavaScript at that point. And there's also, uh, customization of your PDF generator. So if they allow you to customize a fonts, if they allow you to customize your, uh, headers, footer, whatever CSS is involved, you can also abuse that, uh, to get SSRF in some cases, uh, which we'll, which we'll talk about in a little bit. And always, uh, open redirects, don't burn them if you find them. You will always, you will regret burning an open redirect if you're not, uh, looking for SSRF. So if I find one, I'm not reporting it until I find the SSRF, just bunch them together and report it. So PDF generation process. Uh, I'll let Kodi explain this really quickly. Um, go ahead. So when you're talking about doing PDF generation, you have two really common ways of, uh, of approaching the problem. So you have headless browsers and kind of, uh, browserless HTML renders. Uh, so headless browsers are things like headless Chrome, which is exactly what it sounds like. It's Chrome that renders to an image or a PDF. Um, and then you have things like WKHTML to PDF, which is, again, exactly what it sounds like. It is WebKit with a PDF rendering back end. Um, and those are probably the most common ways that people do conversion to PDF these days. Generating PDFs directly is fraught with difficulty and you have to restyle everything. You know, if you have a custom style that you're doing through CSS and HTML, that's not gonna work in a PDF. So these converters allow you to get around that. So headless browsers are super common for that kind of thing. Um, and there are lots of wrapper libraries. Like if you're doing this in Python, Ruby, Java, C-sharp, whatever, there are libraries that will make that really easy. Um, and then there's the HTML renderer side where it's not actually a browser engine. Uh, there's no JavaScript support. Usually CSS support is limited. Like it'll be like CSS level one, maybe two. Um, they provide a really restricted environment where HTML is, um, is used, but only in so much as, you know, it's, um, it's, it's the layout of the page, not any, uh, any real functionality. So, Weezy print is a great example of this and we'll talk about, uh, some really interesting stuff with Weezy print and, uh, in a little bit. Um, so yeah, earlier I talked about getting XSS in a PDF, but we wanted to kind of show that process. It doesn't always have to be XSS, but it's just easier if you have JavaScript running, uh, in these PDF files. Uh, so what happens? You get XSS, um, any modern web application probably does this. Um, what you want to do is, you want to make sure, um, you have, you want to have confirmation, whatever, um, you're exploiting, you want to make sure that this is actually rendering this JavaScript HTML server side, and it's actually maybe reaching out to an external host, um, such as this one. So if I get an HTML injection in there, it shows that my HTML got rendered and put into the, uh, PDF. The next thing I do is I reach out to the server using HTML, something like maybe an iframe, an image source, an object, uh, something to embed a file inside of it. And as soon as it renders, it will hit your server where you're opening up an, uh, a port. And the thing, the important thing about this is, uh, the reason why you do this, you want to get a user agent. So the user agent is very helpful to figure out what you're going against. Um, in this case, we're going against, uh, some sort of, uh, browser, but in other cases it could be Weezy print, uh, it could be the PDF HTML kit, so there could be different things and based on that, the exploitation completely changes. So again, if you do, uh, cloud IP address, user data, a bunch of slashes, folders, paths to the API key or the secret keys, it spits this out and you have access to the AWS instance. Alright, I'm going to do this one again. Sure. So, simple is great and a lot of SSRFs are simple. They are not something that a lot of people still look for. Um, there are simple SSRFs that have been there for years that still haven't been found in popular programs. Um, but simple doesn't always work here. Um, when it comes to something like Headless Chrome, you're really going up against a browser running in the cloud. Like, there's, there's no two ways about it. You're going to run up against things like same origin policy, which the JavaScript engine actually ca-cares about. So, you know, we've talked a lot about this metadata service, 169, 254, etc. Um, you will not be able to access that if you're in Headless Chrome because same origin policy is going to block it. The same reason that Facebook can't go talk to your bank website without special communication and cores. So, same origin policy really shoots a lot of this in the foot. You know, you're, you're unable to, uh, to actually connect to the services that you care about, uh, whether that's the metadata service or some other internal service. Um, so we need to find interesting ways to, uh, to get around that. Um, additionally, we can't redirect. Uh, so, in the old days with, uh, WKHTML to PDF, um, you could actually just do a standard redirect and it would have some kind of time out. So it would spend, you know, 10 seconds rendering at max or whatever. And it would just wait until the final page is loaded. But with Headless Chrome, if you do a redirect, it says, oh, the page is finished loading, I'd better render what I've got now. Um, so we can't redirect over to another service. We have to figure out a way around all this. So let's say, uh, we're going against an app, against an application, um, there's no access available. This is something that, uh, we found by luck a little bit. Um, we go against an application, anything we put in XSS4 doesn't work. Um, someone already found all their cross-scripting roles, reported it, they've gotten fixed. Um, but we're allowed to customize CSS. You know, I can change the fonts, uh, the font type, size, the color background, whatever that is, right? Um, we can also end a style tag and get out of it and then start adding more HTML and go back to step one and ifaming things and, uh, fetching for stuff. So I don't know if you guys can see that. The first one is, uh, the burp, um, request that we got. It's for a font name. It says the font name and then at the end of it, there's a closing style tag. And when we generate the PDFs, you can see all of our other payloads were failing on the right side. But then somehow this one worked. We see that the remainder of the CSS which screams at us, okay, we have something on this PDF generator now and we can actually start putting HTML in there. And you go back and, uh, you change the payload to an external host. So I'm pointing this to my server and it comes back with a user agent Java. So we know we're going against a Java application in the back end. We start thinking of how to exploit it. But it doesn't have to be that hard. You can just give it an iframe after you close the style tag. It's supposed to be a closing style tag, iframe, and you hit the metadata and you get the keys. So it doesn't have to always be XSS. If you don't find them, the first thing I do is just go and look and see if I can actually customize this PDF. And if it does, I want to say 9 out of 10 times people forget about their style tags. And you can just close it out and, uh, start inserting, uh, injecting HTML or JavaScript. Weezy print makes hacking weezy. I'll let Cody explain this one. Um, this was a really fun one. Um, we sat on this, uh, this next vulnerability took us about three months to figure out. Uh, it took us a trip to New York for us to actually look at this in person and, uh, figure out how this whole weezy print thing works. So I'll let, uh, Cody explain this. Yeah, so Ben gets all the credit here for actually finding the underlying bug here. Um, I just can't stop once I see a puzzle. Um, so weezy print as I said earlier is, um, is really, really, really simple. Like it's maybe what, 4,000 lines of Python, something like that. Um, it doesn't run scripts. It will not load, uh, will not load iframes. Um, it'll load images but only kind of. Um, and the worst part was any time we wanted to actually test this generator we were coming up against, we had to do a ride share. Um, so we had to actually go take a ride somewhere, put a payload in a mobile app, wait a few minutes, be able to test. So, we, we spent some money, took, took quite a few rides around New York City, uh, got some really good hot dogs. It was, it was great. Uh, but the thing was, we just eventually we thought, okay, we're gonna send an image source, we're gonna point it to our server and we're gonna get the user agent. And once we got through that, um, and the difficulty of quotes on iOS, uh, where it'll try to use smart quotes instead of normal, straight up double quotes. Um, we were able to see that this was Weezyprint. Um, so, great thing was it was open source, um, simple Python, you know, Python library just wrote a quick script and then I was able to actually replicate this in my own environment. And I was able to do all the testing there. Um, the problem was this was where we kind of hit the brick wall. Like looking through the source, this thing did nothing. It doesn't do any scripts, any iframes, no redirects, nothing. Um, so we kind of hit a brick wall and just didn't feel like we could get through. Um, when, yeah, go for it. Um, this is the, this is how the Weezyprint application works if you're just locally doing it. So this is what we have to do in order to figure out if it's even vulnerable. Like Cody mentioned, we installed Weezyprint locally. Uh, what you do is, you will pretty much put in a HTML file. So on the left side, I'm making that HTML file on the left and I give it to Weezyprint and I say output to output dot PDF. And on the right hand side, you can see what was printed. So this is my process of seeing what the heck can I do on this PDF thing? Like what is actually available to me? So obviously basic HTML worked. Uh, I did a document right that didn't work. I tried to fetch an image. Um, you know, I, I titled it and at the bottom I'm writing it to fetch a Google image. That one worked but having an image really doesn't help me get clear text for the AWS keys. Worth this a little bit. And iFrame obviously didn't work. Um, so we needed to come up with a backup plan. Um, just to reiterate this again, no JavaScript, no iFrame, and uh, but we did have access to source. Which uh, enters this unicorn, Cody. So I'm hunting through and I'm actually just going through the entire HTML parser. When I say entire HTML parser, it's a couple hundred lines of code. Um, but at this point I'm exhausted. I'm not feeling very good about it. I'm looking through it more as a formality to be able to be like, all right, I, I did everything I could. I'm done. I, I'm gonna quit here. And I'm looking at it and I'm like, image, okay, they might be using a vulnerable library on the back end. They're using like, um, some, uh, GTK library to do decoding. Maybe there's something fun there. No. Um, there is in bed, but it turns out that it just points to image. Um, there's object, again, points to image. Like they really love image processing. But then there's this link tag. And that looked really interesting to me. Um, I didn't really know what it would be. You know, link is often used for spread, uh, for style sheets, uh, things like that. But this didn't seem to be doing that. So that's where rel attachment comes in. And uh, WeezyPrim will actually just take whatever file or URL you, uh, you give it and just put it in the PDF. Uh, not visibly. But it's there. Uh, a, a three line Python script will pull that data right out and decompress it. And uh, yeah, we could not only read files but make requests to the metadata service. Um, it took us three more rideshares. We had to pull the name of their, uh, EC2, uh, access account. And then two more to actually pull all the keys. And we had everything. We had complete control of their environment. So you can actually see here, just using that, uh, rel attachment, this, uh, this Python script just unpacks it straight from the PDF and boom, you have Etsy password. We also use this, uh, after we found this, we actually put this in our CTF. We wanted to see, I missed this for three months until him and I linked up. So we wanted to see if other hackers would miss it and obviously they didn't miss it. We had a bunch of people find this as a part of our, uh, $50 million hacker one, uh, CTF. So, uh, if you found this, shout out to you. So now we're gonna talk about something that I, I found really fun, which is DNS rebinding when it comes to SSRF. So as I said before, uh, Headless Chrome is tough. Um, same origin policy really, uh, really screws things up. You are unable to talk to anything that is not effectively the original sub domain or domain that you are on. Um, there's really nothing you can do about that. So what if you do just keep talking to the same domain? What if, so you go to, you have the browser go to x.ploit.info. Um, it does some kind of XMLHTP request to the metadata service. It's gonna fail. Like we know that. This is standard same origin policy, JavaScript. But if I go to exploit.info and I do an XMLHTP request to exploit.info, uh, info with the same path, it's gonna succeed. Like this is, this is standard stuff. So instead, what we can do is we can have the browser load this page. And then once, when the page loads up, you're gonna have a script that kicks off a message to the server that says, okay, your DNS server now should map exploit.info to 169254169254. Um, the script then goes ahead and does request, uh, or an image tag or, or whatever to a bunch of other domains, specifically 2500 of them. Because if you do 2500 of them, it flushes Chrome's internal DNS cache. The next request that you make to exploit.info, it has no idea where you're, where you're talking to anymore. So it has to go and make a new DNS request and it turns out that it's connecting to the metadata service now. And the metadata service does not check its host header. Uh, none of them do. EC2, Azure, GCP, none of them check the host header. So as soon as you have done this rebinding attack, you actually have the ability to make any request whatsoever to metadata without any of the same origin policy because it thinks that it's talking to the exact same server. What's really cool is that you can actually use other server, uh, other domains, uh, like I used bc.exploit.info. Um, and you just have to enable cores on them to be able to send data up to them and exfiltrate data. So, we have a little demo. Um, this was actually in, um, this was in, this was in Snapchat, uh, in their ad, uh, functionality. So, uh, yeah. So what this app does is you can create ads on Snapchat. So if you're, you know, watching your stories, click, click, click, it comes up. This is how you make it. But it also lets you fetch external images from a website in order to make your ad. So if you wanted to use images from a page that you have created on your website and embed that page, you fetch for it and it will grab all those, uh, images. So, um, we found this endpoint that, uh, would make the request to my server and on the response we couldn't see anything. And when I tried to JavaScript, JavaScript worked but I couldn't just directly hit the metadata, uh, instance and get the keys off. So we had to do a little bit of DNS rebinding and it looked like this. So again, uh, we're going to this app and we're just going to create a new, uh, advertisement on Snapchat using their own templates. Uh, it let you again customize those logos that they're giving you and you fetch your own website. We just fetched Google, we intercepted it on Burp and we changed the value from, let's go send it to repeater and then we're going to change the value from google.com to our host where we're going to do the DNS rebinding, uh, in order to hit the metadata. So we hit the metadata, uh, we hit that, uh, endpoint, it invokes our script on Kodi's box. So it invokes it, you go to your, uh, it'll provide who you're using, we're using Cloud for this instance and you change the IP address to the cloud, metadata IP and you give it, uh, 50 loops. It takes a while but we split it up a little bit. And uh, this was their GCP tokens and uh, secrets pulled out and prod from Snapchat. So the reason that this took so long is that this was actually before I figured out that 2500 requests would flush the cache. So you had to actually make it just continually request, uh, until about a minute past, which is the minimum TTL for the, um, Google, um, the built-in Chrome DNS cache. So doing that manually kind of sucks, um, you have to go in, change your DNS, uh, DNS provider at the exact right time. Um, so I didn't want that. So I actually wrote a tool called HTTP Rebind, it's a real clever name. Um, I combined a DNS server with an HTTP server, um, and then I made it attack everything. Um, so you point your, you actually have to point this to be your name server for a domain and once you've done that, this will handle basically all of the exploitation for you. You point, um, you point something like Snap in, in our case to this tool. Um, it'll automatically handle the rebinding because it's got the DNS server built in. Um, it'll automatically figure out what you're attacking against and handle it appropriately. So it'll work for EC2, ECS. Uh, I think I have Azure support in there. If not, it'll be there in a minute. Uh, Google Cloud. Um, all of these work automatically. And because of the, the cache flush thing, uh, it works pretty much instantaneously. Um, I think, uh, usually on average about a second and a half, two seconds to pop all of the credentials for the server. Um, the source for that will be up on GitHub immediately after this talk. Um, likewise I have a tool, SSRF test. Um, I have a live instance of this. This is something that's actually been out there for a while but I haven't really talked about. Um, basically it acts like request bin if you're familiar with it where you can create a target, it'll show you any requests that come in. Um, which is great. It's useful to just kind of get an idea of what you're doing. Like, you'll get that username, uh, the user agent that's really important. Um, but what it'll actually do is if it's, if it is in a browser like an actual headless browser, uh, it'll do a, um, a quick automated exploitation. So, uh, if same origin policy is not a problem and we don't have to go down the DNS rebinding path, this will automatically go and pull literally every key from, uh, from Amazon. Um, and this tool alone made me a lot of bounties. Um, so the source code for this is all available. Um, but if you don't want to run it yourself and you trust me enough, um, which in theory you shouldn't, but, uh, if you want to SSRF test.com, uh, make sure you go to it with HTTPS or things will go weird. Um, that's, uh, that's the public instance for it and, uh, this is what I personally use for all of my, uh, all of my testing for SSRF when I'm trying to just figure out what I'm dealing with initially. So a quick recap. Um, as I thought it can be dangerous. Uh, don't stop at the, you know, if you get an external fetch, don't stop there, see what else you can do. Uh, don't give up your bugs. WheezyPent took me three months and some change and a bunch of rides in New York City to figure out. Uh, and if you see a PDF generator, I promise you it's usually vulnerable. You just gotta find the right, uh, angle and the way to get in. Uh, the stable JavaScript, it's not good, you don't need any PDF generators. Um, create some whitelisting, blacklisting, whatever, uh, works with you. Limit the exposure to your instance at least. Um, probably configure your cloud instances so the keys aren't being leaked. And please be nice to hackers. Uh, again, I'm, uh, Nahamsek, Benson Deguiporn and this is Cody. Uh, keep in touch with us, tweet at us, email us. Uh, if you ever find any SSRFs you can't exploit, we'd love to look at it and see if we can, uh, extend on this research. And thank you guys for joining us.