WEBVTT 00:00.000 --> 00:12.440 And I'm glad to welcome Jan Luca Varisco, who is going to talk about modern security features 00:12.440 --> 00:14.720 for web apps and the Pro Regions. 00:14.720 --> 00:15.720 Thank you very much. 00:15.720 --> 00:16.720 And hi. 00:16.720 --> 00:26.560 So, good afternoon everyone, glad to be here with you, just as a background before we move 00:26.560 --> 00:27.560 forward. 00:27.560 --> 00:28.560 I'm Jan Luca. 00:28.560 --> 00:34.880 I spent the last 20 years, both in the public and private sector, June Sutter, mostly, and 00:34.880 --> 00:40.720 they got interested over the last year's security and everything that actually entails. 00:40.720 --> 00:43.200 How can we make the web better from a security standpoint? 00:43.200 --> 00:45.520 So, happy to be here today with you. 00:45.520 --> 00:49.240 Now, today I'm going to try to answer this question. 00:49.240 --> 00:52.680 Did I know it's what actually keeps everybody awake at night? 00:52.680 --> 00:56.000 That is, how can we actually make the web? 00:56.000 --> 01:00.240 Now, can we fix the web not to be a scary place? 01:00.240 --> 01:06.000 Now, if I actually had to summarize where we are from a security standpoint in a single 01:06.000 --> 01:11.840 slide, but I'll try to go beyond that, is where three main pillars that I like to 01:11.840 --> 01:18.120 call actually the three capital scenes that are fundamentally encryption, injection, and 01:18.160 --> 01:20.360 a fundamental isolation. 01:20.360 --> 01:24.160 When it comes to encryption, of course, and isolation, I'm referring to the lack of 01:24.160 --> 01:30.800 it, if you actually want to shake the hand of whoever is actually sitting next to you, 01:30.800 --> 01:34.240 I think we did a very good job on the encryption side over the last years, so congrats 01:34.240 --> 01:36.040 everyone. 01:36.040 --> 01:41.680 On the injection side, there's still a lot to do in there, but things are getting better. 01:41.680 --> 01:46.440 And on the isolation side, so today the talk is going to be covering both the injection 01:46.480 --> 01:48.480 and the isolation part of it. 01:48.480 --> 01:54.640 Now, when we talk about injection, we start from the simplest of our nightmare, trust 01:54.640 --> 01:58.520 the scripting, and I'm pretty sure you are all familiar with trusted scripting and actually 01:58.520 --> 02:04.200 countless similar approaches and similar patterns that you might have seen when responding 02:04.200 --> 02:10.680 to the incident on your company, working on projects, without a peers, and fundamentally, 02:10.720 --> 02:17.920 we had to always address injections from a standpoint on how can we mitigate multiple 02:17.920 --> 02:19.720 classes of vulnerabilities in there. 02:19.720 --> 02:24.480 So, CRETSESS scripting being our like entry points in there. 02:24.480 --> 02:28.760 Isolation here is pretty interesting also because when you think about isolation, when 02:28.760 --> 02:35.400 you think about how can we fundamentally try to respond to new classes of flows? 02:35.400 --> 02:41.320 We had micro-protectual issues, you might recall spec, meltdown, the subsequent patches 02:41.320 --> 02:46.600 that got applied, how old your Linux kernel and your Linux machines became lower at some 02:46.600 --> 02:51.560 point in time, here are quite old, some additional set of patches, and fundamentally 02:51.560 --> 02:58.240 in here isolation is pretty interesting because we might be talking about same site isolation, 02:58.240 --> 03:01.840 same origin isolation, and several other type of isolation that we're going to be covering 03:01.840 --> 03:04.280 today. 03:04.280 --> 03:10.680 Now, it all actually started, if you make a request to any page of there, you can see an 03:10.680 --> 03:14.600 example in here, we can split the request between three of the areas that I wanted to 03:14.600 --> 03:16.640 cover today. 03:16.640 --> 03:20.840 Content security policy and trusted types that we're going to be covering today, the two 03:20.840 --> 03:26.760 headers you see out there, content security policy with the goal of blocking third-party 03:26.760 --> 03:32.440 app scripts from execution, and the third part of it that is pretty interesting is, 03:32.440 --> 03:39.640 how do we make isolation working to address cross-set three because forgery, access 03:39.640 --> 03:45.040 aside, and several other type of classes of vulnerability is that we might be wanting to 03:45.040 --> 03:50.200 address with fetch metadata headers and some other things that I will be going through 03:50.200 --> 03:51.200 today. 03:51.200 --> 03:56.600 Now, let's go into the isolation mechanism because I think we have a lot to unpack in here. 03:56.600 --> 04:01.800 Now, why do we even bother on isolation isolation is pretty interesting because we might 04:01.800 --> 04:07.840 have isolation when we consider attacking windows, and we will see what windows means, 04:07.840 --> 04:10.920 and when we see attacking on resources. 04:10.920 --> 04:17.800 Now, it's pretty interesting to see how you can do cross-set search and in general, leaking 04:17.800 --> 04:22.840 information from a given tab, from a given window of your browser, and that we want to 04:22.840 --> 04:28.240 address actually with how not to leak information, how not to attack, how actually to 04:28.240 --> 04:35.040 mitigate attacks at the resources level, and so the first things that I want you to start 04:35.040 --> 04:40.600 with is like we said, we might have three scenarios actually to address the same origin 04:40.600 --> 04:46.400 site, the same site in here, and actually the cross-site, same origin as you can imagine 04:46.480 --> 04:52.400 same URL, same path, I mean different paths from the same URL, but the schema is actually 04:52.400 --> 04:53.880 the same. 04:53.880 --> 05:00.680 Same site with potentially the same schema and actually your digital domains, what's interesting 05:00.680 --> 05:04.720 in here that we're going to be also addressing today is actually our cross-site might 05:04.720 --> 05:09.400 come and do, and that we mitigate all of those three, and what that actually does, origin 05:09.400 --> 05:12.440 versus sites, has to be along. 05:12.440 --> 05:17.680 Now, when we consider a relation for resources, there's a very nice things, how many 05:17.680 --> 05:22.960 people of you, I mean how many of you have deployed, for instance, fetch me today the 05:22.960 --> 05:30.040 request headers across your applications, it's a very no one, 1, 2, 3, 4, good, you're 05:30.040 --> 05:31.040 the best. 05:31.040 --> 05:37.400 So what's interesting in here is actually that we always consider ourselves to be in 05:37.400 --> 05:43.760 charge of taking decisions, granting decisions to the request, granting decisions to the 05:43.760 --> 05:49.520 clients, but what if actually we make the server itself, make those security decisions 05:49.520 --> 05:51.160 on our behalf. 05:51.160 --> 05:56.680 What if based on the source, based on the context of each HTTP request, we can consider, 05:56.680 --> 06:03.080 for instance, which website generates the request, for instance, what, record mode, the 06:03.080 --> 06:08.600 note in the type, and also anything with the type of request, and what if we can also 06:08.600 --> 06:13.520 consider the destination in there, what type of data are we talking about, what if we can 06:13.520 --> 06:20.600 instrument each of those requests to perform and behave differently across HTTP requests 06:20.600 --> 06:22.440 that we're going to be considering the site. 06:22.440 --> 06:27.600 Let's have a look at, for instance, this example, where when we call this URL, like this 06:27.600 --> 06:34.800 full JSON, at site.example, we are fundamentally setting three errors, set set site, 06:34.800 --> 06:38.000 set set mode, and actually the destination in there. 06:38.000 --> 06:41.400 Here we're starting to set to allow the same origin. 06:41.400 --> 06:46.000 Here we're starting to consider also our QURS policy, of course, policy, if you're 06:46.000 --> 06:47.000 allowed so. 06:47.000 --> 06:50.440 And then we're also defining what you do with the destination in there. 06:50.440 --> 06:57.240 Now let's consider, for instance, something where we might not want to allow to get through. 06:57.240 --> 07:03.720 We can set the thing with, we can instrument you had there to be behaving in a way that 07:03.720 --> 07:09.680 cross-site, for instance, is actually handled as such, and behaves differently to block 07:09.680 --> 07:13.440 for instance, that either request. 07:13.440 --> 07:17.360 And even request is pretty interesting, because over the last couple of years, we've seen 07:17.360 --> 07:24.480 a lot of C-O-O-P issues called cross-aging opener policy, where, fundamentally, if you 07:24.480 --> 07:32.240 look at the screen here, we fundamentally define an opener, like we open a window, we sense 07:32.240 --> 07:37.840 the messages, we count whatever we want to count, and then we allow the opener itself 07:37.840 --> 07:41.600 to open a new window to any victim website. 07:41.600 --> 07:48.520 And if we're not actually careful with that, we can, interestingly, control windows and 07:48.520 --> 07:50.520 taps with windows opener. 07:50.520 --> 07:54.480 I'm sure if you do a lot of web applications, scanning, a lot of web application security, 07:54.480 --> 07:59.680 you might have seen a lot of the cross-aging opener policy being flagged such. 07:59.680 --> 08:05.240 It's pretty interesting in here, because based on the policy you're going to be setting, 08:05.240 --> 08:09.280 you might be able to call from a given tap that might be a legitimate. 08:09.280 --> 08:13.160 You might be able to redirect that user to evil page. 08:13.160 --> 08:18.280 What you want to make sure there is that with the cross-aging opener policy, you define 08:18.280 --> 08:24.880 what kind of behavior, like same origin, for instance, the opener should be allowing for. 08:24.880 --> 08:29.520 From a given tab, you might be calling another application if and only within the same 08:29.520 --> 08:30.520 origin. 08:30.520 --> 08:38.720 You might not want to allow WWWGoogle.com to have an opener policy allowing you to go to www.donclicment 08:38.720 --> 08:39.720 .com. 08:39.720 --> 08:44.880 Now, what can we also do to do injection defenses? 08:44.880 --> 08:50.160 Trusted types, it's something that actually, as it can imagine in here, we want to solve 08:50.160 --> 08:55.120 several types of process scripting we set, and Dom, process scripting is one of the things 08:55.120 --> 09:04.120 that makes, means behaving the Dom API pretty interesting, because it allows us to fundamentally 09:04.120 --> 09:10.600 use control strings, and we need to make sure that those strings, when converted into code, 09:10.600 --> 09:12.600 are sanitized. 09:12.600 --> 09:17.160 And when you look at the here, for instance, at the given URL, you might be wanting to address 09:17.160 --> 09:21.160 that process scripting in the Dom and handle it as such. 09:21.160 --> 09:23.800 Now, Trusted types is a very good idea. 09:23.800 --> 09:30.240 It's been around for a couple of years, actually several years, to be honest with you. 09:30.320 --> 09:36.600 What's relevant for this is that any HTML string, any script string, any URL, that you might 09:36.600 --> 09:43.140 be triggering, get fundamentally typed into three new types, Trusted HTML, Trusted 09:43.140 --> 09:45.360 Script, and Trusted Script URL. 09:45.360 --> 09:50.760 What you're getting there is that when you force Trusted types, those are fundamentally 09:50.760 --> 09:58.840 sanitized process and handled in a more secure way from a Dom perspective. 09:58.840 --> 10:04.040 So if we want to address any type of process scripting, like a Dom level, we can use Trusted 10:04.040 --> 10:08.840 types to accepting objects in the given way we expect you. 10:08.840 --> 10:13.720 You can set up policies as you can imagine in here where you create validation rules. 10:13.720 --> 10:19.920 You can actually use those policies to create those objects, define as Trusted types. 10:19.920 --> 10:26.400 And then you can enforce that policy setting, the constituency policy had such so that 10:26.400 --> 10:29.240 the Trusted types are kept along. 10:29.240 --> 10:34.480 Now, you might be wondering, how do I get an understanding from a reporting perspective 10:34.480 --> 10:40.400 on whether my rollouts of Trusted types are actually misbehaving my web application. 10:40.400 --> 10:46.580 You can also deploy them with a reporting mode where you get a lot of information from 10:46.580 --> 10:49.480 Trusted types information that we just printed in there. 10:49.480 --> 10:53.920 So you all set in reporting mode, for instance, the constituency policy. 10:53.920 --> 11:00.800 You define a such where you might be requesting Trusted types for a type script, for instance. 11:00.800 --> 11:07.480 And then we might having actually the Dom to accept report findings and strings in here, 11:07.480 --> 11:12.040 but then we want to make sure that we want to accept for instance Trusted types and handle 11:12.040 --> 11:14.920 them as such. 11:14.920 --> 11:21.360 If we need to summarize in here how Trusted types behave, for instance, you have to simplify 11:21.360 --> 11:27.040 security reviews, so you need to dramatically reduce the amount of time spent on code 11:27.040 --> 11:30.160 base and handle that code base as such. 11:30.160 --> 11:35.360 And then you can implement the Trusted types and reporting things as part of your security 11:35.360 --> 11:38.480 validation pipeline that you might have established. 11:38.480 --> 11:47.360 Now, this is all interesting because, fundamentally, we all came back to our best friend 11:47.360 --> 11:49.600 that is content security policies. 11:49.600 --> 11:55.400 And content security policies, let's think about content security policy level free, for instance, 11:55.400 --> 11:58.320 comes actually with a very big challenge. 11:58.320 --> 12:04.280 Now, CSP policies have been around for a while, there are strong defense in that mechanism. 12:04.280 --> 12:10.520 They're not bulletproof as we will see in a while, but they are in did something that 12:10.520 --> 12:13.440 do work against trusted scripting. 12:13.440 --> 12:19.960 And we can control them with scripts, scripts can get executed, plugins can be loaded. 12:19.960 --> 12:25.400 And it's actually not sold in the main problem we're here for, that is, it's keeping 12:25.400 --> 12:27.120 or fixing bugs. 12:27.120 --> 12:33.040 Now, enabling a content security policy is, why do we so scape today? 12:33.040 --> 12:35.280 I'm pretty sure many of you did that. 12:35.280 --> 12:40.520 You can enable that in reporting on remote, you start collecting CSP reports, you start understanding 12:40.520 --> 12:45.920 how your scripts, how all the things and types you're loading, you're actually loading 12:45.920 --> 12:51.160 into application behave, and then you can, of course, enforce it. 12:51.160 --> 12:58.200 Now the problem is that very easily your web application is going to be looking like this. 12:58.200 --> 13:04.320 I'm not a fan of allow lists, and you should be either because fundamentally, it's not 13:04.320 --> 13:05.320 going to work. 13:05.320 --> 13:09.520 Allow list is going to be prone to errors, and allow list is not going to make it in 13:09.520 --> 13:15.320 a way that it's maintainable, as I can see here is the mess, I'm sure you spend a lot 13:15.320 --> 13:21.000 of time into CSP policies that were bigger probably than your web code base, and CSP 13:21.000 --> 13:26.000 policies are fundamentally something we shouldn't be behaving on with an allow list approach. 13:26.000 --> 13:32.080 Now, the allow list approach though, it's actually pretty good at blocking third-party 13:32.080 --> 13:37.880 JavaScript, because fundamentally we're going to be defining whatever we want, and we're 13:37.880 --> 13:41.360 going to be allowing one, two, three, hundred. 13:41.360 --> 13:44.960 But then the problem is that it's not maintainable, as we said, and it's not a strong 13:44.960 --> 13:55.440 mitigation against trusted scripting, because CDN, because common URLs, because many 13:55.440 --> 14:02.560 assets that fundamentally cost several type of resources make things pretty interesting. 14:02.560 --> 14:07.120 And so my advising here, of course, I'm pretty sure you know already, is to fundamentally 14:07.120 --> 14:13.560 not allow the list things and not rely on them for CSP policies. 14:13.560 --> 14:20.520 Now, let's have a look at how to bypass this, I mean, how bypasses are applied over CSP 14:20.520 --> 14:21.520 policies. 14:21.520 --> 14:29.200 If you look at several of this CSP policies that can be bypassed, you will see that it might 14:29.200 --> 14:34.440 be a configuration issue, it might be an allow list problem, like we said, it might also 14:34.440 --> 14:42.160 be that we might be enabling a library that fundamentally brings in a lot of tax 14:42.160 --> 14:49.560 surface, and it might also be things that don't make that allow list approach maintainable 14:49.560 --> 14:50.400 at all. 14:50.400 --> 14:55.520 There's several ways to, and you might have seen also a lot of the bug bounces out there 14:55.520 --> 14:57.880 by passing a lot of the CSP policies in there. 14:57.880 --> 15:00.360 So there's a solution for that. 15:00.360 --> 15:06.480 There's a solution for that that is fundamentally what if, instead of handling something 15:06.480 --> 15:12.040 that the attacker also can predict, we use actually Nons, and we use Nons that are fundamentally 15:12.040 --> 15:17.920 generated by something that is like a random number, random ideas, and the likes, and 15:17.920 --> 15:24.400 the attacker itself, it's not going to be able to inject that ID on their side. 15:24.400 --> 15:29.560 It's not going to be able to, I mean, when you, when you actually enforce the Nons part 15:29.560 --> 15:36.240 of it, the attacker is not going to be able to inject that and hence, inject the script without 15:36.240 --> 15:39.240 the Nons will be fundamentally blocked in the browser. 15:39.240 --> 15:42.780 So even if you get an injection without a proper Nons that is set on the server side 15:42.820 --> 15:48.020 or the application side, you can see in here that you will not be able to execute that. 15:48.020 --> 15:53.580 And that's where I actually, not only the proof, but way better than it used to be before. 15:53.580 --> 15:59.380 Now, the problem with that is that, from a maintenance perspective, actually, you might 15:59.380 --> 16:04.420 have to do a lot of refactoring, and a lot of third-party is created, widgets, and the likes, 16:04.420 --> 16:09.340 you might see a lot of violations into your report. 16:09.340 --> 16:15.220 And so it has to be done with actually this kind of BDT and maintenance of BDT mind, 16:15.220 --> 16:18.660 and it's not quite straightforward out there. 16:18.660 --> 16:22.460 So we can go the extra mile, and we can do strict dynamic interferes. 16:22.460 --> 16:27.860 So script acts, we might be wanting to cover on these scripts, and we might be wanting to 16:27.860 --> 16:33.860 make sure that on these script acts in response body are actually needing the Nons attribute. 16:33.860 --> 16:38.060 Not all scripts, not all the includes that we do in there. 16:38.060 --> 16:42.700 So third-party scripts are validated, and also the potentially larger refactoring it's 16:42.700 --> 16:47.940 taken care of. 16:47.940 --> 16:50.980 Now, how do I deploy this? 16:50.980 --> 16:53.660 First of all, you don't want to actually break your stuff. 16:53.660 --> 16:56.980 So you remove all the CSV blockers that you might have. 16:56.980 --> 17:03.740 You actually start heading, as we said, the script acts across your CSV Nons' into the 17:03.740 --> 17:05.580 script acts, and you start there. 17:05.580 --> 17:10.900 You can also do the CSV policy reporting mode, so before turning and sleeping the 17:10.900 --> 17:16.620 kind on your production application, you start actually light with a fundamentally enforcing 17:16.620 --> 17:18.620 it in reporting on the mode. 17:18.620 --> 17:24.460 I need to go a bit faster, because we're getting over time. 17:24.460 --> 17:25.980 So I'm going to skip a bit of this. 17:25.980 --> 17:31.660 I'm going to give you the back, but fundamentally the way this works, removing actually the 17:31.660 --> 17:39.340 CSV blockers, is if we do it in a strong way, like inline events, like this one, 17:39.340 --> 17:43.140 I'm going to be becoming, as you can see, the refactoring here, we're going to be covering 17:43.140 --> 17:45.260 at the way we load. 17:45.260 --> 17:51.220 We do the list load of JavaScript calls, or any type of script request that's fundamentally 17:51.220 --> 17:56.540 collapsing external URLs, external scripts, or execute codes in there. 17:56.540 --> 18:01.820 And when we set it up, we can see how we can have a strong, stronger, it sounds like a 18:01.820 --> 18:08.540 buff punk song, but we can add actually a very interesting approach into, we set a CSV 18:08.540 --> 18:14.100 policy that has strict dynamic, but allows unsafe evil. 18:14.100 --> 18:18.940 We go for strict dynamic that it is, and then we even remove strict dynamic to the 18:18.940 --> 18:19.940 strongest one. 18:19.940 --> 18:24.660 But to do that, we need to have a migration path towards actually the CSV policy. 18:24.660 --> 18:30.060 And so my advice in here is that side would report in mode and get it from there. 18:30.060 --> 18:35.020 And now what's making things even more interesting is that you can use CSV ashes for 18:35.020 --> 18:41.580 static HTML, so if you're any of parts of your site use static HTML, you can actually 18:41.580 --> 18:46.780 use those ashes for the, again, in here, you need to compute and you need to account 18:46.780 --> 18:53.420 for the tags in a way that is capable and probably bring, broadly, from your CICD pipeline 18:53.420 --> 18:54.420 in there. 18:54.420 --> 19:00.380 Now, I want to complete the session today with something that is launching at the end 19:00.380 --> 19:02.660 of the month. 19:02.660 --> 19:07.740 When I first announced that I was making this talk, everybody from OZL and reached 19:07.740 --> 19:12.260 out to me and said, hey, you need to, you actually need to make sure that you mention 19:12.300 --> 19:15.580 the sanitizer API, it's coming live this month. 19:15.580 --> 19:19.980 And it's saying sanitizer API is pretty cool to be honest with you. 19:19.980 --> 19:25.620 Scentizer API is fundamentally taking the pain away from you in regards to taking strings 19:25.620 --> 19:33.340 of HTML, for instance, in fields throughout unwanted elements, stripping things, sanitizing 19:33.340 --> 19:39.740 each timeline to days and all the likes, and this API, it's actually shipping at the end 19:39.740 --> 19:44.300 of the month, it's already available in Mozilla nightly, it's available in Chrome, where 19:44.300 --> 19:48.660 the experimental web feature is enabled, and as you can see in the spreadsheet in here, 19:48.660 --> 19:53.700 all you have to do on the left side is actually what makes things on the right side to 19:53.700 --> 19:55.100 be mitigated. 19:55.100 --> 20:00.220 The typical traditional simplest cross-scripting that you see on the right side, it's 20:00.220 --> 20:05.500 fundamentally mitigated by, for the first time also, we have a very simple method that is 20:05.500 --> 20:11.980 at HTML, there should be quite straightforward to set, and it allows that for sanitizing 20:11.980 --> 20:20.380 that when you develop, when you make things much simpler in a much secure way to sanitize 20:20.380 --> 20:25.860 using that sanitize API, you can make things in a way that, for instance, all the unwanted 20:25.860 --> 20:31.020 HTML entities, stripping characters, stripping tags, and the likes can be handled very 20:31.020 --> 20:32.660 simple from there. 20:32.660 --> 20:38.980 If you have a custom policy, you can also use the sanitizer API and pass sanitizer content 20:38.980 --> 20:43.740 to work it in a way that you can be much more flexible than the traditional normal behavior 20:43.740 --> 20:44.740 that you're going to be having. 20:44.740 --> 20:48.180 I want to thank you, and I wish you a good day.