start	end	text
1280	4400	Welcome to this talk, When TLS Hacks You.
5160	7040	I'm actually going to start with the demo.
7100	10280	This is going to be weird. This isn't a concrete attack scenario,
10280	13100	but hopefully should make everyone curious about what's going on.
13100	16180	For those familiar with SSRF, the implications will be fairly clear,
16180	18720	but I'll explain them right after the demo for everyone else.
19080	22120	After that, the attack examples are going to gradually move towards real stuff,
22120	23940	but I find it's easiest to look at the simplest cases
23940	26680	and then start expanding to look at real-world stuff.
26800	29740	For now, though, let's see the essence of the dangerous property of TLS
29740	31120	that this talk is about.
33460	39200	So, here's memcached, a popular cache that commonly runs on port 11211.
39880	43460	I have it installed here, so you can first see for the key named Z,
43460	44880	there currently is no entry.
45060	48040	If you're not familiar with memcached, this is how stuff communicates with it,
48120	50040	a newline-delimited TCP protocol.
50260	53680	But now I'll do something that you might not expect to affect memcached.
53680	55880	I'll make a request to an HTTPS URL.
55880	60260	The "-l'' enables redirects, and the "-v'' lets you see all that's going on.
61040	64780	So, you can see that the endpoint is redirecting to itself.
65260	67100	I sped this up because this is a lightning talk,
67100	69340	and the string of redirects takes a couple of minutes.
69900	74880	But the redirects don't go on forever. After a bit, we get an error.
76080	77380	And now for the magic.
77760	82520	Going back to memcached, if we rerun the same git command, we see an entry appear.
83040	87060	The odd thing is, that text never showed up in the curl command or in any of the redirects,
87060	92360	so somehow the server we were talking to had to do something with TLS to trick curl into putting it in there.
92900	97380	So even though I didn't just do anything other than hacking myself,
97380	99720	what just happened was weird and potentially useful.
103260	105020	But here's where I'm going with this.
105060	107460	Because not everyone is into these sorts of attacks,
107460	111400	I'm going to start off with exactly what makes this useful as an attacker.
111400	115480	I'll then move on to some stuff that shows just how widely these attacks can be applied,
115480	118360	and then get to some recommendations for what to do about them.
119400	123280	So to start off with, there's an existing class of vulnerability called SSRF.
123280	125460	It stands for server-side request forgery.
125800	129600	It's where you effectively phish a server into doing something by sending it a URL.
131320	136020	Last year at Black Hat, I demonstrated a bunch of these vulnerabilities in Apple Pay and in Webhook receivers.
136240	139160	I'm not going to go into those as much here, but if you're curious,
139160	142840	you can download these slides later and go to this YouTube link right here.
144320	148900	SSRF has a ton of different approaches, but it was actually pretty easy in some cases.
148960	152120	Webkit.org had a live sample implementation of Apple Pay,
152120	155500	and it was even on AWS with the old Insys metadata service.
155540	160380	So all I had to do was pass this IP, and I could poke around an internal API and get some tokens.
161460	163260	But not everything was so simple.
163260	167900	I had a lot of SSRF vulnerabilities that were almost there, but weren't vulnerable to this easier approach.
169340	173480	Sometimes I'd have a Webhook where I could hand it a URL, and the server would even fetch the URL,
173480	176760	but not give me a response. This is called blind SSRF.
177760	182820	Other times the request in question would be a put request, which restricted what endpoints I could hit.
183080	187780	Sometimes you can mess with the request method by setting up an endpoint that redirects the target server around,
187780	188920	but that's hit or miss.
190160	194720	Other times you might get some data back, but it's validated against a specific content type,
194720	199680	or you only get back certain fields. Or even worse, it'll only accept HTTPS URLs.
201320	206360	But what we really want in order to exploit this stuff is a generic blind SSRF approach.
206360	209380	In other words, we'd like to see in the server a URL,
209380	212700	have it fire a payload at something internal like SMTP or Redis,
212700	217420	and get a security compromise just from that payload, without needing to see the response.
218740	220880	Here are some of the common approaches.
221000	227760	The issue is these are extremely platform-specific, to the point where I've never had any luck with these.
227880	231700	But there are some useful ideas in here, particularly in SNI injection.
231780	236640	You wouldn't think that TLS would be particularly useful, because its packets are mostly just encrypted data,
236640	241540	binary flags and other stuff an attacker doesn't have much control over, but it's not all that limited.
241540	246660	As OrangeSci noticed, the SNI, which is basically just the domain name, is part of the URL.
246660	250620	So if you can trick the victim into accepting a weird domain name and parsing it incorrectly,
251060	256000	you can include stuff like arbitrary bytes in there and smuggle stuff like SMTP commands.
256400	259860	This approach is dependent on a platform-specific URL parsing book.
260020	263400	But what if we had something that was inherent to the TLS protocol?
263600	268460	This is where my work starts. Let's look at a TLS packet and see what's in there for us to use.
269420	276420	As is often helpful when looking at protocols, we can open up Wireshark to see what happens in a TLS connection.
276700	281800	Here's the SNI, or server name indication, that was previously explored in Orange's talk.
282000	286540	His work involved putting new lines and SMTP commands into the section pointed to by the arrow here.
286720	291980	If you poke around, you'll see stuff like random strings, key shares, and other stuff that isn't useful for SSRF.
292240	296080	Why? Because the only part of this we can typically feed a server is a URL,
296080	301120	and the only part of the URL that will make it into the client-hello packet is the domain name that we provide the victim machine.
303120	307160	But there's a different way that we as an attacker can get payloads into client-hello messages.
307180	310480	It involves a couple of steps and is the main focus of this talk.
310740	315660	First, we send over a link to our own server, in this case jmatrix.com.
316040	321100	Then jmatrix.com responds with a valid server hello, but it contains our payload.
322620	327780	Now, it would be ideal if we as an attacker could get that payload that jmatrix.com sent the victim,
327780	330240	and then get the victim to send it somewhere internal.
330360	334680	But that raises a question. Is there such a field that we can use to deliver these payloads?
335480	341380	It might seem too good to be true, but TLS actually provides exactly that in the form of a session ID.
341600	344160	Most clients even persist this field for later use.
344500	347240	Session IDs are limited to 32 bytes, as you can see here,
347240	351600	but depending on the implementation, you might have session tickets.
351780	356460	This one is about 200 bytes, but these can be up to around 65 kilobytes.
357100	360940	Both session IDs and session tickets are mechanisms for a TLS client to go,
360940	363560	hey, remember that cryptographic key exchange we did earlier?
363560	365940	Let's just keep using that key in this new connection.
366260	371520	TLS 1.3 includes a slightly more complicated but similar mechanism called a pre-shared key identity,
371520	373680	which pretty much does the same thing for our purposes.
373680	377700	All of these are about optimization, since key exchanges can be time-consuming.
378000	387360	But they provide a way for a server to tell whatever is connecting to it to persist some data for later use,
387360	389300	almost like a cookie that lives in plain text.
389300	391820	So it's perfect for the SSRF attack we're trying to do.
393060	395020	Now, you might anticipate a problem here.
395500	401620	Obviously, if you go to google.com and then to apple.com, those TLS sessions are going to have distinct data from each other.
401620	404580	The same applies between google.com and localhost.
404640	410940	So we have a bit of a problem getting the target server to reuse the session when communicating with something internal.
412140	418680	But when I looked at both the TLS spec and popular session cache implementations, I saw this wasn't quite the case.
418680	422900	I first went to the curl source code, since libcurl is used by a lot of PHP stuff.
423160	429260	Sessions are keyed by the four properties here, which belong to this struct.
429260	431740	As you can see, none of these are the IP address.
432140	437520	This means that no matter what IP address jmatrix.com resolves to, curl will attempt to reuse the session.
437720	441040	This happens to be how just about everything else caches TLS sessions.
441260	449740	So if you establish a TLS session with jmatrix.com, whether it resolves to something on the internet or your own machine, your HTTPS client will not know the difference.
449880	456240	Since I, as an attacker, own jmatrix.com, I can combine all of this TLS stuff with a concept called DNS rebinding.
457580	463440	So I resolve the first request to 35.x.x.x, some server I control.
464840	470340	Then the target server picks up the payload from 35.x.x.x in the form of a session ticket.
472080	476660	After some time, I send the exact same URL, except the DNS entry has expired.
476740	484160	Again, since I control the DNS server, this time around I resolve jmatrix.com to something internal that I wouldn't normally have access to from the outside.
484160	486620	To simplify things, I'll just use localhost.
487800	492560	Once the DNS query finishes, the target server then makes an internal request with that payload.
494540	505220	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.
505340	508400	Here I'm showing a PSK identity that does a memcache insert.
509880	513140	And here's that same TCP stream, but just displayed raw.
513140	518300	This view shows the really important property of my approach to combining TLS with DNS rebinding.
518300	522200	You can get arbitrary characters to be sent, which includes new lines.
522260	528980	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.
530300	534300	And here's an exchange more typical of what you'd use to do real damage.
534320	540380	This is a value that in most Python memcached libraries will execute a shell command immediately once it's retrieved from a cache.
540380	548280	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.
548520	554340	Unfortunately, built-in serialization methods are also common RCE targets. We'll get to exploitation later.
555220	559120	But since this is pretty common, I ended up testing a fair amount of slides.
559120	566920	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.
567980	570240	So here are all the VMs I have on the internet.
570280	575640	Say for maybe some IP whitelisting, they need to be on the open internet so that the target boxes can reach them.
575840	585180	I've got a nameserver record pointing ssltest.jmatrix.com queries to the DNS server on the top left, which is just a Python script running on port 53.
585180	590080	It alternates between answering with the IP of the custom TLS server and localhost.
590680	595980	Then over there on the right, I have my custom TLS server, which is there to deliver my payloads via session tickets.
595980	599120	I configure those by just updating values in Redis.
599380	607740	But when testing it, it proved to be difficult to just go straight to localhost, because depending on what library is making the requests, I didn't know if SSL sessions were being cached.
609180	614760	To address this, I sometimes just ended up adding another box to see if the payload was being persisted.
614820	620880	If you're not familiar, Netcat can be set up to just listen for TCP connections and log the results.
620880	624840	If I saw my payload making it into the logs, I knew the general approach could work.
625120	630580	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.
631940	634020	And here are the links to all that I actually used.
634220	640380	A big chunk of the work was saved by just messing around with a pure Rust implementation of TLS, which is linked to here.
640560	642960	A big thanks goes out to everyone mentioned in this slide.
643040	647120	I wouldn't have had the time to do any of this work if not for the code they had put out there.
648980	655460	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.
655880	659800	I'll start off conceptually and then get to some examples along with another demo.
661560	663120	But here's the mullot I've got.
663400	666500	If you're in the middle of this diagram, you're generally vulnerable.
667520	673780	This top part refers to when you can send something a URL and it will fetch that URL, but you don't know of a way to exploit that behavior.
673780	679840	It's interesting because you would hope by now people would try to eliminate anything even remotely looking like SSRF.
679880	683040	But this pattern is in fact required by a few popular specs.
683260	689060	This is even common enough that I've seen bug bounties mention SSRF with no proven security impact as an excluded category.
689300	695840	But that's what this talk is about. Adding the security impact when you have just something that is just almost SSRF.
697040	699520	This one on the left sounds weird, but it's getting bigger.
699520	706140	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.
708080	715340	Unfortunately, there are quite a few HTTPS client libraries out there that support full-blown TLS session caching.
715520	718020	Here are a few that you may be wondering about.
718060	722340	I reported this as a vulnerability to some of these, but not all of the entries with yes.
722520	724120	And I haven't seen much traction.
724480	730180	Understandably, since fixing this requires diverging from the TLS spec, not a whole lot of people are eager to do so.
732060	735500	The thing you run into the most trouble with is this last circle.
735500	739600	Because you have to first do some recon to see what ports might be internally exposed on the server.
739900	745920	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.
747420	749960	Here are some examples of what you might be looking for there.
749960	753020	It's far from complete, but here are the most notable entries.
754660	761240	So now we'll go through a couple of exploitable examples of these TLS session-based SSRF vulnerabilities that I reported and got fixed.
762580	771060	Here's one from uTrack. 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.
771300	776680	It originated from uTrack's import feature, which normally wouldn't be easy to exploit, being blind SSRF.
777780	782940	But with my rebinding code, here's a section from the TLS packet I got uTrack to send itself.
783420	790740	This works because SMTP is a newline-delimited protocol, so just like memcache, you can embed working commands within a TLS ticket.
792920	794880	And here's what came of that packet.
794940	801500	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.
801500	808320	But it did get initiated by a TCP stream I got uTrack to send itself, so it's still pretty bad.
809700	811640	Here's the one I reported in Nextcloud.
812080	819880	The idea behind Nextcloud is a cool one. You set up a server and host files, and can even share them with other people's servers using a share URL like this.
821100	824220	But as it turns out, you can include port numbers in the share URL.
824220	832380	Now, since Nextcloud automatically puts HTTPS in there, normally there wouldn't be much SSRF potential, and it would have to be blind SSRF.
833460	836080	But luckily I was able to do just that.
836080	842140	So as a non-admin user, I could use my TLS for binding attack infrastructure to perform arbitrary writes on memcached.
844360	847920	After reporting this and working through the options, there weren't any great ones.
847920	851780	Because not all request libraries allow you to disable TLS sessions.
851780	856720	In this case, libcurl has the option, but it isn't exposed by PHP request libraries such as Guzzle.
857180	865360	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.
865740	869960	Nextcloud was still generous enough to give me a bounty, even though in my opinion this is libcurl's fault.
872000	878060	Since the last couple were just text slides, let's see a real demo now, from the perspective of a Django web developer getting phished.
878060	885280	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.
885500	890440	In the past, you had to get people to visit a fully malicious page to get anywhere with DNS for binding.
890640	893260	But with my work, you can do the same with just an image tag.
893380	898120	Because of that, you can phish people into RCE, even if they just view an email, but don't click any links.
898140	899240	Let's see that now.
900860	902820	And now for the actual demo.
904920	909580	So as you can see, we're pretending I'm a Django application developer running a typical app.
909760	911700	If we look at the app, it's pretty simple.
911700	916500	We can view a sloth emoji, but if we refresh too fast, the sloth needs to go to sleep.
916940	919040	And now for what happens when I get phished.
919300	925160	As you can see, I have received some perfectly legitimate emails, and I'm viewing them.
925160	933080	Normally, these image tags should be benign, but after viewing them, my sloth now opens a calculator via shell command.
933620	939580	That's because those image tags pointed to the domain with my binding setup, and a simple Python pickle payload.
944110	947870	So here's most of the source code of the example app I created.
947950	951730	You can pretty easily find apps that call django.core.cache or on GitHub,
951730	955730	but I didn't want to demo against a specific one, because that seems a little mean,
955730	959950	and I wouldn't want people launching actual phishing campaigns against such projects.
960050	962030	It's a little tough to assign blame here.
962190	964670	Nothing is really breaking from established safe practices,
964670	968470	but it's clear that there's a potential to compromise real-world developer laptops.
969930	973790	On that note, there's a lot more to do that I couldn't possibly do on my own.
974330	976810	These slides will be available online if you want to return to this,
976810	979710	and if you do anything interesting, I'd love to hear about it.
979970	983110	There are certainly a lot more potential vulnerabilities to explore.
983910	987550	So all of that is bad, but what can be done about it?
987570	990790	Let's start from the root of the problem, TLS clients.
992550	995450	Here's something I recommended to the Chromium team a while back.
995650	998850	We still aren't in agreement about whether or not this should be fixed,
998850	1002110	and my report was pretty hastily written, which probably didn't help things.
1002210	1006350	Essentially, I'd like to remove the ability for sessions to be resumed between servers.
1007350	1010170	But while the Chromium team has marked this as a won't-fix,
1010170	1014570	they did suggest an alternative that maintains support for resuming sessions across servers.
1014690	1019190	They probably care about that more than I do, but we can at least have the best of both worlds.
1019390	1025210	This last option of just partitioning based upon whether the address is something local is a pretty good compromise.
1025430	1029890	It wouldn't affect performance, but would protect against most of the attack scenarios I can think of.
1030230	1034890	But based on my experiences so far, I'm not hopeful that there's going to be much proactive effort
1034890	1038590	on the part of software packages that make HTTPS requests.
1038590	1044630	For most of the audience, it's more useful to know what's susceptible, and what layers of defense can be applied.
1045270	1050270	However, with all of this worth taking a step back to consider, is TLS session resumption even worth it?
1051710	1055510	There are other issues with it, a couple of which are shown here.
1055690	1061070	I'm not going to make the case that the industry as a whole should give up on this optimization,
1061070	1064010	but we should take a step back and see if this is a worthwhile trade-off.
1064050	1067670	We may, just like in the previous slide, find that the costs can be eliminated.
1067670	1071850	But if we find we can't tackle these problems, we need to weigh them against the benefits.
1072930	1076390	And here's the main benefit. You get a sizable performance improvement
1076390	1079850	on the small subset of packets that are TLS handshakes.
1079870	1083150	You probably care about this whenever you're in the position of serving up TLS.
1083430	1089250	Whatever percentage of CPU usage is due to TLS handshakes, you probably want to keep that low to minimize costs.
1091050	1093090	But if you're like me, you don't care.
1093290	1096950	I'm taking on all the security and privacy risk of session resumption,
1096950	1099970	but the amount that it saves on my power bill is pretty minimal.
1100150	1104690	Additionally, if you're running a web application, you might care about session resumption on incoming connections,
1104690	1108250	but when you're making external requests, it's probably not in your interests.
1108450	1113370	You're placing a lot of trust on random websites not to redirect you and on your local services.
1113570	1115470	So how might you turn it off?
1116890	1120570	Here's what I found. It's kind of sad when stuff forces you into this,
1120570	1126470	but at least as an internet user, you can pick Firefox and disable session identifiers if you're paranoid about this stuff.
1126470	1130350	If you're running a web application, you're a bit stuck, though. So what should you do?
1131530	1135310	First off, it's a good idea in general to run your outbound requests through a proxy,
1135310	1138790	especially if you're supporting webhooks or some other SSRF-prone feature.
1138870	1141930	But also reconsider your infrastructure decisions.
1142050	1149890	You'd be surprised to know just how much stuff is still set up in a way that is just one locally initiated TCP stream away from compromise.
1151190	1152870	But here are the general takeaways.
1152870	1156390	The thing I'd like to highlight is if you're just starting out in the offensive side of security,
1156390	1159690	I'd encourage you to look at the random standards and browser features that come out.
1159750	1165190	Even if you don't fully understand them at first, find something that seems interesting and start hacking around in Wireshark.
1165190	1172690	I know I didn't understand TLS at first, and I still don't really understand it very much after all of this.
1172690	1177510	But as an attacker, you really only need to understand the worst parts, and that's what this is all about.
1179270	1182810	And thank you. Here's my Twitter and a link to Latakora, where I work.
1182810	1187170	They're a great place to work and have been amazingly supportive of random research directions I take.
1187330	1188390	Definitely take a look.
