 Okay, so it's quarter of when we get started, so I have time at the end for questions. This is 10 ways Drupal 8 is more secure, hopefully this is the session you want to be in. This is the 10 ways, we're done. No, actually, so this is what I'll cover, so I'll talk about number one, twig templates, PHP input filter, config management, user content entry, user sessions, cross-site request forgery tokens, trusted host patterns, SQL, limiting to single statements, click-jacking, and the core JavaScript API, so this will be the 10 things I'll cover that we basically were conscious efforts to make Drupal 8 more secure than past versions of Drupal. So who am I, if you don't know me already, I have been a Drupal core contributor to Drupal 5, 6, 7, and 8, a member of the Drupal security team. I work now for Biaraft, which is why I'm wearing this T-shirt, on the engineering team, and I actually helped implement several of the features in this talk, so in the question section if you want more background, I might have it. I also help organize Drupal Camp in New Jersey, which is a great event. If you're in the states nearby, I recommend coming. It should be about the beginning of February of this coming year. So the 10 ways that I'm going to talk about it, I'm going to put in the context of the top 10 lists from OWASP. So OWASP is the Open Web Application Security Project. If you have not already looked at their website or don't know about it, you should go there. It has self-study materials, best practices, cheat sheets, all kinds of great stuff for anyone developing web applications who cares about security. They also have software tools like a Zap Proxy, which allows you to intercept requests and mess with them and potentially hack your application. And so they also published the OWASP top 10. The current version was published in 2013. They're about to update it for 2017, but it won't be very different from the one I'm showing you. And basically, this is sort of a consensus about the top 10 things that you as a web application developer should know and care about in terms of security. Some of them are pretty broad, as you'll see. But the important thing to note is that these are ordered essentially by risk, not just prevalent. So the number one thing is the most dangerous thing, not the most common. So this is the OWASP top 10. Number one is injection, and that covers things like code injection and SQL injection, which you can often turn one into the other. And so this is something, if an attacker basically achieves this, pretty much game is over, they have control of your web application. So, or they can take all your data, at least. So it's pretty bad. Number two, broken authentication or session management. Obviously, if someone can log in as someone else or take over their session, that's pretty terrible too. Cross-site scripting is when an attacker can have their JavaScript or some other similar script execute on the site. And once the JavaScript does that, it can run in your browser as you and do anything it wants, like change your password, create new user accounts, do all kinds of great things. Insecure direct object reference sounds obscure, but it's something like if you can just manipulate the URL and put in a node ID and see a node that you weren't supposed to have access to. That would be an insecure direct object reference. Security misconfiguration is really a broad topic, but that might be something like you misconfigure your web server so someone can browse the files that have been uploaded. Sensitive data exposure, again, allowing someone to access something they shouldn't see, having pages in the site that publish sensitive data. Missing function level access control, this is if you essentially have a callback or controller for a page in your Drupal site and it doesn't have any access checks, you just return true for access. For example, that would be a missing function level access control. Cross-site request forgery, if you aren't familiar with this, is a little bit tricky. But this is basically when there's an action that can be taken just by having the browser make a request and the attacker can basically get your browser to make the request without your knowledge. A simple example of this is an image tag with a link in it and your browser tries to load the image. And instead of loading the image, it disables all the views on your site. There was actually such a bug in views that would allow this to happen that was fixed last year. So using components with known vulnerabilities, I'm looking at you, Equifax, so this is, keep your software up to date. Keep your modules up to date. Make sure you are getting emails or signed up for the security list. Finally, unvalidated redirects and forwards. This is something we've actually had a bunch of in Drupal Core and this is really useful for social engineering attacks. Where the innocent victim thinks that they're going to your website. But the attacker has given them, let's say, a poison URL and it redirects them to the attacker's website. And then they go in and they type in their username and password. And now the attacker has the username and password. So this is actually a quite serious problem. So again, these are quite broad. Like some of these cover the entire spectrum. I mean, insecure configuration pretty much can cover anything that you want to do. But the other thing to note, so again, these are ordered by severity, not by frequency. And so the frequency that we see these things in Drupal is not the same as the order that was top 10. And some of these apply beyond Drupal. So in particular, using components with known vulnerabilities, that could apply to any level of your web hosting stack, your web server, your database server, anything could be vulnerable. So you need to be aware not just of your Drupal application code, but your entire stack in terms of maintaining the security of your site. Relate to that also is with increasing use of Composer and pulling in third party libraries, how do you know if there's a vulnerability in one of the third party libraries that you're using? That's actually not something that's very well supported yet in terms of discovering those vulnerabilities. There is a start on an effort called Friends of PHP Security Advisories where projects are starting to basically record when they have a security vulnerability, so you could use then a script to check whether any of your Composer vendor libraries have a known vulnerability. So that's, I think, something you'll be hearing more about in the future. Okay, so let's get into the top ten ways that Drupal 8 is more secure. And number one, twig templates being used for HTML generation. And I picked this as number one for Drupal 8, because really, this covers especially the most common vulnerability in Drupal, which is cross-site scripting. In past versions of Drupal, you would see this all the time when someone would forget, for example, to escape a node title. So the attacker could just type in a script tag in the title and execute some script, like take over your site. There is also, of course, the problem that themers could do something entertaining like run SQL queries in PHP template or execute code. And so if the themeer was able to do that, and maybe they weren't careful, they would have opened up vulnerabilities for code injection at the template layer in previous versions of Drupal. So I think this shift is really a huge win for security. Drupal 8 enables auto-escaping in twig. So what that means is that if you pass just a string to a twig template, twig will basically run the equivalent check plane on it. So it will always be escaped. And so now there's a very few routes to get unescaped text into twig. As I said, again, you can't have your themeers running SQL queries or PHP. So it means that they can't open up vulnerabilities there. And twig is also actually a lot easier to read and write, I think, for normal humans. So this is actually really a win for developer experience also. Let me just show you kind of a comparison. So this is a Drupal 7 block template. If you look at this, do you have any idea what's going on? I mean, really, you'd have to dig in and try to parse through in your head the print statements and all these things and the PHP open and close tags. Try to see just what the markup is that's going to be generated by this template. So the templates were not really that user-friendly, but this is a twig template for the same thing in Drupal 8. And you can see now that it's a lot easier to read. You've got still if statements. You have basic branching logic still. But you can see where the h2 tags, the div tags, are being rendered much more easily. So I think this is a real win. The other thing, because this is such a win for security, basically we ended up deciding to completely deprecrate the use of theme functions. So if you're upgrading something to Drupal 8, you should try as hard as possible to convert all your theme functions to twig templates. The support for theme functions will be removed, in fact, entirely in Drupal 9. If for some reason you really have to can't somehow make a template, there is this theme render and auto-escape function that does the same as the twig auto-escaping. So if there's some case where you have to have a theme function, please use that. And then an example at the bottom here where I just want to share again an example why this is more secure in Drupal 8 than Drupal 7. So if you look at that very simple template on the left, can anyone see what the problem is? The severe security vulnerability that's being introduced. Yeah, the no title, right? We're just printing the no title. The user's input is to then pass back directly rendered and that's a cross-site scripting vulnerability. In Drupal 8, you see we use node.label. This is one of the cool things about twig, you use this dot notation and you can pull a property, you can pull an array element, you can actually do a method call. Twig will figure out the right thing to do. So if you're copy-pasting this, you don't have to worry about what label actually is. That might actually be a method call. But because it's in twig and auto-escaped, if it wasn't already safe, twig will escape it. And so now in Drupal 8, this is not a vulnerability at all. This is perfectly fine. So that's why I think this is a real win, as I said, in terms of developer experience. And so again, you should feel excited about adopting twig because it's easier for you but also because it's more secure. Okay, so number two, and this is certainly something that always made people nervous, was the PHP input filter. And so this is sort of, this is OSPOP 10 number one. It is essentially Drupal, previous versions of Drupal came built in with a code injection of vulnerability, in a sense, right? So Drupal is vulnerable to anyone who had an admin login, could inject code into the site, could potentially get a shell on the server, could take over the entire site. Also, for Drupal 7, importing something like a view meant importing executable PHP code. So again, anyone you wanted to carry out what you might think of as normal site building function, like, hey, import this view. You basically just let them execute arbitrary code on your site or your server, that's pretty dangerous. So there were lots of other areas in Drupal 7 and before where we used PHP snippets for things like block visibility, field defaults. All those things have now been removed in Drupal 8, so there should be no place in the Drupal 8 UI where you can type in and execute PHP. So if you need special logic, put it in a module. Put it in version control, track it. That was always the best practice. But sort of in this over the last couple of versions of Drupal, we moved in this direction towards eliminating PHP and the UI. Now it's completely gone, and I think we can all really celebrate that in terms of the security win. Okay, related to that is that, and what I put is number three is that your site configuration is exportable and manageable as code and versionable. So people have probably heard about the configuration management initiative. That's where we can export Drupal's configuration as YAML files. And you can take those exporting YAML files, you can put them and get, and you can commit them together with your code base. And that's actually really important for security, because it means that you now have, or can create a history of the configuration of your site. And if an attacker came in or someone on your team went and changed configuration that weren't supposed to change, you could actually look over time and compare the versions of the site configuration and say, hey, on this date, or between these two dates, someone changed the configuration in a way I didn't expect. So I think that's really important to be able to audit the history of your site configuration in terms of security. And then compare what the configuration was in the past to what you have in the code base now. So I think that's a huge win for security. If you haven't played with that, this is what it looks like in the Drupal UI to export a single item of configuration. You can see we're getting the user settings there about how a user can register, what kind of weather admin approval is required. And you see this, YAML file is very human readable. So it's pretty easy to manage and very easy when you put it in get to see the diff meaningfully between two different versions of the configuration. This fact that Drupal has this configuration management system also opens up other possibilities for securing your site. So you can actually lock down the configuration of your production site completely and not allow any configuration change in production. What that means is you would go in development, you would make your configuration changes, test them, export your configuration to the code base, and then you would update your code base and import the configuration on the command line to your Drupal 8 site. And so in production, only someone who had basically command line access to do that import could change the configuration. In the UI, if they went and tried to change it, they would just get an error message saying, sorry, this is production. You can't reconfigure production. So I think this is also a great thing because people sometimes are in a hurry. They're trying to test something out. They're trying to fix something, make a config change on production, and open your site up to an attack. You can also hook into the configuration system to log every change. So let's say you couldn't actually lock down production for some reason. You could actually log each and every change and which user made that configuration change. So again, you would have basically a history and you can see who's doing what on your system in a way that you could never do with earlier versions of Drupal. So I think that's an amazing thing. People aren't really focused on that yet, but I think that's going forward gonna be a best practice. Okay, so we're up to number four, which is about text filtering. So this feeds back with OWASPOP 10 number three, cross-size scripting primarily. And so I'm gonna talk about a few different improvements, but I primarily focus on the integration with the WYSIWYG editor and text formats. So we've improved the user content filtering so there's a better connection between the actual input formats and the WYSIWYG configuration. And this is important because in the past, there was often a tendency to give site editors full HTML access on the site. Because you didn't want to deal with the headache of configuring the text format to match the editor configuration. So you just say, sure, give everyone full HTML access, what could go wrong? Well, in fact, what could go wrong is that you've now given them the ability to execute JavaScript, which means that you've given all of those people the ability to carry out a cross-site scripting attack on you and basically take over your site in any way they saw fit. So did you really trust all your content editors that much? Did you really think that they should control your site? Probably not, right? I mean, especially if it was the intern who just came on out of college and probably they don't deserve that level of trust yet. So to show you what happened in Drupal 8, so this is just showing you if you go to the editor configuration screen or the text format configuration screen, you'll see at the top there there's the editor configuration, right? And there's along the top is a list of available basically functions or buttons that you can add to the editor. So let's say I want to add the underline tag to the editor, allow my content authors to make underline text, very common thing. What's great is that if you go on that screen, you drag the U into the active toolbar. At the bottom of the page, Drupal will actually populate that HTML tag into the list of allowed tags. So now Drupal will automatically update your text format and add new allowed tags as you add them to the WYSIWYG editor. So you don't have to think about it, you don't have to manage that yourself, it just happens automatically. So I think this is again a great feature, it makes Drupal more usable, makes it easier to keep the configuration in sync and reduces your tendency to want to give that full HTML format to anyone. Some other elements here in terms of filtering that are important is that Drupal Core now gives you the option to limit image tags to only load images from the same site. And that was something that was actually originally developed for Drupal at org to avoid various kinds of attacks, including it prevents people that can add content from using your site as a cross-site request forgery attack vector. So I mentioned image tags towards the beginning. You can put a URL in an image tag to a remote site and try to carry out a cross-site request forgery attack. So now that blocks it limits it to being only on the same site. And there's also, of course, problems with spam where people want to link in, let's say a spam image from their site onto your site. Again, this prevents that. We also added attribute filtering. So you saw on the previous screen, the text filter limited you to certain HTML tags, but we also now have filtering on HTML attributes. And that's actually important because it again, it helps block certain spam attacks as well as more severe attacks. The people like to do things like adding certain classes that are used in the installer which hide text to their spam comments. So that you only see, let's say one line where they say that's a great idea. And then there's like 20 lines below that of advertisement for their spammy product. The search engines will often read that hidden text and index it, even though it's not visible to the user because they managed to use a CSS class to hide it. So attribute filtering allows you to help block things like that. So you can prevent users from using class attributes. There's also Drupal's Ajax system uses different attributes to trigger Ajax behaviors. We closed down a lot of this vulnerability already in a Drupal core release last year, but there are still cases where you wouldn't want to let people write arbitrary attributes because they may be able to trigger some Ajax behaviors. So again, this helps lock down and keep you safe from that. Okay, so now we get into another fun one. Hardened user session ID handling, and this gets us to OS top 10 number two. So this is the second most severe thing that could go wrong. And the change here actually sounds pretty simple, but what we did is start hashing the session IDs in the database. So when Drupal gives you a session, that basically sets a cookie in your browser. And then when Drupal wants to validate that cookie from your browser, it looks at the value, and a previous version of Drupal, that exact value would be stored in the database. And Drupal would just do a one-to-one comparison. In Drupal 8, we actually run the session ID through a hash function before storing in the database. So we run the cookie value also through a hash function, and then compare them. And I'll tell you more about why that's important. The other thing that we improved in Drupal 8, two more things, mixed mode session support has been removed. So this allowed you to run a Drupal site where some pages were served over HTTPS, and some were served just over HTTP, and you had the same session across those. And that's not maybe intrinsically a vulnerability, but it led to a lot of bugs in cases where people's sensitive information would be exposed, because the attacker could potentially redirect them to the insecure link. Or their session would leak over the insecure link, and then the attacker could basically upgrade and get access to other information. So that was removed. In general, your site should be running fully over HTTPS now. There's really no good reason not to. Another fun thing in previous versions of Drupal, if your website domain starts with dub, dub, dub, which most people do, Drupal will actually strip that out of the name of the cookie, the domain set for the cookie for the session. And now that's actually really a problem, because that means that every sub-domain on that same parent domain will get your session cookie. So the way the browser works is if you set a cookie on the base domain, then you access any sub-domain that cookie will be sent along. So this is a real problem. So if you are at a company and you have a bunch of different sub-domains with different web applications, and you have one main website with the dub, dub, dub domain, Drupal, because Drupal will set the cookie that way, your session cookie for Drupal will actually get sent to all these other web applications and sub-domains. So if any one of those is compromised, they could steal your session cookie and get access to your Drupal site. So you can prevent that in Drupal 7 and before by making a tweak in settings PHP. So if that's a worry for you, you should definitely look into that. But in Drupal 8, that behavior is no longer implemented. We ripped that out, and now you don't have to worry about making it happen. So getting back to why this hashing of session IDs is important. So in Drupal 7, a stolen session ID can be used to basically impersonate a user in hijack a session. And one of the easiest ways to seal a session ID and that people don't think about is in your database backups. So in your database backups, if you dump the session table as part of your database backup, which you probably are doing if you didn't specifically exclude it, you have the user session IDs. In those session IDs, Drupal sessions are valid for something like 30 days. So if someone has a recent database backup, they have the session IDs. So if you left a database backup lying around somewhere or you had a contractor that had a database backup from production, so they could do some testing. Now they've got session IDs, they could potentially access your Drupal site. Drupal 8, this can't happen, as I said, because we're now hashing them. And so the thing in the database is not the actual valid session ID. So let me just show you here. This is what a database dump might look like. And you can see here these raw session IDs from Drupal 7. And just to show you how easy it is to basically take this database dump and then log into, be logged into Drupal 7 site. So I'm just going to basically copy paste one of these two session values. This is the Drupal 7 site. And you can see I can go in the JavaScript console here at the bottom. Just say set document cookie with the session name, which is very easy to find. Drupal just exposes you and the session value that I just took out of the database dump. Just that one line of JavaScript right there. And boom, I'm logged in as the user whose session that was. Right, so this, again, is something a lot of people don't think about, but database dumps for Drupal 7 and before expose a lot of potentially damaging information like this, where someone could just log into your site, potentially as an administrator and take over your site. Sorry. Okay, so hopefully you're convinced that was a good improvement. Okay. And we're halfway through. So automated cross-site request forgery tokens. So this is something lower down on the OSPOP 10 number 8, cross-site request forgeries. I wanted to focus on this and, you know, there was improvement. This was a core issue because this vulnerability is extremely common in Drupal sites, especially in custom modules or contrib modules. I would say after cross-site scripting, this is the number one most common vulnerability, maybe even more common. Yeah, so we've seen it in Drupal core recently, we've seen it in views, we've seen it a lot of places in Drupal. And so this, to think about what cross-site request forgery vulnerability looks like, this is when there's something like a menu callback or a page controller where when you make a get request or a post request without some kind of token, it takes an action that's essentially destructive. So unpublishing a comment, approving a comment, you know, disabling a view, deleting something. It can also, it's not just get request, it can also work through post request, but the most common ones are just someone who says, oh, I want to go to this link and have this thing happen. Right? Not a great idea. You should generally use the form system. So Drupal's form API has built in protection against cross-site request forgery and that's why people should use it for almost anything that takes a destructive action. But sometimes, you know, you feel like you need a quick link to do something. And in Drupal 7, if you wanted to protect yourself against cross-site request forgery, you had to write custom code to output a token and then validate the token. And so a lot of people neglected to do this. They didn't realize it or it's too much trouble. They just skipped over and thought, who's gonna find my modules vulnerability? It's no problem. Drupal 8 makes this really easy. So you can see here at the top, it's a little small. But basically, this is a route definition in the YAML file for routing. And under the requirements, you just have to put this underscore CSRF underscore token to true. If you do that, then the routing system Drupal 8 will take care of protecting these routes for you and adding a token to the URL. And because there's a unique token based on your session, the attacker won't know that random token and they can't force your browser to make this request in a way that will carry out the action. So I showed you here also an example of how Drupal 8 core is using that. So it's using it with shortcuts. So you see at the bottom there, block layout. I have a shortcut to block layout that yellow star and I'm gonna hover over it with my mouse. You'll see it says remove from default shortcuts. So that's sort of a destructive action, right? It's taking away my shortcut. And then at the bottom, which is obviously hard to see, you can see the long URL. And that actually includes that automatically generated token. So we zoom in on that. You can see, just by putting that underscore, no, I don't want that. Underscore CSRF token in the route definition. We've now gotten this token query string appended and Drupal 8 will validate that on the incoming request and make sure that it is valid for your user and that it's not an attacker's request. So again, this makes this kind of carrying out this functionality much easier than in previous versions of Drupal. Okay, OSPOP 10 number seven, or sorry, number seven way Drupal 8 is more secure is trusted host patterns enforced for request. And I think this would fall under OSPOP 10 number five security misconfiguration. So this is again, one of these fairly severe vulnerabilities that people don't pay a lot of attention to. If you want to know more about it, you should go to this handbook page in Drupal.org. And host header spoofing is a real vulnerability in very common deployments of Drupal where for example, you put Drupal in the default virtual host of your web server. So Drupal is in the default virtual host on Apache. That means any request to that IP address, regardless of the host name in the header, will be served by your Drupal site. And so that, I don't know if that sounds bad to you, but there's a lot of ways that could be bad. So one great way that that is bad is that I can, let's say I want to take over your account on your Drupal site. I can basically send a request to the Drupal site with a password reset. And I can send it with a host header for my attacker site. So now your Drupal site will see an incoming request. It's in the default virtual host. It'll say, hey, great, I'm serving this request and hey, I'm looking at the host header that comes in and I'm gonna generate an email to you saying, hey, would you like to reset your password? Follow this link, but using the attacker's domain name. And so the attacker could potentially have a domain name that looks very similar to yours. You wouldn't notice the difference in an email. And so if you go and click that link in your email to reset your password, you'll be sent over to the attacker's site. They can now capture your password reset link, go to your site, log in as you, and change the password and take over your site. So that's one great way that host header spoofing can be used to take over a site. You can also do fun things like poison the render cache for Drupal. So again, make lots of requests with the attacker's domain name. In certain cases, Drupal will render an absolute link somewhere in the content and now any absolute links that are rendered will link out to the attacker's website and set it back to the same site. So that's a great way, again, to basically do some social engineering attacks to trick people to visiting the attacker's website when they think that they're on your site. So this is, so protecting inset in previous versions of Drupal wasn't that easy. You basically had to configure a web server. You had to go in and make sure that there wasn't just a default virtual host serving Drupal, that it was in a named virtual host, I matched all the host names that you cared about. And that was something that I think a lot of people didn't always remember to do or there was a disconnect between the people developing the Drupal site and the people running the web server. So great thing in Drupal 8 is you can go in settings.php and now just define a set of patterns of allowed host names. And so you can basically protect yourself at the Drupal application layer and not have to rely on the web server and particular web server configuration to protect you. So if you don't do that, you'll see in your status report this big red error. So if you are seeing that in your status report, especially for a production site, you should not ignore it. You should take note of that. You should go into settings.php, configure the allowed host names. And again, if you're doing local development, obviously you can put a wild card in for star.local or star.whatever domain you use for your local development. But you should be sure that you also put in the specific pattern that matches your production site so attackers can't forge or do this host header spoofing and attack you. Okay, so it's a number eight way the Drupal 8 is more secure. This is really a fun one. So all is top 10 number one injection, SQL injection. So this one has a bit of a backstory. So if you remember Drupal 6 and before, we used PHP's MySQL driver or MySQL I driver. And those drivers sort of had a very specific interface and we had to have wrapper code that basically wrapped our function calls like DB query to translate them into the MySQL one. So the good part about that and something that I think most of us didn't realize is that that driver actually flagged the connection with MySQL so that each SQL statement that was sent over to the database server was only allowed to contain one single SQL statement. So it could have a single select or a single insert, but it couldn't have multiple. For Drupal 7, because the PDO system in PHP allowed us to basically get a more uniform object oriented database driver that was similar across multiple database servers, we decided to switch to that. But something that none of us realized basically until there was a problem is that PDO allowed multiple SQL statements to be sent over at one time to the database server. And in fact, PDO didn't even have a way to prevent that from happening, didn't have an option to basically restore this behavior that we'd had with the previous version of the MySQL driver. So that turned out to be really bad. So it turns out that Drupal 7 was dramatically more vulnerable to SQL injection attacks or the severity of an SQL injection attack, actually I should say, was dramatically more severe in Drupal 7 than in Drupal 6. And you guys might remember the impact of this. So this Drupal Core Security Advisory SA Core 2014.05 also sometimes known as Drupal Getten. If you remember within, you know, about six hours of this vulnerability being released on Drupal.org, people's websites were being taken over all of the world. And probably the, there's also a little thing that maybe the Panama papers, some of these other things related to this vulnerability not being patched by people's sites. And that was really terrible because there were multiple attack vectors accessible to anonymous users. So anyone basically who could reach your site on the internet basically could hack your site. And the reason that this vulnerability was so severe relates back to that switch to using the PDO driver. So a single read query, so for example, checking the name that you're trying to log in with on the login form. This was one of the actual common vectors that attackers used. It could now be converted to a read, look up the username, and also a write, let's change the user's password, or let's insert another user, or let's insert something else in a database that basically allowed the attacker access to your site. So that was again possible because these multiple SQL statements could be sent in a single query. And so Drupal thought it was only sending, you know, check if this username exists in the database, but it was checking this username exists in the database semicolon, and then write this new row into the user table. So that was pretty bad. Drupal 7 on MySQL was actually tremendously more vulnerable or the severity of SQL injections was much higher on Drupal 7 than on Drupal 6. So this is a real wake-up call and decided we better do something about that for Drupal 7 and 8. And that actually involved making a small change to the PHP language itself just to enable the PDO driver to set the flag on the MySQL connection that sets it to only allow a single database query to be sent at a time. So we did that. The good news, you know, we got some help from people in the PHP community and that flag was added in PHP 5.6.5 and 5.5.21. Also obviously in PHP 7 has always had this because that was before 7 was released. And so we now use that flag in Drupal 8 and we also use it in Drupal 7.4 and above, or 7.40 and above. The other thing we did in Drupal 8 was we actually added for all database drivers and now checks your SQL statements. And if you put a semicolon in the SQL statement, a Drupal will throw an exception. So for any SQL drivers, so basically even though Postgres and SQLite and other databases don't have native support for limiting you to one SQL statement, Drupal 8 at the PHP database driver level implements it essentially just by string checking. And so that basically now production has been applied to all database drivers in Drupal 8. So hopefully we won't see this kind of severe SQL injection before again in Drupal 8. But you should not be complacent about SQL injection. So this is again OSPAP 10 number one and it's still very dangerous. So if someone, even if they can only read data out of your database, that means that they can do things like read out the hash passwords of the users in the database and they could potentially then run those through a cracker and try to break people's passwords or they could read sensitive data out of your database. So if you have private information about your users, you have contact information, medical records, so let's hope not. But if they did and there's an SQL injection, then the attackers can read those things out and you probably wouldn't want to be on the hook to explain why you had this kind of vulnerability in your code that allowed an attacker to exfiltrate all your sensitive medical data. So again, if you use the database layer in Drupal that's really designed to protect you against these SQL injections and don't be complacent if someone says hey, your module has an SQL injection, don't wave your hands and think that that's not important. Okay, so number nine way Drupal 8 is more secure is click jacking protection. And this, I'm not sure how this would fit in OS top 10 except maybe the security misconfiguration one, but that's so broad it covers almost everything. But this is basically in Drupal 8 and in Drupal 7 also, we added just a header to every response from Drupal and it has this X-Frame option, same origin and that's being emitted by default. And this Drupal not doing this was actually really popular thing to be reported to the security team by so-called independent security researchers who basically wanted to publicize their expertise. So we get this report basically every week. Someone would be like, hey, Drupal isn't sending this header. And for a long time we sort of ignored that and finally we said, we should probably take this attack seriously because someone's reporting to us every week. And what this header does is it actually prevents a number of attacks, particularly click jacking attacks. And so this is, I don't know if people have heard of this, but what this header does is it prevents someone from serving your Drupal site inside an iframe. And so what the attack basically looks like this is the attacker writes an iframe that loads, let's say an administrative page on your Drupal site and let's say they limit the size of the iframe so it's only over top of a button. And the button might be enable the modules, publish the content, delete the user. Some button that you wouldn't wanna click normally, but they've iframed in just that button and they put that iframe in their site and they invite you to come to their site and let's say post a comment or submit your opinion or something and you go and look at your site and you're saying, oh, I wrote my comment and now there's a button at the bottom, I'm gonna click that. Well, you've just clicked through the iframe into your own Drupal site where you're logged in and done the thing that the attacker wanted you to do. So that's clickjacking, which I mean, again, sounds sort of esoteric, but this is an attack that is known and has been used to compromise people's sites. The other thing this prevents is people basically hijacking your content. So I don't know if you remember there used to be sort of popular way to steal SEO juice from people's websites, which was to serve your website in an iframe on my website to convince the webcrawlers that I really had all the great content on my spam site, even though it was being served from your site. So this header will also prevent that, which is a good thing, again, keeping your SEO for yourself. And then finally, the number 10 way Drupal 8 is more secure is changes we made to the JavaScript API to be compatible with the content security policy headers. So this gets us OWASPAP 10 number three cross-site scripting primarily. And so content security policy, show of hands how many people have heard of this. Wow, not many, okay. So this is actually a great new feature that's been added to browsers over the past couple of years. You should take a look at it at this w3.org page that basically shows you the specification for content security policy. So content security policy basically allows your website to send headers saying things like, this site does not have any inline JavaScript. Or this site only loads third-party JavaScript from Twitter and not from any other third-party site. Or my site has no inline CSS styles at all. So you can basically specify very clearly what your site expects the page content to have and the browsers, most browsers now will respect this content security policy. And if they see something in the page that doesn't conform to that content security policy, they will just skip it over and not render it or not execute it. So in terms of this core improvement in Drupal 8, we now have the big change we had to make is that the JavaScript settings, so if people have used Drupal's JavaScript API, you know that there's a settings object in every page. It tells you things like the current path and various other things. And so now in Drupal 8, we're adding those JavaScript settings to the page content as basically a JSON string instead of actually as an inline script that instantiates the JavaScript object. And then we have a separate loader script that's loaded as a file that reads that JSON string and creates the object in the page. So what that means is so this JavaScript settings was the one piece of inline JavaScript that basically every site had on every page in previous versions of Drupal. And now there's no inline JavaScript at all being shipped by Drupal 8. And in fact, Drupal 8 core in the render API removed support for inline JavaScript being rendered at all. So if you were in the habit of just throwing some JavaScript in the page, you should really now think about how you can put that JavaScript into a file and load it so it's not inline because that allows you not having any inline JavaScript allows you to set a content security policy header saying there is no inline JavaScript. Inline JavaScript is how attackers execute cross-site scripting attacks. So again, back to our original node title attack, if the node title is rendered in the page with some script tags, but the content security policy says this site has no inline JavaScript that should be executed, the browser will say, well, I won't execute that cross-site scripting attack, it's neutralized. This basically lets you neutralize the whole broad range of cross-site scripting attacks by just setting the appropriate headers. So Drupal core doesn't yet send these content security policy headers. There are some contributed modules like SecKit that will help you do that, or you can just set them yourself either through your hdaccess or Minimodule. They're not really that complicated if you wanna do sort of blanket prohibition, but you can get quite sophisticated again. So you can allow, for example, a third-party JavaScript to be located, loaded from Twitter, if you have a Twitter button, but not loaded from any other third-party site. That also helps prevent cross-site scripting attacks, where let's say an attacker was able to inject a link to a script from their site. So just to show you, again, what that looks like in Drupal 8 versus Drupal 7. So this is the Drupal 7 example where you see we actually, we have a script tag of type text JavaScript, and that's actually executing this jQuery command to basically set the Drupal JavaScript settings into the page so they can be accessed by other JavaScript. In Drupal 8, these JavaScript settings are now just written out as a JSON string. So you see there's not actually any JavaScript being executed there. It's type application JSON instead of text JavaScript, and so then our loader script comes in is just loaded as a file, just reads that and puts it into the page. So, just want to focus on a few takeaways for people here who might be PHP developers who are not doing just Drupal, since this is in the PHP track. So if you haven't already looked at the OOS Pop 10 and the resources on the OOS site, you should definitely do that. And think about those, you know, those Pop 10 and different resources there, again, in the PHP context and how those are generic web application attacks and not something that is Drupal specific. If you're using the MySQL, MySQL is a backend for any PHP web application, you should think about setting that flag in the PHP PDO driver so that you can only execute a one statement at a time on MySQL, and that will help limit the damage from SQL injection attacks. They're still severe and you should not allow them to happen, but it will make them a little less damaging. A lot of people like to use Twig now in symphony projects or other PHP projects. So if you're using Twig in your custom PHP project, you should definitely, if you're not already, turn on that auto-escape feature and learn how you can set up your user input which has already been escaped to be wrapped in a way that Twig won't escape it again. So that's something that if you look in Drupal, people may be wondering, how does this auto-escaping work? How is it that Twig can know magically that this string is safe and another string is user input that's not safe? Anyone have an idea how that works? Maybe. So basically what's happening is that in Drupal 8, and a lot of functions that used to return strings are now actually returning objects. So if you look, for example, the T function or the equivalent in Drupal and a lot of other functions like that that would return what you think of as a string, they're actually returning an object and that object, because it's an object, when we get to the Twig layer, Twig can say, oh, this is an object and it implements an interface that I know about and that wraps a string that is already safe or will be made safe by calling two string on the object, then I'm not gonna call the equivalent a check plane on it. But if I get a bear string, something that's not wrapped in an object, I will go ahead and escape it at that point. So that's basically how Twig and how Drupal 8 distinguish between things that we know have passed through a system that's gonna sanitize it in some way. So you know with T, you can use those at placeholders to sanitize user input and the other part of the text should not be escaped. So once we've done that, we don't want it to be escaped again. You get double escaping, which is really ugly. And that's how it works. So in general on PHP, you can wrap something that's already rendered as safe markup in a basically a Twig object and Twig knows natively that those objects are safe to render without escaping again. Another one that, you know, again, sounds really easy but I showed you how bad the consequences can be. If you don't do this you should not store raw session IDs in your database. So if you have a PHP application that has session IDs you should hash them before you store them in the database. This is a really easy way to mean to basically sanitize your database backups in a way so that the raw values in the database can't be used to take over a session on the website. All browsers now support content security policy to and allow you to block inline JavaScript. So again, your web application especially if you have any kind of user input you should think about making sure that you don't have any inline JavaScript if possible and then turn on this content security policy by setting the headers to block any cross-site scripting attacks. Host header forging is a problem that's not limited to Drupal for sure. So any PHP application you should either through the web server configuration or through your PHP application make sure that you are limiting yourself to only host names that you recognize for your production web application. And a general rule that applies throughout any kind of web development is really beware of user input, right? So user input, whether it's coming from the query string it's something someone submits in a form, it's even a path in the URL. All these things can have attacks in them and if you're not aware those things can be manipulated by the user and if you trust them implicitly that's a great way for users to attack your web application. Okay, so wrapping up here, some final thoughts. So yay for us, Drupal 8 is more secure than Drupal 7 and many of those security features actually improve the developer experience. So things like Twig, these automatic token generation and Routes, things like that make it easier for you as a developer to make your site secure and are actually more pleasant to work with than in Drupal 7. But we shouldn't be complacent. I think Drupal 8 does have possible new risks especially because we're pulling in a lot of third-party libraries. This is a system we don't yet have great tools for tracking vulnerabilities in these third-party libraries. Also, Drupal 8 was extensively refactored. People are probably aware of that. So it was rewritten in an object-oriented style. But that means that there's a lot of new APIs and then there's a lot of code moved around if it wasn't changed and those refactoring, refactoring is our chance to introduce bugs and those bugs might have security implications. So we shouldn't be complacent. There may be security-related bugs that are new in Drupal 8 we haven't discovered yet. So do be aware, pay attention if there's some unexpected behavior in your site that it could be something new related to Drupal 8-specific code. So that's it. You know about the contribution sprints tomorrow, Friday. So there's a mentor core sprint, first-time sprint, and general sprint here in this building. I hope you will all attend. And with that, I will take questions and I hope you will go and rate this session. Tell me what you thought of it. Thanks. So if you have questions, there's a mic there. It would be great to use that. Hi. So I have one question about the hardening around SQL injection. You were mentioning it's no longer possible to issue more than one statement. Does this apply only to statement expressed in a string form, so like using DB query or does that apply also to DB, TNG queries? Because I remember that the field API when inserting and updating field values used to issue multiple insert statements to improve performance. Yeah, it applies to anything because all of those queries are converted to strings before they're sent to the database. In Drupal 8, for sure, there really was no use and core of multiple inserts. Maybe this was in Drupal 7. Was it in Drupal 7 that this was happening? I'm sure in Drupal 7, this used to be the case, not for whether this changed in Drupal 8. Yeah, in Drupal 8, I think it was just doing a loop and preparing the SQL and then just running individual inserts for each one. Okay, thanks. Yep. So some of the mitigations against the attacks that you've just gone through happen in the theme layer. And one of the rising trends that we've seen is this trend towards decoupled Drupal, which means that you lose the protections that we've implemented there. Are there decent resources out there for what you need to do if you move to a decoupled approach to mitigate against those kind of attacks that you've lost those protections from? It's a good question. It's actually a really hard problem. So I know there is being some work done to basically refactor the form API so that you can more easily take advantage of some of the things like cross-site forward protection in the form API if you're doing a decoupled system. I think escaping text is really a hard one in the decoupled case because you don't, you know, if you send the raw node body, right, you may not have knowledge about the text filter in that needs to be applied. So I don't, there, I don't know that there's great things. I know you can, there is a JavaScript version of twig but I don't know how complete that is at this point. So it's, it's hard. And it's certainly one of the challenges of doing decoupled. And a second question. You mentioned about good security policy for hooking it into config management to generate logs. Right. That sounds like something that would be a really simple and very widely used contract module. Are you aware of there is anything that already does that in the contract space? I believe there is a module already, at least one called config log. And there may be another one that does something similar. Yeah, that gives you options about where you wanna log each change. And it shows you the diff of the config that was actually changed by who. So yeah, there are options already available and it's pretty easy. I mean, that's like a really trivial module. So if you wanna do something custom, you definitely could. Great, thank you very much. Yep. All right, any other questions? No, if not. So the session slides are already posted. If you wanna, you know, look at them and get into more of these details. I know I said there was a lot of material here, so I hope you can move fast. I hope this was informative. And yeah, certainly come and find me if you have more questions you wanna ask one-on-one. Thanks a lot. Enjoy the rest of your fun. Thank you.