Web Security, v2

Clickjacking

Steve Kinney

Steve Kinney

Temporal
Web Security, v2

Check out a free preview of the full Web Security, v2 course

The "Clickjacking" Lesson is part of the full, Web Security, v2 course featured in this preview video. Here's what you'd learn in this lesson:

Steve discusses clickjacking, a type of attack that tricks users into performing malicious actions without their knowledge. He demonstrates an example of clickjacking and also explains some measures to protect against it, such as using frame options and content security policies.

Preview
Close

Transcript from the "Clickjacking" Lesson

[00:00:00]
>> Steve Kinney: So now, we're gonna do a little bit of a victory lap here. We're gonna talk about ones that involve at least a certain amount of social engineering, right? Which means, before, with cross-site request forgery, we were tricking the browser into doing something on their behalf. In cross-site scripting, we were tricking, again, the browser into doing something on their behalf in a more insidious way.

[00:00:24]
In this kinda next kinda example, what we're gonna do is effectively look at how can we trick the user into just doing the bad thing, right? And one of those is called clickjacking, and that's a definition that I wrote. I'm gonna give you the shorter version of that definition.

[00:00:49]
You take the thing you want them to do and you make it an opacity of 0, and then you put something else that they want to do behind it and you hope that the mouse clicks the bad thing that you want to have happened, right? And so basically, you are kind of definitely click this button and realizing that button does something nefarious, right?

[00:01:13]
Again, this involves that they don't look at the URL bar. This involves, you get a lot of things just right depending on what you work on, the target audience for this attack could be different, right, which is why it's kinda in our bonus run victory lap section of the show.

[00:01:33]
But effectively, we'll talk about it and then I will show you kind of a quick example, which is they take a your webpage, they embed it in iframe. They either put something in front of it or put it in front of something and play around the opacity and positioning to make where you click on the iframe the thing they wanna have happen, but hide it from you with deception.

[00:02:00]
That way, the user thinks they're doing something else and they're doing the thing that you wanted them to do. That's cool, words are nice. Let's go take a look. So you can imagine what this in the examples, then what this one called clickjacking might do. So let's check that one out.

[00:02:21]
>> Steve Kinney: So yeah, npm start, clickjacking. So I'm running two different ports right now, the attacker and the victim. Let's look at the victim site first. No, holding option is not what I wanted. So this is the legit site, right? Yeah, I wasn't building an entire another bank UI, okay?

[00:02:45]
This button, you click it, it sends $100 to Alice, right? Ideally, you're logged in, everything's fine, yay, yay, yay. The attack site, and I purposely, just to kind of make a point, the attack site here has this cool button that says Win a Free Prize. Let's go click that button.

[00:03:11]
You also sent $100 to Alice, right? Now, again, I'm peeking out the old UI so I can make a point, but ideally you could either play with the opacity a little bit, or get the positioning just right, to be, yeah, one of those stupid games or something like that.

[00:03:31]
Do the thing and make it happen, right? Again, this involves that they don't look at the URL, that you get the entire look and feel just right. But we all have people in our lives that we know would fall for this. Let's be honest with ourselves. If you close your eyes, you can think about somebody you know in your family that would definitely fall for this.

[00:03:52]
Honestly, it could be my 11-year-old son, [LAUGH] right? So we go through and we can kinda get a sense of kinda how this works. This is just starting the two different servers, yada yada, it doesn't see here. Okay, victim is just a normal site, nothing that you wouldn't expect to see, it's got a button, it does stuff.

[00:04:14]
The attacker is a little more interesting, which is, if you look, we've got this iframe, which is, other than ports are hard and local host, assume that that is a real domain name. It's got an iframe, and we can kind of go take a look. That one is set to actually be seen.

[00:04:33]
I think I can change the opacity of 0, but the more important part is there is a CSS class. I'm using the Tailwind 1, but there's a CSS property called pointer-events-none. That means I don't care what happens when you click on this thing. Make believe that it's unclickable, unanythingable, right?

[00:04:53]
And if you look, effectively, what you can do is absolute position, and you're just putting it over the other one and saying all click events should pass through to the underlying to whatever's beneath it, right? And this is useful in a whole bunch of places, but in this case, all that is really happening is, I think, if I'm not mistaken.

[00:05:17]
I just thought it was better to show it, but if we're not mistaken, yeah, this looks like we made the other one an opacity 0. Still there, right? All click events go through the malicious site and pass down into the invisible site, right? And so this could be, and they're logged in, right?

[00:05:39]
That's a legit cookie session. We're not CSRFing anything, right? It's a fine click event that was totally cool and very normal, except that it wasn't cool at all. And something could happen behind the scenes, and they probably wouldn't even know, right? And so how do we protect yourself against this?

[00:06:04]
Do we have any ideas?
>> Steve Kinney: I have slides if we don't, but-
>> Student: There's some headers that I've used before.
>> Steve Kinney: Like what?
>> Student: I'd have to look at camera first.
>> Steve Kinney: So you've got a few options. There is this one that will work, which is frame-options, which you can guess what either deny or same origin do, right?

