 Alright. So hi. I'm Jeff from Vancouver, British Columbia, Canada. I do a few Dribble modules. A few of them are up there, a couple of which I'll be mentioning today, one I'm talking about today. If you want to find me online, I'm on Dribble.org as Gapel or you can find me on Twitter as well. I work at MyPlanet, which is from Toronto, Ontario, Canada. It's a pretty cool place. Talking about headers today, I figured I'd start with a couple simple ones. This one is X content type options. Since it starts with an X, it's actually not a standard header, but this addresses an issue in the past of what browsers try to be pretty lenient in the content they accept. So if you write a script element on your page and link it to something that's not JavaScript, the browser will actually try and still execute it, which might not be a good thing if it's not JavaScript. It might not be something that's supposed to execute. But the browser is going to try and do that in trusted anyways. This is one that Dribble actually handles for you by default. It sets a value to no sniff, which tells the browser to say, hey, if you get a script element or you get a style element that's supposed to link to a style sheet, and the server doesn't tell you that that's actually the content you accept, don't run it. That protects you from a few different options, a few different things. Like I said, Dribble helps you out by default. Make sure that you're kind of doing a safe thing. And I think browsers are actually trying to pull back this behavior so that this header won't be needed in the future, but it's safe to start with. Another one that Dribble gives you by default is frame options. The risk here is something called a click-jacking attack, where if another site puts your website in an iframe, the user sees your website and can try and interact with it, but they can potentially be interacting with an invisible layer on top. So this could be fairly innocuous if they're trying to click a button on your website, think they're doing one thing, and the website that wraps your page is actually doing something else, or it could be something like they think they're typing in their username and password, and that allows them to steal credentials. So there's a few options to kind of restrict this. The default that Dribble goes with is same origin to say your site is the only site that's allowed to have itself in an iframe. You can be more strict. In a lot of cases today, you don't use or don't need iframes, and you can say outright, my page should never be in an iframe. But there is other options. In some cases, you actually are providing an iframe that should be accessible to other locations, and you can target that to say this is the only website that should be able to include my site in an iframe, and this can be done per page. So if you're providing a service to another website or to different service providers, you can say each one is only allowed to iframe the own specific page. So Dribble sets this by default to same origin, but when it sets it, it does it so that it's overridable. So if you want to make this more restrict or not, it lets you do that. Another browser feature is cross-site scripting protection. This is built into Chrome, Safari, and Internet Explorer. Firefox doesn't do this, but it has a couple heuristics to detect, you know, is there a potential cross-site scripting attack on this website? So the default is one, where it goes, okay, if I think something might be running that's bad, I'm just not going to execute that portion of code. That can potentially cause a few problems, though. Maybe it's actually blocking something legitimate, or the other challenge is it's silently blocking it by default. So if something's not executing, you or the user might not be aware of it, but it could actually break some functionality on your website. So a lot of cases recommend that you go to the stricter mode with mode block, and that means that if the kind of the browser heuristic detects that, hey, something weird is going on here, it actually blocks the entire page, which makes it a lot more obvious that something is going wrong and you need to fix it. You might not necessarily be aware of that, though, is the problem. So Chrome adds another option where you can actually send kind of a log of, hey, this browser blocked something, send it to the server, and the server will have a record of, like, hey, content is getting blocked, you probably need to look at this page, whether it's something just, you know, injected innocuous, you need to clean up the page, or the browser is detecting something that shouldn't, and you need to make a larger change. Refer policy is a little bit different, because it's more about the information that you share. Whenever you link between pages on the website, each request says, hey, what sent me here in a refer header? And that also includes if it's a linked request like an image, or you're calling out to a content delivery network for your styles or your scripts. Each of those are going to be able to tell what pages on your website are sending information. And if your URL contains something that maybe should be private, you might want to restrict where that gets sent. Do you want your CDN to know how many users and what their user names are on their website, because their user profiles are linking to, you know, this style sheet that's somewhere else? So this header gives you a few options. From the completely restrictive no refer to say, never send a refer header at all, to the most permissive of unsafe URL of any time you're sending a request, if it has a refer, that is my site. Send the full information. And various ones in the middle. The default, if you don't set it, is basically equivalent to a no refer when downgrade. So that if you're going from a secure web page to an unsecure web page, no refer is sent. But as long as you're going from unsecure to unsecure or secure to another secure web page, then it'll include that header. One of the ones that I think is most interesting example is strict origin when cross origin. So that if you're going within your own website, it sends all of the information. Page two knows that it was sent from page one. But if you're linking off site, it hides that path. So if you link to Google or anywhere else on the website, they know that your website sends a request to them, but they don't know which page it is. And then because it's strict, there's the two options, strict or not. The strict one says that it has to be done over the same protocol as well. So if you're linking from a secure page to an unsecure page, it goes, I don't want to expose this information over an unsecure connection, and it completely excludes it. To implement any of these headers, the best case is probably you want to do it within Drupal itself. Since the request is in Drupal 8 is now the responsibility kind of the symphony components, you have to use an invent subscriber as opposed to a hook. But they're fairly easy to implement. First you just register it as a service. The important part here is tagging it as an invent subscriber so that Drupal knows I have to ask this when I need to act or when I'm doing certain things. You can pass it arguments and here I have the example of you're passing it just general site configuration to make some decisions. But any Drupal service can be included here to give it information. And then the actual class is pretty simple as well. You're implementing the invent subscriber interface, which you can see from the use statement is from symphony component. You're telling it I want to act whenever Drupal is sending a response. And then I want to run a particular method. In this case, all it's doing is adding a header. And this is strictly setting that header. It will overwrite any previously one. So for example, Drupal setting the frame options header. This is the way that you can say I want to have the most strict frame options header and Drupal core will respect that won't overwrite it. So one of the other big things that's happening is the internet in general is moving to kind of a secure by default policy. Users should be able to have the assumption that their information between their browser and the website that they're looking at is private. No one else can listen to it or intercept it. Chrome and Firefox are being most strict about this, Chrome especially. Right now, if you go to a website that doesn't have a secure certificate and try and type in a password, they give you a warning to say, hey, this is information you probably don't want to share to anyone in between. And you should probably be concerned that anyone can listen in. If you're typing this in in a coffee shop, someone might be aware of what your password is and could then access your account. And they're bumping this up. Next month, Chrome is actually going to give a warning on any form input on your website. So if you just have a search, users should be able to expect that no one can listen into what they're searching on your website. And so Chrome will pop up a warning as well within Drupal if you have a view with an exposed filter. That's a form input. It sends additional information back to the browser and people probably don't want that able to be listened into unexposed. So there's a couple of options. You know, for securing a website, Let's Encrypt is a free automated service that provides domain-validated certificates. So if you have control over your server, if you run it on a VPS, for example, they provide a command line script and Chrome tools that will perpetually keep your certificate up to date. A lot of services are starting to integrate it. Pantheon is one where you can get a free certificate just by clicking a button and turning it on and through the very interface. And some hosts like Dreamhost, which is a shared hosting provider integrated as well, hopefully more in the future. Or Cloudflare is a service that can wrap your website and they provide free certificates as well. So where strict transport security comes in is that when someone first goes to your website, they just type in your domain. They have no idea whether it's unsecured or secured. And you can do a redirect, but that first request of the website is always sent unsecured because of the browser by default puts HTTP at the front and that's it. They get the redirect to the secure connection and then their browsing session is fine. But when they go to the website again, they type in the domain name, the browser adds it without the pass at the beginning, and they're sending another unsecured request. So the strict transport security is a way for you to add a header that says, if you ever come back to this website, expect that it will have a secure certificate and don't make any requests that aren't secure. And then in addition, if there's a problem with the certificate, if you don't use something like Let's Encrypt that automatically renews it for you and it expires, the browser goes, hey, something really big is probably wrong. And you can't just go, hey, I want to skip this warning. Because the browser knows this is probably something that shouldn't just be skipped. It's pretty easy to set. My recommendation, if possible, so like on my own servers, I run this, I put this directly in the virtual host configuration right alongside where I set the certificates. If that's not an option for you, depending on your host, you can also set this in your HD access files or directly in Dribble itself. I just like to put it next to the certificate because they are related. And then I get to the big one, is content security policy. One of the most common security vulnerabilities on the web is cross-site scripting, as I mentioned earlier. And it can be pretty innocuous. The basic test of it is, can you put in just an inline alert onto your page? And does it pop up my message? You know, this doesn't risk much, but you still don't want to allow this. If an administrator is on your website that has an inline JavaScript, that JavaScript can act as that administrative user is or similar to the click-jacking attack if any user goes to the website and there's inline JavaScript that was put there maliciously on your login page, someone can extract credentials from those users, learn their passwords, get access to your site, or if they reuse that password, they should get access to more from that user, log into their email and other things. So content security policy gives you the option to say, I don't want to allow that. This is a screenshot of the browser console that's saying, this browser knows that I shouldn't be able to run inline JavaScript so that it just skips over it. And it gives a warning to say, hey, there was invalid JavaScript on this page. I'm not running it. It's a little bit more expansive than that. There's actually quite a few options. In the case of the previous example, it's script source where you can say, hey, I only want to allow JavaScript from a certain location to be able to run. You can include that for CSS, which also has some attacks that are possible. You can restrict images to say, well, I only want to allow images from my own domain, like I believe Drupal.org does this, where it doesn't allow links to external images. Connect source actually deals with APIs. So if your site connects, makes an HTTP request to an external service, you can restrict where a browser is able to send any information or make any requests. And frame source is basically the standardization of that earlier frame header, where you can say, what sites are allowed to put my site in a web frame? And then there's also a child source one that says, what sites are allowed to be in an iframe on my own website? So there's a bunch of different options here to give very specific ones. And then there's kind of a generic wrapper around it that is default source. To say, by default, I only want things to be valid if they come from my own website. It also allows a few other options that are pretty helpful. Upgrade insecure requests. It's less common today, but in the past there was mixed content warnings. If your secure website linked to an image on an unsecure domain, the browser would go, hey, something's weird about this. There's a bit of a warning. In the past, you could opt in to allow those or not. Some browsers blocked them. Upgrade insecure requests says to the browser, I want everything to go over to a secure connection. So automatically change it to an HTTPS request, even if it's HTTP. And that applies whether it's a link to your own domain or any other domain. There's the option, there's the possibility that that can break things if it's linking to another site that doesn't enable security. But at the very least, it doesn't ensure that everything goes over a secure connection. And then the last one that I've got up there is report ERI. Similarly, as I mentioned before, with the XSS protection is, what if something is blocked? How are you going to potentially be aware of it? Report ERI tells the browser that if anything is blocked, it should actually notify you by sending a JSON object to a location on your website so that you can actually log and process those to know whether someone is trying to inject anything on your website or alternately if just something is misconfigured and you're blocking something that you do actually want to allow. There's a few keywords that you can apply. You can outright block things. So for example, if you don't want to allow JavaScript at all in your website, you can add this header and say, I want no JavaScript at all. Some of the other ones, maybe that's more appropriate for iframes to say I don't want to allow my site in an iframe or I don't want any iframes included on my website so that content editors can't add anything. Self goes to the same domain, so you're saying I want to allow JavaScript as long as it comes from the same domain as the page itself. The star is basically and everything is allowed. So any domain is allowed, but the one restriction is that doesn't include inline scripts. So if someone was able to add some sort of random JavaScript into a text box on your website, even if it's inserted, that's going to be blocked even if external requests to any content delivery network are allowed. So you have to specifically opt in to say, I want to allow inline JavaScript or style sheets, or I'm going to leave that off and they'll be blocked by default. And then the other one is eval, especially for JavaScript, where it's kind of dynamically created code in JavaScript itself. So that's something that is maybe less used today, but gives you a little bit of protection about certain kind of JavaScript attacks just even if you're limiting to allow inline script as well. You can specify domains. So for example, if you're linking to a particular content delivery network for external JavaScript on your website or linking to certain locations for style sheets and images, you can use wild cards for subdomains. So if you have a network of sites, you don't have to list every single domain in it. You can just list your main domain with a wild card. And then you can actually limit protocols as well. So this would be less important if you were using that upgrade in secure requests property. But in here you can say I only want to allow connections to a website if they go over a encrypted connection, or I just want to allow requests in general with just the protocol in the colon to say that they have to come from a secure connection. This obviously can get a little long. This example is from Drupal release state.com, which I built before I understood this header, so it has to allow unsafe online still because I didn't refactor that out. It needs to include the content delivery networks to load jQuery, Bootstrap, a Google API to be able to connect to Google Analytics. But it doesn't always have to be that complicated. And then again this header is only set on your HTML pages as well, so not every request is going to have to send this additional information. And then hopefully with HTTP2 your browser can reuse connections, and it's actually only setting this header once, and then on subsequent requests it's saying hey, I just want to send this header again, and it's actually only like a single byte each time. As I mentioned with the report URI, there is a risk that you're going to block something that you don't want to. So there is a report-only version of the header, so we can start out with a very lenient one to say I want to allow JavaScript to link to anywhere. I'm going to allow inline because I know I have some stuff, but I'm trying to get rid of it. Do a report if anything is actually blocked, and then you can have a more restrictive one that's in report-only mode. So in this case I'm going to restrict it to self, and then any time the web page loads it's going to apply the lenient restrictions and then report on the less lenient restrictions. So if anything else comes up it's going to give you a report but not actually block it from executing so that it doesn't affect the user or the functionality of your website. And then one of the cool things that I think that you can do with this is that you can actually start to segment your things. So for example on a Drupal website your files directory both has your aggregate files and user uploaded files. And you don't want your user uploaded files to include a JavaScript file that can be included on your website because that's essentially a cross-site scripting attack as well. So you can actually start to separate it out to say I have specific domains with vetted JavaScript, vetted style sheets, and I only want to allow those to execute from a particular domain. And as well I've got an example here. If I only want to allow files or images to be linked if they load directly from you know core or a module or their user uploaded file I don't want anything off my website. So integrating this with Drupal. Drupal 8 does a couple of important things. One is that core doesn't do any inline JavaScript itself. Previously in Drupal 7 the Drupal settings was added through an inline function. That's actually changed in Drupal 8 so it isn't. So out of the box with Drupal you can do a default source self and it won't block things, won't restrict things. And then the other component is that everything is added through a library's definition. So when you're building your module it has to prespecify these are all of the JavaScript and CSS files that I'm going to load onto my website. Which allows to make an automated policy to say I know beforehand everything that should be valid on my website restricted to only those things. So once I'm giving a presentation on it I figured I have to actually build this. So I have an alpha version of the module that applies a report only header and actually does do that pull it in from libraries. Which is a great start. Unfortunately parts of the web don't like this. Google Analytics is one example. This is their recommended JavaScript and they tell you to just paste this into the head of your website. And then the other problem is like you can wrap this in Drupal, add it into a local file that's fine. But it dynamically loads its own separate JavaScript file and the library system has no way of knowing that this exists. Thankfully in this case they actually do provide you with an alternative. You can wrap the inline script here into something local to Drupal and then you can include the file within JavaScript. The first version really only exists to support Internet Explorer 9 and previous which aren't supported anymore. So hopefully more services move to this structure where they provide snippets and direct links to be able to create content security policies for websites to make them secure. This is one of the reasons why I decided it was a good idea to rewrite one of the top 25 Drupal modules to make a version that actually does work with content security policy that does use that second set that define it in the libraries so that you could turn on an automated content security policy module and not have to worry about your analytics just breaking. It does have some things that are probably important to continue on. In finish right now it doesn't have any way to handle that logging. It doesn't expose whether it's automated policy is failing in any means. The other problem is that it only works for script and styles. So hopefully it needs an API so that other modules can say I need to be able to load an iframe. I need to be able to connect to an external service. Don't block me from being able to do this. And then the last one is manual configuration for things like the image sources. The module is never going to be able to make a decision of does the administrator of this website want to be able to link to external images or not. So that's something that's going to have to be a configurable option in the interface and I just haven't had the time to do that yet. So I know I ran through a lot of things quickly. You can see my presentation online. It does have a bunch of resources for each of the sections that I went over. Links to where you can find out the headers and some articles to learn more about them. As well as some extra slides that I had cut out. Contribution sprints are tomorrow. And I would love to hear what you think about my session. So if you have any feedback, please go to the event website and let me know what you think. As well as for DrupalCon itself. Thank you. I think I have probably a minute for questions, but I know I'm running late here and I don't want to eat into the next presentation's time. Hi, a while back I was reported that opening a new window of new tap gives the new window or tap a partial access to the DOM of the previous page. So it can replace for instance the location. Are there any things right now available to combat that? Or would you just push the no opener into the link in the HTML? So yeah, there is the no opener property on HTML links and that's part of content security policy itself so that you can actually specify through the policy that the page should disown any openers as well. So that works from the header and you don't have to put it in the HTML anymore on the HREF, right? Yeah, because if you're linking to another page and you want to exclude the opener, it's the responsibility of the linking page, whereas content security policy allows to move that responsibility to the target page to be able to restrict that. Thanks. So there's definitely a whole lot more options in content security policy. Not all of them are available yet. It's actually on its third version. CSP2 is largely implemented in Chrome and Firefox, but there's additional options that are going to be enabled in the future to restrict more things like that as well. Yeah, so basically for still supporting IE11, you will still have to put it in the HREF, probably. Yeah, that would be an example of Internet Explorer 11 and potentially Edge, but hopefully Edge gets updated in the same manner of... Thank you.