This is a transcript of the A03 - Injection & Cross-site scripting training session. Click here to return to the OWASP Top 10 Security Vulnerabilities page


Janez Urevc: [00:00:00] The third and the last topic for today is injection.

Um, you know we, we used to look separately at SQL injection and cross site scripting and all that. Now we have everything in a single category cause you know, it's uh, different, but very similar problems at the same time.

Um, and as far as I'm aware, it has been for awhile, but the next one is actually SQL injection, and the third one is external control, file name or path. Um, in the context of Drupal now compared to how much SQL injection problems there are, or were in the industry in general, [00:01:00] we are quite good at that in Drupal.

Um, and the reason for that is that we have, you know, these database abstraction APIs, which basically assured that we write secure queries. Uh, nonetheless, you know, if you remember Drupalgeddon, that was a SQL injection problem. Um, so we're not 100% secure, and we never will be that's, that's just the fact of life.

But you know, even in Drupal 6 times, Drupal was very successful at preventing SQL injection. On the other hand, cross site scripting was something that was way more common as if you remember in Drupal 6 and Drupal 7 times. Um, we had this functions called check_plain and also Check_XSS. Um, and I'm pretty sure that like 90% of job interviews in Drupal, in Drupal industry had this question about what these functions do, or, you know, something along the lines, how do you handle insecure user supplied content or something like that? Cause it was so important to know how to use these functions and to understand what is.

User supplied content and what is, you know, system content that never got touched or created by user. And I remember one really good question was okay, so if we have an article on, on, on, on the NewsPage [00:03:00] a comment is definitely a user supplied content because you know, generally most users can publish comments.

So you want to handle that content with care, but then the next question was, okay, what about articles that are written by you know, generally sort of the staff and the answer was sure it should be also considered unsafe because you can have either people accidentally doing stupid things or, you know, somebody tricking them into pasting some dangerous code somewhere and not being aware of.

Or we can have like, rogue employees that want to do us harm something like that. So that's definitely also something that we need to handle, but then it was, I remember there was as a presentation at one of the DrupalCons that [00:04:00] somebody asked, what about the machine name of taxonomy vocabulary? Should that be considered a safe street or in a safe stream?

And no, very common answer. Predominant answer in the room was, oh, machine name is safe. Of course. And the answer is no, it's not. And the reason it's not is that on most forms where we are created in the specific example where we are creating taxonomy terms. The machine name will be auto generated and displayed but you also have this edit button next to it, where you can change it and know any user that has permission to create the taxonomy terms has permission to change the machine name and could inject something in there that is harmful.

But since it's called the machine name, it's very un-intuitive that this is something that [00:05:00] could be abused by the user. Um, and all of these caveats made, you know, working with this functions and understanding where and when to sanitize content before displaying it basically really hard, but then with Drupal 8 we switched the approach.

With Drupal 8, we started sanitizing everything by default. So, you know, we will sanitize everything no matter what, except if you tell Drupal not and this also improve the situation with cross site scripting quite a lot. Um, so while this is one example of making API more bulletproof. Before we had really good API that protected us from cross site scripting.

Um, and [00:06:00] we relied on developers to use it correctly. Um, otherwise it would not work. And that's why Drupal has a lot of cross site scripting problems, not as Core per se, but the projects that were built with Drupal. And now we changed this API to be friendlier and more secure. Um, we improved the situation with that.

Um, so yeah, like 10 years ago, I would give you a whole lesson about how to use the APIs. Now I just want to bring the message over that, you know, these systems are in place and, you know, it's nice to be aware that they are there or should be aware that they are there. Uh, but they for the most part work out of the box.

But you know, cross site scripting and SQL injection [00:07:00] is not the only part of this story. We also, for example, if you're using LDAP, you can do LDAP injection, if you're doing LDAP queries and you know, using user supplied filters, for example, to do that. So something to be aware of, even there you can, you can expose yourself to dangerous situations if you're not sanitizing user pro user supplied inputs correctly.

Um, another area that is really tricky is if you are evaluating code, like provided code, that's why the PHP module in Drupal 7 and on Drupal 6 was [00:08:00] not the best idea. Um, and that's why it was basically removed from the Core. Cause it lets anybody that would get access to some form that had something like this, theoretically write PHP code to control on the site. Um, so if we can avoid things like that, like evaluating code that are provided by the user, or simply don't use UIs and things like that, where people could write code, like code should be the Git repository and that's it. Um, sometimes, you know, we have situations where we have to do those things, and these are the situations where we have to be really careful to really understand what we are exposing ourselves to.

