Web Security

Content Security Policy (CSP)

Web Security

Check out a free preview of the full Web Security course

The "Content Security Policy (CSP)" Lesson is part of the full, Web Security course featured in this preview video. Here's what you'd learn in this lesson:

Since browsers cannot determine the difference between scripts downloaded from the origin or another source, Mike discusses how Content Security Policy (CSP) tells modern browsers which sources are trustworthy. Mike takes questions from students.


Transcript from the "Content Security Policy (CSP)" Lesson

>> Mike North: So one of the defenses we can use and I heard this as we went around the room and talked about like different things that security issues that were on our mind. I heard content security policy or CSP. The reason we have this is that, browsers can't tell the difference between code that is brought in from a URL on a different domain versus code that we're serving up.

Meaning, like once we fetch that resource and start processing it and treating it as a script, it's really all one pile of code that's sitting within the same execution environment. We really don't draw a distinction between like, well, I got react from the CBN and I got my program from somewhere else, it's all together.

It all has the same rights and privileges. So CSP allows us to inform the browsers to where it's allowed to receive stuff, or where it's allowed to do certain things as it pertains to different sources. For example you could say, as the app running on frontendmasters.com, I'm only allowed to execute scripts if they come from assets.frontendmasters.com and Google Analytics, and GitHub, and that's it.

But if it comes from mike.works, if it comes from my site, like the browser will basically, even if I injected some script that was trying to download something I've hosted, the browser would fail to treat this as JavaScript it's allowed to execute. So that's the point of content security policy.

It comes with, like you delivered this information to browsers via either a meta tag or an HTTP response header that looks like this. So this would say,
>> Mike North: In this case, we've got a directive which has a name. The name sort of tells us what's the flavor of resource that we're talking about.

And script source would mean, we're talking about where you're allowed to get scripts that you may execute. Self would mean like, the origin that this frame is currently being served on. And then this other domain I've added a second allowed source. But for example plain HTTP on the same domain would not be allowed, so an origin includes a protocol, host, and a port.

And so, now I've just said, if you get JavaScript over plain HTTP, not allowed. Do not execute it in browser, it will never get a chance to run. So you can have multiple directives that are separated by semicolon. As you see below, you're allowed to get web funds from Google funds.

And that could be added on top of script source. If you happen to double-down on a directive, so if we had another script source after the font thing, the second one would be disregarded. So only the first one is respected. And the default setting if you don't specify anything for CSP, you kind of let everything fly, which is understandable because the web existed before CSP.

And this is the kind of thing where it is our responsibility to tighten things up, it's our task to do. You can't start with the default being restrictive. So here is a selection of, it is a subset of useful CSP directives. Child source, that tells the browser that you're only allowed to spin up workers and frames from the following domains, from the following origins, rather.

Connect source, that lets you have a white list of what you're allowed to do stuff like fetch, open up WebSocket connections, or use EventSource. If you don't know what Event source is, maybe you've heard the term server sent events it's over HTTP. It's a long polling connection, basically in the background that let's you Like, basically ping a client from the server and say, hit me up for some more data.

Form action, that is a white list of origins that you can form posts to. Image, media, and object source, those are get requests, right? That's a white list of only allowing images from this domain or flesh embeds, things like that. We've got style sheets, upgrade and secure request, this is an interesting one.

So if you have a huge web application you're trying to migrate to HTTPS and you have a whole bunch of links. Say you're a CMS, a Content Management System. And users have generated a ton of content. And you've got a bunch of HTTP links baked into your data.

What this will do is it will instruct the browser that you wish to take those links And rewrite them to HTTPS. And then, obviously you're gonna wannna go through and alter your data over time. But this kind of tells the browser that you wish to have it assist you in the meantime, while that effort is underway.

So default source, think of that as the general fallback in the event that you don't have a named directive, like if we had no image source directive in our content security policy. We could basically say, by default, unless I've specifically name a directive, here are the sources that you should allow for that.

Any questions about content security policy?
>> Speaker 2: To a great and secure quest. This is gonna automatically, [COUGH] flip HTTP to HTTPS then for in the browser like in the client or how is it gonna work?
>> Mike North: It depends what you mean by that. Can you?
>> Speaker 2: Well, so let's say the user requests the resource by HTTP.

>> Mike North: Yes.
>> Speaker 2: And we have that specified, so is the browser gonna flip it to HTTPS?
>> Mike North: That's not what this does. Basically it means that when the browser finds HTTP links in your HTML, it will attempt to rewrite them as HTTPS links.
>> Speaker 2: Okay, got it.
>> Mike North: Right.

>> Speaker 3: John and Chad's asking if older browsers understand the headers for CSP?
>> Mike North: Some of them. So older browsers have implemented a subset of CSP headers. In fact, some newer browsers are trying to lean more on CSP and less on separate headers and meta tags. So you'll see, this is almost like, if you've ever dealt with SEO and meta tags, we've gotta have a huge list of non-intersecting stuff for Apple and Android.

And you basically have to just define whatever you can, hope that browser respect it, and then put in some extra stuff. We'll talk about some legacy stuff we can use for older browsers like IE9 that don't handle CSP or release than newer version of CSP that I do stuff properly.

So there are a few keywords we can use along side sources. So sources are typically origins. None is like it's make certain things forbidden,, imagine if we had object source, like I don't allow flash. So object source none would say, I never allow flash. In a document served up from this domain, flash is off limits even if I happen to have some in the code ,don't run it.

Self is whatever the current origin is, so that's usually pretty safe and pretty smart. Same origin, like we already trust that for a variety of reasons. Unsafe-inline, that allows inline JavaScript and CSS, meaning like a unclick equals execute this function, or a script tag that's baked into your HTML.

Unsafe-eval would allow eval. So by default, if you have script source, if you're gonna start to define the kinds of JavaScript that you'll allow. The default is like, all right, now that you're defining it, we're not in everything is allowed mode anymore. The default position is, eval is not allowed, which is a good thing simply because that is a potentially dangerous thing to do.

Now unfortunately on the other side, we found that eval can be a performant thing to do. Some of the common templating engines and stuff, instead of sending code over the wire to represent a UI component, they'll send a string or something else. And we only evaluate that into code just in time.

We only pay the cost of turning text into an abstract syntax tree right before we render. And so, there you might find that you have to flip the switch back on. All right, however, there are ways that we can make unsafe-inline a little less unsafe. But it's important to realize, this is the most common means of cross-site script injection today.

When I recalled myself earlier with Man-In-The-Middle Framework and the BeEF Framework, that was by adding a little script tag. So this is what we have to watch out for. And sometimes it's been official to have one of these little things in there. Maybe it's that our app is a little bit on the heavy side, and we want just some core piece of script to run.

Just enough to make our navigation work or something, while we wait for our client's side app to download. That is a real use case. What we can do, one way of solving that is to generate what's called a cryptographic nonce. And these are generated on each payload. They increment in an unpredictable way, so that an attacker can't read this and figure out what a future nonce might be.

And we add that to our Content Security Policy header. So basically, the response header and the script itself here, they must line up in order for that tag to be run. So that's one way of doing it. Another way of doing it is to add basically a checksum to the content security policy.

So what we have here is a script tag, and we've got some inline code in it. And basically, we have permitted it by adding this sha256 string to the bottom here. The easiest way to generate this, the easiest way to find this is to use the browser itself, use a browser itself.

So basically, you would leave this out of the content security policy, try to visit the page, the error message is gonna be like, I'm sorry, you're not allowed to run this piece of code that I found with the following hash, sha256, [SOUND]. And then, you take that and you can move it into your CSP.

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