When TLS Hacks You
CC Attribution 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor.
Maddux, Joshua
Lots of people try to attack the security of TLS. But what if we use TLS to attack other things? It's a huge standard, and it turns out that features intended to make TLS fast have also made it useful as an attack vector. Among other things, these features provide a lot of flexibility for Server-Side Request Forgery (SSRF). While past work using HTTPS URLs in SSRF has relied upon platform-specific bugs such as SNI injection, we can go further. In this talk, I present a novel, cross-platform way of leveraging TLS to target internal services. Uniquely, these attacks are more effective the more comprehensively a platform supports modern TLS, so won't go away with library upgrades. It is also unlikely that the TLS spec will change overnight at the whim of a random security researcher. Instead, we need to walk through scenarios and dispel common assumptions so the audience can know what to look out for. Of course, the best way to do so is with demos!
 Welcome to this talk, when TLS hacks you. I'm actually going to start with a demo. This is going to be weird. This isn't a concrete attack scenario, but hopefully should make everyone curious about what's going on. For those familiar with SSRF, the implications will be fairly clear, but I'll explain them right after the demo for everyone else. After that, the attack examples are going to gradually move towards real stuff, but I find it's easiest to look at the simplest cases and then start expanding to look at real-world stuff. For now though, let's see the essence of the dangerous property of TLS that this talk is about. So, here's MIMCache, a popular cache that Common really runs on port 1, 1, 2, 1. I have it installed here, so you can first see for the key named Z, there currently is no entry. If you're not familiar with MIMCache, this is how stuff communicates with it, a new line-to-limited TCP protocol. But now I'll do something that you might not expect to affect MIMCache. I'll make a request to an HTTPS URL. The dash L enables redirects, and the dash V lets you see what all that's going on. So, you can see that the end-billient is redirecting to itself. I set this up because it's a lightning talk, and the stringer of redirects takes a couple of minutes. But the redirects don't go on forever. After a bit, we get an error. And now for the magic. Going back to MIMCache, if we rerun the same Git command, we see an entry appear. The odd thing is, that text never showed up in the crawl command or in any of the redirects. So, somehow the server we were talking to had to do something with TLS to trick curl into putting it in there. So, even though I didn't do just anything other than hacking myself, what just happened was weird and potentially useful. But here's where I'm going with this. Because not everyone is into these sorts of attacks, I'm going to start off with exactly what makes this useful as an attacker. I'll then move on to some stuff that shows just how widely these attacks can be applied, and then get some recommendations for what to do about them. So, to start off with, there's an existing class of vulnerability called SSRF. It stands for server-side request forgery. It's where you effectively fish the server into doing something by sending it a URL. Last year at Black Hat, I demonstrated a bunch of these vulnerabilities in Apple Pay and in WebPoke receivers. I'm not going to go into those as much here, but if you're curious, you can download these slides later and go to the Ctabtube link right here. SSRF has a ton of different approaches, but it was actually pretty easy in some cases. Wibkit.org had a live sample implementation of Apple Pay, and it was even on AWS with the old Insys metadata service. So, all I had to do was pass this IP, and I could poke around an internal API and get some tokens. But not everything was so simple. I had a lot of SSRF vulnerabilities that were almost there, but weren't vulnerable to this easy approach. Sometimes I'd have a WebPoke where I could hand it a URL, and the server would even fetch the URL, but not give me a response. This is called blindSSRF. Other times, a request in question would be a put request, which restricted what endpoints I could hit. Sometimes you can mess with the request method by setting up an endpoint that redirects the target server around, but that's hit or miss. Other times, you might get some data back, but it's validated against a specific content type, or you only get back certain fields. Or even worse, it'll only accept HTTPS URLs. But what we really want in order to exploit this stuff is a generic blindSSRF approach. In other words, we'd like to see the server I URL have it fire a payload at something internal, like SMTP or Redis, and get a security compromise, just from that payload, without needing to see the response. Here are some of the common approaches. The issue is these are extremely platform-specific, to the point where I've never had any luck with these. But there are some useful ideas in here, particularly in SNI infection. I wouldn't think that TLS would be particularly useful, because its packets are mostly just encrypted data, binary flags, and other stuff an attacker doesn't have much control over, but it's not all that limited. As orange sign-os, the SNI, which is basically just the domain name, is part of the URL. So if you can trick the victim into accepting a weird domain name and parsing it incorrectly, you can include stuff like arbitrary bytes in there and smuggable stuff like SMTP commands. This approach is dependent on a platform-specific URL parsing book. But what if we had something that was inherent to the TLS protocol? This is where my work starts. Let's look at a TLS packet and see what's in there for us to use. As is often helpful when looking at protocols, we can open up a wire chart to see what happens in a TLS connection. Here's the SNI, or server name indication, that was previously explored in Orange's Doc. His work involves putting new lines in SNTP commands into the section pointed to by the arrow here. If you poke around, you'll see stuff like random strings, key shares, and other stuff that isn't useful for SSRF. Why? Because the only part of this we can typically feed a server is a URL, and the only part of the URL that will make it into the client-hello packet is the domain name that we provided the victim machine. But there's a different way that we as an attacker can get payloads into client-hello messages. It involves a couple of steps and is the main focus of this talk. First, we send over a link to our own server, in this case jmatx.com. Then jmatx.com responds with a valid server hello that it contains our payload. Now, it would be ideal if we as an attacker could get that payload that jmatx.com sent the victim, and then get the victim to send it somewhere internal. If that raises a question, is there such a field that we can use to deliver these payloads? It might seem too good to be true, but TLS actually provides exactly that in the form of a session ID. Most clients even persist this field for later use. Session IDs are limited to 32 bytes as you can see here, but depending on the implementation you might have session tickets. This one is about 200 bytes, but these can be up to around 65 kilobytes. Both session IDs and session tickets are mechanisms for a TLS client to go. Hey, remember that cryptographic key exchange we did earlier? Let's just keep using that key in this new connection. TLS 1.3 includes a slightly more complicated but similar mechanism called a pre-shared key identity, which pretty much does the same thing for our purposes. All of these are about optimization, since key exchanges can be time-consuming. But they provide a way for a server to tell whatever is connecting to it to persist some data for later use, almost like a cookie that lives in plain text. So it's perfect for the SREF attack we're trying to do. Now you might anticipate a problem here. Obviously, if you go to google.com and then to apple.com, those TLS sessions are going to have distinct data from each other. The same applies between google.com and localhost. So we have a bit of a problem getting the target server to reuse the session when communicating with something internal. But when I looked at both the TLS spec and popular session cash from implementations, I saw this wasn't quite the case. I first went to the curl source code, since libcurl is used by a lot of php stuff. Sessions are keyed by the four properties here, which belong to the SREF. As you can see, none of these are the IP address. This means that no matter what IP address jmatx.com resolves to, curl will attempt to reuse the session. This happens to be to have just about everything else cashed as TLS sessions. So if you establish a TLS session with jmatx.com, whether it resolves to something on the internet or your own machine, your HTTPS client will not know the difference. Since I as an attacker own jmatx.com, I can combine all this TLS stuff with a concept called DNS rebinding. So I resolve the first request to 35.x.x.x, some server I control. Then the target server picks up the payload from 35.x.x.x in the form of a session ticket. After some time, I send the exact same URL, except the DNS entry has expired. Again, since I control the DNS server, this time around, I resolve jmatx.com to something internal that I wouldn't normally have access to from the outside. To simplify things, I'll just use localhost. Once the DNS query finishes, the target server then makes an internal request with that payload. So like what I did in the opening demo, you can manipulate whatever you're attacking to send a TLS session ID, ticket, or PSK identity like this to itself. Here I'm showing a PSK identity that does a memcached insert. And here's that same TCP stream that just displayed raw. This view shows the really important property of my approach to combining TLS with DNS rebinding. You can get arbitrary characters to be sent, which includes new lines. This is what allows you to interact with a bunch of local services like memcached, just like people did in the past with gopher URLs. And here's an exchange more typical of what you'd use to do real damage. This is a value that in most Python memcached libraries will execute a shell command immediately once it's retrieved from a cache. This is because it's quite common in Python and other languages to use built-in serialization methods like pickle to convert values to something that can be stored. Unfortunately, built-in serialization methods are also common RCE targets. We'll get to exploitation later. But since this is pretty common, I ended up testing a fair amount of slides. I'll get to some specific ones in a second, but first I'll go over some testing infrastructure I set up. Along with some tips for actually performing these kinds of exploits. So here are all the VMs I have on the Internet. Say for maybe some IP whitelisting, they need to be on the open Internet so that the target boxes can reach them. I've got a nameserver record pointing ssaltest.jmatt.com queries to the DNS server on the top left, which is just a Python script running on port 53. It alternates between answering with the IP of the custom TLS server and local host. Then over there on the right I have my custom TLS server, which is there to deliver my payloads via session tickets. I configure those by just updating values in Redis. But when testing it, it proved to be difficult to just go straight to local host, because depending on what library is making the requests, I didn't know if SSL sessions were being cached. To address this, I sometimes just ended up adding another box to see if the payload was being persisted. If you're not familiar, Netcat can be set up to just listen for TCP connections and log the results. If I saw my payload making it into the logs, I knew the general approach could work. And then go back to the setup from the previous slide to get the server to start delivering the payload to itself on different ports. And here are the links to all that I actually used. A big chunk of the work was saved by just messing around with a pure rust implementation of TLS, which is linked to you here. A big thing goes out to everyone mentioned in this slide. I wouldn't have had the time to do any of this work if not for the code they had put out there. But I know with everything I just claimed, I need to back things up by showing what actual real world attacks can happen with this. I'll start off conceptually and then get to some examples along with another demo. But here's the amount I've got. If you're in the middle of this diagram, you're generally vulnerable. The salt part refers to when you can send something URL and it will fetch that URL, but you don't know of a way to exploit that behavior. It's interesting because you would hope by now people would try to eliminate anything even remotely looking like SSRF. But this pattern is in fact required by a few popular specs. There's even common off that I've seen bug bounties mention SSRF with no prevent security impact as an excluded category. But that's what this talk is about. Adding the security impact when you have just something that says just almost SSRF. This one on the left sounds weird, but it's getting bigger. It's just a matter of if whatever the SSRF is going through to make requests has implemented this feature according to the latest spec. Unfortunately, there are quite a few Https client libraries out there that support full blown TLS session caching. Here are a few that you may be wondering about. I reported this as a vulnerability to some of these, but not all of the entries with yes. And I haven't seen much distraction. Understandably, since fixing this requires diverging from the TLS spec, not a whole lot of people are eager to do so. The thing you run into the most trouble with is this last circle. Because you have to first do some recon to see what ports might be internally exposed on the server. And then you need to see if what's on those ports is permissive enough to keep the connection open past the opening bytes of the TLS client hello. Here are some examples of what you might be looking for there. It's far from complete, but here are the most notable entries. So now we'll go through a couple of exploitable examples of these TLS session based SSRF vulnerabilities that I reported and got fixed. Here's one from Utrecht. It's rated low because all I did was hit local SMTP and I didn't try poking around to see if I could exploit the SMTP server further. It originated from Utrecht's import feature, which normally wouldn't be easy to exploit being blind SSRF. But with my rebinding code, here's a section from the TLS packet I got Utrecht to send itself. This works because SMTP is a new line delimited protocol. So just like NIMCache, you can embed working commands within the TLS ticket. And here's what came up that packet. This alone wasn't super severe because it's not signed quite right and I didn't dig too deeply because I wanted to just report it ASAP. But it did get initiated by a TCP stream I got Utrecht to send itself, so it's still pretty bad. Here's the one I reported in NexCloud. The idea behind NexCloud is a cool one. You set up a server in host files and can even share them with other people's servers using a share URL like this. But as it turns out, you can include port numbers in this share URL. Now, since NexCloud automatically puts HTTPS in there, normally there wouldn't be much SSRF potential and it would have to be blind SSRF. But luckily, I was able to do just that. So as a non-NNMN user, I could use my TLS for binding attack infrastructure to perform arbitrary writes on NIMCache. After reporting this and working through the options, there weren't any great ones. Because not all request libraries allow you to disable TLS sessions. In this case, LibGirl has the option, but it isn't exposed by PHP request libraries such as Gezzle. In any case, adding a request timeout made the attack pretty much infeasible, assuming that people don't turn the DNS time to live values super low on their servers. NexCloud was still generous enough to give me a bounty, even though in my opinion this is LibGirl's fault. Since the last couple were just text slides, let's see a real demo now from the perspective of a Django web developer getting fished. The DNS for binding part has been done in the past, but what's new here is combining DNS for binding with TLS session persistence to make it more powerful. In the past, you had to get people to visit a fully malicious page to get anywhere with the DNS for binding, but with my work you can do the same with just an image tag. Because of that, you can fish people into RCE even if they just view an email, but don't click on any links. Let's see that now. And now for the actual demo. So as you can see, we're pertaining a Django application developer running a typical app. If we look at the app, it's pretty simple. We can view a sloth emoji, but if we refresh too fast, the sloth needs to go to sleep. And now for what happens when I get fished. As you can see, I have received some perfectly legitimate emails, and I'm viewing them. Normally these image tags should be benign, but after viewing them, my sloth now opens a calculator via shell command. That's because those image tags point into the domain with my binding setup and a simple Python pick-up pick-hole payload. So here's most of the source code in the example app I created. You can pretty easily find apps that called Django.core.cache or on GitHub, but I didn't want to demo against a specific one because that seems a little mean and I wouldn't want people watching actual fishing campaigns against such projects. It's a little tough to assign blame here. Nothing is really breaking from established safe practices, but it's clear that there's a potential to compromise real world developer laptops. On that note, there's a lot more to do that I couldn't possibly do on my own. These slides will be available online if you want to return to this, and if you do anything interesting, I'd love to hear about it. There are certainly a lot more potential vulnerabilities to explore. So all of that is bad. But what can be done about it? So let's start from the root of the problem, TLS clients. Here's something I recommended to the Chromium team a while back. We still aren't in agreement about whether or not this should be fixed, and my report was pretty hastily written, which probably didn't help things. Essentially, I'd like to remove the ability for sessions to be resumed between servers. But while the Chromium team is marked this as a won't fix, they did suggest an alternative that maintains support for resuming sessions across servers. They probably care about that more than I do, but we can at least have the best of both worlds. This last option of just partitioning based upon whether the address is something local is a pretty good compromise. It wouldn't affect performance, but would protect against most of the attacks scenarios I can think of. But based on my experiences so far, I'm not hopeful that there's going to be much proactive effort on the part of software packages that make HPS requests. For most of the audience, it's more useful to know what's susceptible and what layers of defense can be applied. However, with all of this worth taking a step back to consider, is TLS session resumption even worth it? There are other issues with it, a couple of which are shown here. I'm not going to make the case that the industry as a whole should give up on this optimization, but we should take a step back and see if this is worthwhile trade-off. We may, just like in the previous slide, find that the costs can be eliminated. But if we find we can't tackle these problems, we need to weigh them against the benefits. And here's the main benefit. You get a sizable performance improvement on the small subset of packets that are TLS handshakes. You probably care about this whenever you're in the position of serving up TLS. Whatever percentage of CPU usage is due to TLS handshakes, you probably want to keep that low to minimize costs. But if you're like me, you don't care. I'm taking on all the security and privacy risk of session resumption, but the amount that saves on my power bill is pretty minimal. Additionally, if you're running a web application, you might care about session resumption on incoming connections. But when you're making external requests, it's probably not in your interests. You're placing a lot of trust on random websites not to redirect you and own your local services. So how might you turn it off? Here's what I found. It's kind of sad when stuff forces you into this, but at least as an internet user, you can pick Firefox and disable session identifiers if you're paranoid about this stuff. If you're running a web application, you're a bit stuck, though. So what should you do? First off, it's a good idea in general to run your outbound requests through a proxy, especially if you're supporting webhooks or some other SSRF-prone feature. But also, re-consider your infrastructure decisions. You'd be surprised to know how just how much stuff is still set up in a way that is just one locally initiated TCP stream away from compromise. But here are the general takeaways. The thing I'd like to highlight is, if you're just starting out in the offensive side of security, I'd encourage you to look at the random standards and browser features that come out, even if you don't fully understand them at first. Find something that seems interesting and start hacking around in Wireshark. I know I didn't understand TLS at first, and I still don't really understand it very much after all of this. But as an attacker, you really only need to understand the worst parts, and that's what this is all about. And thank you. Here's my Twitter and a link to Lotakora where I work. They're a great place to work and have been amazingly supportive of random research directions I take. Definitely take a look.
 Welcome to this talk, when TLS hacks you.  I'm actually going to start with a demo. This is going to be weird.  This isn't a concrete attack scenario, but hopefully should make everyone curious about what's going on.  For those familiar with SSRF, the implications will be fairly clear, but I'll explain them right after the demo for everyone else.  After that, the attack examples are going to gradually move towards real stuff, but I find it's easiest to look at the simplest cases and then start expanding to look at real-world stuff.  For now though, let's see the essence of the dangerous property of TLS that this talk is about.  So, here's MIMCache, a popular cache that Common really runs on port 1, 1, 2, 1.  I have it installed here, so you can first see for the key named Z, there currently is no entry.  If you're not familiar with MIMCache, this is how stuff communicates with it, a new line-to-limited TCP protocol.  But now I'll do something that you might not expect to affect MIMCache. I'll make a request to an HTTPS URL.  The dash L enables redirects, and the dash V lets you see what all that's going on.  So, you can see that the end-billient is redirecting to itself.  I set this up because it's a lightning talk, and the stringer of redirects takes a couple of minutes.  But the redirects don't go on forever. After a bit, we get an error.  And now for the magic. Going back to MIMCache, if we rerun the same Git command, we see an entry appear.  The odd thing is, that text never showed up in the crawl command or in any of the redirects.  So, somehow the server we were talking to had to do something with TLS to trick curl into putting it in there.  So, even though I didn't do just anything other than hacking myself, what just happened was weird and potentially useful.  But here's where I'm going with this. Because not everyone is into these sorts of attacks, I'm going to start off with exactly what makes this useful as an attacker.  I'll then move on to some stuff that shows just how widely these attacks can be applied, and then get some recommendations for what to do about them.  So, to start off with, there's an existing class of vulnerability called SSRF. It stands for server-side request forgery.  It's where you effectively fish the server into doing something by sending it a URL.  Last year at Black Hat, I demonstrated a bunch of these vulnerabilities in Apple Pay and in WebPoke receivers.  I'm not going to go into those as much here, but if you're curious, you can download these slides later and go to the Ctabtube link right here.  SSRF has a ton of different approaches, but it was actually pretty easy in some cases.  Wibkit.org had a live sample implementation of Apple Pay, and it was even on AWS with the old Insys metadata service.  So, all I had to do was pass this IP, and I could poke around an internal API and get some tokens.  But not everything was so simple. I had a lot of SSRF vulnerabilities that were almost there, but weren't vulnerable to this easy approach.  Sometimes I'd have a WebPoke where I could hand it a URL, and the server would even fetch the URL, but not give me a response.  This is called blindSSRF.  Other times, a request in question would be a put request, which restricted what endpoints I could hit.  Sometimes you can mess with the request method by setting up an endpoint that redirects the target server around, but that's hit or miss.  Other times, you might get some data back, but it's validated against a specific content type, or you only get back certain fields.  Or even worse, it'll only accept HTTPS URLs.  But what we really want in order to exploit this stuff is a generic blindSSRF approach.  In other words, we'd like to see the server I URL have it fire a payload at something internal, like SMTP or Redis, and get a security compromise,  just from that payload, without needing to see the response.  Here are some of the common approaches.  The issue is these are extremely platform-specific, to the point where I've never had any luck with these.  But there are some useful ideas in here, particularly in SNI infection.  I wouldn't think that TLS would be particularly useful, because its packets are mostly just encrypted data, binary flags,  and other stuff an attacker doesn't have much control over, but it's not all that limited.  As orange sign-os, the SNI, which is basically just the domain name, is part of the URL.  So if you can trick the victim into accepting a weird domain name and parsing it incorrectly, you can include stuff like arbitrary bytes in there  and smuggable stuff like SMTP commands.  This approach is dependent on a platform-specific URL parsing book.  But what if we had something that was inherent to the TLS protocol?  This is where my work starts.  Let's look at a TLS packet and see what's in there for us to use.  As is often helpful when looking at protocols, we can open up a wire chart to see what happens in a TLS connection.  Here's the SNI, or server name indication, that was previously explored in Orange's Doc.  His work involves putting new lines in SNTP commands into the section pointed to by the arrow here.  If you poke around, you'll see stuff like random strings, key shares, and other stuff that isn't useful for SSRF.  Why? Because the only part of this we can typically feed a server is a URL,  and the only part of the URL that will make it into the client-hello packet is the domain name that we provided the victim machine.  But there's a different way that we as an attacker can get payloads into client-hello messages.  It involves a couple of steps and is the main focus of this talk.  First, we send over a link to our own server, in this case jmatx.com.  Then jmatx.com responds with a valid server hello that it contains our payload.  Now, it would be ideal if we as an attacker could get that payload that jmatx.com sent the victim,  and then get the victim to send it somewhere internal.  If that raises a question, is there such a field that we can use to deliver these payloads?  It might seem too good to be true, but TLS actually provides exactly that in the form of a session ID.  Most clients even persist this field for later use.  Session IDs are limited to 32 bytes as you can see here, but depending on the implementation you might have session tickets.  This one is about 200 bytes, but these can be up to around 65 kilobytes.  Both session IDs and session tickets are mechanisms for a TLS client to go.  Hey, remember that cryptographic key exchange we did earlier?  Let's just keep using that key in this new connection.  TLS 1.3 includes a slightly more complicated but similar mechanism called a pre-shared key identity,  which pretty much does the same thing for our purposes.  All of these are about optimization, since key exchanges can be time-consuming.  But they provide a way for a server to tell whatever is connecting to it to persist some data for later use,  almost like a cookie that lives in plain text.  So it's perfect for the SREF attack we're trying to do.  Now you might anticipate a problem here.  Obviously, if you go to google.com and then to apple.com, those TLS sessions are going to have distinct data from each other.  The same applies between google.com and localhost.  So we have a bit of a problem getting the target server to reuse the session when communicating with something internal.  But when I looked at both the TLS spec and popular session cash from implementations, I saw this wasn't quite the case.  I first went to the curl source code, since libcurl is used by a lot of php stuff.  Sessions are keyed by the four properties here, which belong to the SREF.  As you can see, none of these are the IP address.  This means that no matter what IP address jmatx.com resolves to, curl will attempt to reuse the session.  This happens to be to have just about everything else cashed as TLS sessions.  So if you establish a TLS session with jmatx.com, whether it resolves to something on the internet or your own machine,  your HTTPS client will not know the difference.  Since I as an attacker own jmatx.com, I can combine all this TLS stuff with a concept called DNS rebinding.  So I resolve the first request to 35.x.x.x, some server I control.  Then the target server picks up the payload from 35.x.x.x in the form of a session ticket.  After some time, I send the exact same URL, except the DNS entry has expired.  Again, since I control the DNS server, this time around, I resolve jmatx.com to something internal that I wouldn't normally have access to from the outside.  To simplify things, I'll just use localhost.  Once the DNS query finishes, the target server then makes an internal request with that payload.  So like what I did in the opening demo, you can manipulate whatever you're attacking to send a TLS session ID, ticket, or PSK identity like this to itself.  Here I'm showing a PSK identity that does a memcached insert.  And here's that same TCP stream that just displayed raw.  This view shows the really important property of my approach to combining TLS with DNS rebinding.  You can get arbitrary characters to be sent, which includes new lines.  This is what allows you to interact with a bunch of local services like memcached, just like people did in the past with gopher URLs.  And here's an exchange more typical of what you'd use to do real damage.  This is a value that in most Python memcached libraries will execute a shell command immediately once it's retrieved from a cache.  This is because it's quite common in Python and other languages to use built-in serialization methods like pickle to convert values to something that can be stored.  Unfortunately, built-in serialization methods are also common RCE targets. We'll get to exploitation later.  But since this is pretty common, I ended up testing a fair amount of slides.  I'll get to some specific ones in a second, but first I'll go over some testing infrastructure I set up.  Along with some tips for actually performing these kinds of exploits.  So here are all the VMs I have on the Internet.  Say for maybe some IP whitelisting, they need to be on the open Internet so that the target boxes can reach them.  I've got a nameserver record pointing ssaltest.jmatt.com queries to the DNS server on the top left, which is just a Python script running on port 53.  It alternates between answering with the IP of the custom TLS server and local host.  Then over there on the right I have my custom TLS server, which is there to deliver my payloads via session tickets.  I configure those by just updating values in Redis.  But when testing it, it proved to be difficult to just go straight to local host, because depending on what library is making the requests, I didn't know if SSL sessions were being cached.  To address this, I sometimes just ended up adding another box to see if the payload was being persisted.  If you're not familiar, Netcat can be set up to just listen for TCP connections and log the results.  If I saw my payload making it into the logs, I knew the general approach could work.  And then go back to the setup from the previous slide to get the server to start delivering the payload to itself on different ports.  And here are the links to all that I actually used.  A big chunk of the work was saved by just messing around with a pure rust implementation of TLS, which is linked to you here.  A big thing goes out to everyone mentioned in this slide.  I wouldn't have had the time to do any of this work if not for the code they had put out there.  But I know with everything I just claimed, I need to back things up by showing what actual real world attacks can happen with this.  I'll start off conceptually and then get to some examples along with another demo.  But here's the amount I've got.  If you're in the middle of this diagram, you're generally vulnerable.  The salt part refers to when you can send something URL and it will fetch that URL, but you don't know of a way to exploit that behavior.  It's interesting because you would hope by now people would try to eliminate anything even remotely looking like SSRF.  But this pattern is in fact required by a few popular specs.  There's even common off that I've seen bug bounties mention SSRF with no prevent security impact as an excluded category.  But that's what this talk is about.  Adding the security impact when you have just something that says just almost SSRF.  This one on the left sounds weird, but it's getting bigger.  It's just a matter of if whatever the SSRF is going through to make requests has implemented this feature according to the latest spec.  Unfortunately, there are quite a few Https client libraries out there that support full blown TLS session caching.  Here are a few that you may be wondering about.  I reported this as a vulnerability to some of these, but not all of the entries with yes.  And I haven't seen much distraction.  Understandably, since fixing this requires diverging from the TLS spec, not a whole lot of people are eager to do so.  The thing you run into the most trouble with is this last circle.  Because you have to first do some recon to see what ports might be internally exposed on the server.  And then you need to see if what's on those ports is permissive enough to keep the connection open past the opening bytes of the TLS client hello.  Here are some examples of what you might be looking for there.  It's far from complete, but here are the most notable entries.  So now we'll go through a couple of exploitable examples of these TLS session based SSRF vulnerabilities that I reported and got fixed.  Here's one from Utrecht.  It's rated low because all I did was hit local SMTP and I didn't try poking around to see if I could exploit the SMTP server further.  It originated from Utrecht's import feature, which normally wouldn't be easy to exploit being blind SSRF.  But with my rebinding code, here's a section from the TLS packet I got Utrecht to send itself.  This works because SMTP is a new line delimited protocol.  So just like NIMCache, you can embed working commands within the TLS ticket.  And here's what came up that packet.  This alone wasn't super severe because it's not signed quite right and I didn't dig too deeply because I wanted to just report it ASAP.  But it did get initiated by a TCP stream I got Utrecht to send itself, so it's still pretty bad.  Here's the one I reported in NexCloud.  The idea behind NexCloud is a cool one.  You set up a server in host files and can even share them with other people's servers using a share URL like this.  But as it turns out, you can include port numbers in this share URL.  Now, since NexCloud automatically puts HTTPS in there, normally there wouldn't be much SSRF potential and it would have to be blind SSRF.  But luckily, I was able to do just that.  So as a non-NNMN user, I could use my TLS for binding attack infrastructure to perform arbitrary writes on NIMCache.  After reporting this and working through the options, there weren't any great ones.  Because not all request libraries allow you to disable TLS sessions.  In this case, LibGirl has the option, but it isn't exposed by PHP request libraries such as Gezzle.  In any case, adding a request timeout made the attack pretty much infeasible, assuming that people don't turn the DNS time to live values super low on their servers.  NexCloud was still generous enough to give me a bounty, even though in my opinion this is LibGirl's fault.  Since the last couple were just text slides, let's see a real demo now from the perspective of a Django web developer getting fished.  The DNS for binding part has been done in the past, but what's new here is combining DNS for binding with TLS session persistence to make it more powerful.  In the past, you had to get people to visit a fully malicious page to get anywhere with the DNS for binding, but with my work you can do the same with just an image tag.  Because of that, you can fish people into RCE even if they just view an email, but don't click on any links.  Let's see that now.  And now for the actual demo.  So as you can see, we're pertaining a Django application developer running a typical app.  If we look at the app, it's pretty simple.  We can view a sloth emoji, but if we refresh too fast, the sloth needs to go to sleep.  And now for what happens when I get fished.  As you can see, I have received some perfectly legitimate emails, and I'm viewing them.  Normally these image tags should be benign, but after viewing them, my sloth now opens a calculator via shell command.  That's because those image tags point into the domain with my binding setup and a simple Python pick-up pick-hole payload.  So here's most of the source code in the example app I created.  You can pretty easily find apps that called Django.core.cache or on GitHub, but I didn't want to demo against a specific one because that seems a little mean and I wouldn't want people watching actual fishing campaigns against such projects.  It's a little tough to assign blame here.  Nothing is really breaking from established safe practices, but it's clear that there's a potential to compromise real world developer laptops.  On that note, there's a lot more to do that I couldn't possibly do on my own.  These slides will be available online if you want to return to this, and if you do anything interesting, I'd love to hear about it.  There are certainly a lot more potential vulnerabilities to explore.  So all of that is bad.  But what can be done about it?  So let's start from the root of the problem, TLS clients.  Here's something I recommended to the Chromium team a while back.  We still aren't in agreement about whether or not this should be fixed, and my report was pretty hastily written, which probably didn't help things.  Essentially, I'd like to remove the ability for sessions to be resumed between servers.  But while the Chromium team is marked this as a won't fix, they did suggest an alternative that maintains support for resuming sessions across servers.  They probably care about that more than I do, but we can at least have the best of both worlds.  This last option of just partitioning based upon whether the address is something local is a pretty good compromise.  It wouldn't affect performance, but would protect against most of the attacks scenarios I can think of.  But based on my experiences so far, I'm not hopeful that there's going to be much proactive effort on the part of software packages that make HPS requests.  For most of the audience, it's more useful to know what's susceptible and what layers of defense can be applied.  However, with all of this worth taking a step back to consider, is TLS session resumption even worth it?  There are other issues with it, a couple of which are shown here.  I'm not going to make the case that the industry as a whole should give up on this optimization, but we should take a step back and see if this is worthwhile trade-off.  We may, just like in the previous slide, find that the costs can be eliminated. But if we find we can't tackle these problems, we need to weigh them against the benefits.  And here's the main benefit. You get a sizable performance improvement on the small subset of packets that are TLS handshakes.  You probably care about this whenever you're in the position of serving up TLS.  Whatever percentage of CPU usage is due to TLS handshakes, you probably want to keep that low to minimize costs.  But if you're like me, you don't care. I'm taking on all the security and privacy risk of session resumption, but the amount that saves on my power bill is pretty minimal.  Additionally, if you're running a web application, you might care about session resumption on incoming connections.  But when you're making external requests, it's probably not in your interests.  You're placing a lot of trust on random websites not to redirect you and own your local services.  So how might you turn it off?  Here's what I found. It's kind of sad when stuff forces you into this, but at least as an internet user, you can pick Firefox and disable session identifiers if you're paranoid about this stuff.  If you're running a web application, you're a bit stuck, though. So what should you do?  First off, it's a good idea in general to run your outbound requests through a proxy, especially if you're supporting webhooks or some other SSRF-prone feature.  But also, re-consider your infrastructure decisions. You'd be surprised to know how just how much stuff is still set up in a way that is just one locally initiated TCP stream away from compromise.  But here are the general takeaways. The thing I'd like to highlight is, if you're just starting out in the offensive side of security, I'd encourage you to look at the random standards and browser features that come out, even if you don't fully understand them at first.  Find something that seems interesting and start hacking around in Wireshark. I know I didn't understand TLS at first, and I still don't really understand it very much after all of this.  But as an attacker, you really only need to understand the worst parts, and that's what this is all about.  And thank you. Here's my Twitter and a link to Lotakora where I work. They're a great place to work and have been amazingly supportive of random research directions I take. Definitely take a look.