[00:06:32]
Deny means, no, you cannot frame me. I will not be framed. Literally, I guess you are truly being framed in this case. God, I hate puns, hate puns. But you can deny it outright or you say only things from the same origin, right? So only things from the origin that I have as a page can also frame me, right?

[00:06:57]
Which is probably also useful if you need to embed your own content into the page, right? And it's tricky because a lot of times you see those, this whole idea of iframes. And sharing cross origin work makes total sense in a lot of cases, because you think about those, you go to a site and you see a comment section and you're already logged into Facebook, right?

[00:07:21]
Those comments are in an iframe, right? That is, that Facebook is hosting, so your Facebook cookie works, right? And so there's a lot of reasonable use cases that can be taken advantage of. But if you know that you're not doing one of these things, and you can also set this header.

[00:07:39]
This is an example of not using Helmet. If you just wanted to see, I think, for the CSP, there's enough going on, and trying to do string interpolation was not worth it. But you can also just set a header as well. So let's go ahead and we'll try that one out first, there it is.

[00:07:54]
We can do this.
>> Steve Kinney: We can deny any kind of framing. And now, if we go back,
>> Steve Kinney: Let's see, I might have to kill this. I don't know if this one totally refreshes the same way. Can I try to load two at the same time? We'll find out.

[00:08:18]
>> Steve Kinney: It has an opacity 0, too, I think why we got to put that one back. So we can actually see the fact that, let's click. No, I'm still borked.
>> Steve Kinney: All right, I'll check the header on that one in a second. We got some other options too, but that should work.

[00:08:39]
We'll find out what.
>> Steve Kinney: So why it didn't work before? Disable cache doesn't disable the cache if your developer tools aren't open, right? And so it cached the header from that first time and said, this is fine, which is kind of one of the problems a little bit with some of these, the caching, which is you need to figure out a way to bust that cache.

[00:09:03]
And we can talk about that later if you really want to, involves fun with CDNs and other stuff like that in a lot of cases. But if we kinda disable the cache, we get a fresh page. You'll see that,
>> Steve Kinney: Refuses to display it, because the frame options were set to deny.

[00:09:23]
And this would be same, it's true, cuz, I don't know that same origin on ports matter in the real web. I'm pretty sure you get a little bit more leeway with localhost, right? So I can start up an NGINX thing. You can see that as well, but I'm not convinced that same origin would actually do what I want it to do right now.

[00:09:42]
And so yeah, that'll do the trick. And let's see other options that you have that you can play around with. Let's see. So the other one is just a regular CSP header, which is, you have one that you can say frame ancestors, which is arguably, personally, I think I have both set.

[00:10:04]
I think X-Frame's options is older and maybe not as widely supported, but I set both because, you know what doesn't cost me a lot? The 20 bytes of setting two headers, cuz I'm paranoid, right? But you can kinda have that in place too and if you look at the X-Frame options, you had only same origin and deny.

[00:10:27]
Here, you can also allow list other ones as well, right? So I would argue if, for some reason, you are allergic to setting both, go with this one, I guess, right? It kinda depends on the origin, unless you're on some shared origin, but you probably not. So you can set it there as well.

[00:10:47]
And the other option is you can write JavaScript that can check to see if it has a parent, and if so, just bust out of the frame completely. Let's give it, yeah, send my ATS. I'm pretty sure I can do,
>> Steve Kinney: Yeah, something like this should do the trick.

[00:11:09]
I think TypeScript's going to get a little angrier with me, but,
>> Steve Kinney: Let's try this out. So I'm basically saying, window has a property called self, which is itself, and then top is the parent, right? And if you are by yourself, you're your own parent, and if you're not, you're in an iframe, right?

[00:11:38]
And so basically, what we're gonna to say is, if window.self and window.top are not the same, bust me out of this frame, right? And so let's see if that works. Except we didn't load the frame at all, cuz I still have that CSP header. So let's take that out.

[00:11:55]
Too much protection. Where is it? Alphabetical order is hard.
>> Dustin: I know your browser's blocking something in the upper right corner. Is that the redirect it in the URL bar on the upper right?
>> Steve Kinney: Yeah, hey, there we go, let's try it again. Dustin saves the day. Yeah, it was kinda interesting, because maybe you need both in this case, too.

[00:12:25]
But basically, the very legit site is saying, if I'm in enough frame, get me out of the frame, right? Re-navigate me out of back to innocent payment site, right, and not where I was before. Now, it's interesting. Chrome's security then was like, whoa, your coach trying to change all this, so maybe you need to do both.

[00:12:49]
But theoretically, you can also choose to try to navigate yourself out as well. And so that basically just tries to destroy out the frame. Arguably, I would say that if it is truly concerning both, again, to our theme of earlier today, which is ideally have the CSP saying your frame doesn't load, and then also maybe have the fallback, which is if for some reason it did, not because CSPs will ever fail you.

[00:13:12]
I've never heard of an issue where it's CSPs were broken in a browser, but I have heard times when somebody made a tiny change and then the CSV didn't work anymore, see also me earlier, right? And so having that fallback mechanism, even if you never need it, is good because a lot of times security misconfigurations are honest mistakes that somebody did while they're working on something else, right?

[00:13:41]
And so having both, I think, makes total sense, and you should do it.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now