So [00:09:00] in the context of injection, I would also like to come back to the Form API. Form API has a lot of security checks in place. Um, and sometimes our, also this security checks that cause us, headaches, because the forms don’t behave in a way that we expect them to. And the most common thing that I see a lot, like even, even in contrib modules that are quite often used, you can still see like in the form you have this form state object where, you know, the state of the form is stored [00:10:00] across requests and all that.

And in there, there are two values, one is called input, and one is called values. And both of them store to the data that was submitted by the user to the form, with one really important difference. The input attribute on form state object is the raw user data. Like the way it came from the browser and the values attribute we sanitize data and data went through checks and validation.

Um, and sometimes for example, when you limit validation errors in the form Form API, will simply remove [00:11:00] everything that is not specific about, you know, the part of the form that you're dealing with. So things will disappear from the values attributes. Um, and then in those cases, you can very often see people getting data from the input attributes, and that's where you're exposing yourself to the risk of being hacked.

Because you know, this is exactly the, the protection layer that Form API offers to you. And then as soon as you go and use input for whatever reason, because you know, data that you're expected to be in, the sanitized array, is not there. Um, you can, you know, you can, you're basically at your own responsibility and at your own risk.

So my recommendation here would be don't use, [00:12:00] ever, the raw input array. If the values that you are expecting or not in the sanitized array, then there's some other thing that you need to change for them to appear there. And here it comes down to, you know, understanding how Form API works and all that, and sometimes can be tricky, but never ever use the input array. Because, I'm not even sure why it's public. It should be private, to my, in my opinion, because it's meant for internal user of the Form API and not for our, for us to use it. Um, so yeah, this is another example of an API that protects us quite a lot, but it's also easy to misuse it.

Janez Urevc: Another API that we have is the [00:13:00] cross site request forgery protection and that one is implemented on a routing layer. Um, and it's as easy as this. If we put the underscores, yes, RF undersCore token through line into the route definition, then the protection will be enabled for this route and know all the links to this route will be generated with the CSRF token.

And if the token won't be provided when accessing these routes or, you know, it's going to be invalid, then the access will be denied. Um, well this is used like generally when you have get requests, you should never change the state of the system. [00:14:00] Um, you should always use boast requests to do that or any other requests and they're suited for that.

But sometimes we have to do that and you know, the log-out functionality is is one example. Like ideally we would have a page when you click log out, we would go to a page and the system would ask you, do you really want to log out? And then you press a button and you're logged out, but then obviously users would go crazy.

So we do change the state for this for distance. Um, but no, we enabled cross site request for your production on it. Another another tool in Drupal that. Protects us from the same problem, like an attacker tricking user [00:15:00] to visit a page without them intending to like, this is basically what this is about.

If, if an attacker, you know, puts some JavaScript code behind the scenes, those requests to this page, they will log out the user from maybe another site and maybe log out is not a huge problem. But, you know, if there is a page that if you are an admin, there would be a guest page that would give administrative role to a user, to an arbitrary user that could be exploited by the attacker to grant themselves administrative access to the site.

Um, and yeah, if you really want it to be a route and definitely use the token. Another tool that we have is [00:16:00] those confirmed forms that we have, like, if you are on the node listing page and, you know, click a few checkboxes on the list and say, delete content, you're always redirected to a confirm form where you have to confirm that you really want to delete this content and that's, then that is a form and that's supposed to request.

So that's another protection for the same or similar problem. So I would say consider, confirm form first. Um, and if that's not acceptable for you X reasons, then definitely use the cross site request, forgery token protection system that we have, and it's really used. Yeah, just this one line, you add this to our out and group of us, everything behind the sales.

Um, [00:17:00] when, since we're talking about tokens like that, this is another protection that form API offers like for API, we'll always add you know, a single use token to every form so that, you know, when you are submitting the form, you're basically proving that you, you know, you've viewed the form page and they submitted it.

It's not somebody trying to trick you to submit the form on your behalf and you're not even knowing about it. So this is another default protection and we have in place in triples form API Yeah. And now I will repeat myself, but again, culture and code reviews and attention to detail and preparedness to learn all the time and to follow to, to [00:18:00] follow current best practices.

Uh, let the people speak up, speak up their opinion, not being blamed if, if they are wrong or even if they're not, sometimes people are blamed for speaking against maybe more senior member of the team or something like that. Um, being open and having this open culture and, you know, dedicated to learning culture, it's really something that pays on the long run.