DEF_CON_Safe_Mode_-_Joshua_Maddux_-_When_TLS_Hacks_qGpAJxfADjo_0_107.png DEF_CON_Safe_Mode_-_Joshua_Maddux_-_When_TLS_Hacks_qGpAJxfADjo_108_215.png DEF_CON_Safe_Mode_-_Joshua_Maddux_-_When_TLS_Hacks_qGpAJxfADjo_216_851.png DEF_CON_Safe_Mode_-_Joshua_Maddux_-_When_TLS_Hacks_qGpAJxfADjo_852_983.png DEF_CON_Safe_Mode_-_Joshua_Maddux_-_When_TLS_Hacks_qGpAJxfADjo_984_1079.png DEF_CON_Safe_Mode_-_Joshua_Maddux_-_When_TLS_Hacks_qGpAJxfADjo_1080_1127.png DEF_CON_Safe_Mode_-_Joshua_Maddux_-_When_TLS_Hacks_qGpAJxfADjo_1128_1199.png DEF_CON_Safe_Mode_-_Joshua_Maddux_-_When_TLS_Hacks_qGpAJxfADjo_1200_1403.png DEF_CON_Safe_Mode_-_Joshua_Maddux_-_When_TLS_Hacks_qGpAJxfADjo_1404_1451.png DEF_CON_Safe_Mode_-_Joshua_Maddux_-_When_TLS_Hacks_qGpAJxfADjo_1452_1859.png DEF_CON_Safe_Mode_-_Joshua_Maddux_-_When_TLS_Hacks_qGpAJxfADjo_1860_2015.png DEF_CON_Safe_Mode_-_Joshua_Maddux_-_When_TLS_Hacks_qGpAJxfADjo_2016_2099.png DEF_CON_Safe_Mode_-_Joshua_Maddux_-_When_TLS_Hacks_qGpAJxfADjo_2100_2375.png DEF_CON_Safe_Mode_-_Joshua_Maddux_-_When_TLS_Hacks_qGpAJxfADjo_2376_2459.png DEF_CON_Safe_Mode_-_Joshua_Maddux_-_When_TLS_Hacks_qGpAJxfADjo_2460_5027.png DEF_CON_Safe_Mode_-_Joshua_Maddux_-_When_TLS_Hacks_qGpAJxfADjo_5028_13883.png DEF_CON_Safe_Mode_-_Joshua_Maddux_-_When_TLS_Hacks_qGpAJxfADjo_13884_22643.png DEF_CON_Safe_Mode_-_Joshua_Maddux_-_When_TLS_Hacks_qGpAJxfADjo_22644_22727.png DEF_CON_Safe_Mode_-_Joshua_Maddux_-_When_TLS_Hacks_qGpAJxfADjo_22728_22895.png DEF_CON_Safe_Mode_-_Joshua_Maddux_-_When_TLS_Hacks_qGpAJxfADjo_22896_23267.png DEF_CON_Safe_Mode_-_Joshua_Maddux_-_When_TLS_Hacks_qGpAJxfADjo_23268_23315.png DEF_CON_Safe_Mode_-_Joshua_Maddux_-_When_TLS_Hacks_qGpAJxfADjo_23316_23423.png DEF_CON_Safe_Mode_-_Joshua_Maddux_-_When_TLS_Hacks_qGpAJxfADjo_23424_23555.png DEF_CON_Safe_Mode_-_Joshua_Maddux_-_When_TLS_Hacks_qGpAJxfADjo_23556_23603.png DEF_CON_Safe_Mode_-_Joshua_Maddux_-_When_TLS_Hacks_qGpAJxfADjo_23604_24611.png DEF_CON_Safe_Mode_-_Joshua_Maddux_-_When_TLS_Hacks_qGpAJxfADjo_24612_29729.png