Conf42 JavaScript 2021 - Online

CSP is broken, let’s fix it

Video size:


The CSP standard was supposed to improve the security of websites. But, like any standard, it needs to evolve to stay relevant, both in the assumptions on how sites are working and what is the reality in the implementation. In this talk, we will discuss those gaps. First, we will demonstrate how the standard can be abused and is abused when facing real-world uses. Second, we will cover multiple implementation gaps causing it to misbehave in browsers and expose information to attackers. Third, we will review and analyze bad implementations by website owners who place poor configuration, misunderstandings of the directives and outdated configurations. These three gaps between the standard and real-world uses will be the basis to discuss the improvements and considerations DevSecOps need to consider using CSP while discussing ideas on how to improve the standard.

The talk will cover the following points: 1. A brief overview of the history behind CSP (3 minutes) 2. The timeline of main changes, early versions to current (5 minutes) 3. Where it went wrong - abusing the safelist concept to inject code and extract information (15 minutes) 4. Examples of poor implementation by browsers - not covering all angles, CVEs and other gaps (10 minutes) 5. Poor usage examples by webmasters (5 minutes) 6. Thoughts on how CSP 3 (or 4) can remediate that to make a more secure internet (5 minutes)

Attendee takeaways include:

  1. CSP Isn’t a silver bullet
  2. Skimmers are a new breed of APT
  3. Checklist for your own site


  • Amir Shaked: Today we're going to talk about CSP. How is it broken? What can we do to fix it? Or at least just demystify some of it?
  • Even though you have CSP you don't usually have it all the way and where are gaps and problems with that. We see cases where even though that should have been in place and CSP in some cases was in place, still the attack vector succeeded.
  • CSP adds another layer of security to the site, mostly to protect from XSS and data injection. Once you go into specifications, the problem is they're not fully defined. Implementation itself may be lacking in different browsers.
  • content security policy is on the rise as more or lets about 10% of the websites. But only 17% out of 620. domains actually implement CSP. Here are some of the reasons for the difficulties in implementing the concept.
  • You will get violations from a lot of stuff which are unrelated to the website. Different browsers do different things. If the number of reports per incident per domain is low or too low, it might be a good indication that it's noise. And these last is browser misalignment.
  • A very strict policy, a very good policy, might also protect you from potential bugs in the browser's implementation. Once you have a safe list, nothing really protects you from sending different kinds of information. The next these was let's try to protect it, maybe by query programs.
  • Skimmers are those using the javascript to inject content and steal data from the website. CSP is not a silver bullet and you should have a checklist for your own site. These are the three things I want you to take from this session.


This transcript was autogenerated. To make changes, submit a PR.
Hi everybody, thank you for joining me today. Today we're going to talk about CSP. How is it broken? What can we do to fix it? Or at least just demystify some of it? My name is Amir Shaked. I work at perimeterx. I did the R D there, software engineer for many years, R D leader for a few as well and building things with good people. And this talk we're going to talk a bit about breaking and building things and how they come together when we're talking, but CSP. So let's begin with these story. And I love to begin with stories. The story here is I wanted to enable CSP on my website. I read and understood the full meaning of all the directives that the implementations, the CSP two, CSP three, all the variances in the standard. I added the header to the website with a report only option and started getting traffic into some lambda functions that consumed all the reports. About a day later I went over the reports. It was very clear which report is what. I marked all the resources that are related to our website and updated these policy. I switched the policy to block policy which basically means no reporter what's blocking policy and I had zero issues. The website worked flawlessly and without any problem or anything crashing, no support call to say some part of the website stopped working somehow and I think nobody ever said that story when it comes to CSP. I've talked to many people in the industry who tried to use this really positive standard with good intentions, but everybody had some kind of issue along the way trying to improvements it in their website. More common case that we have seen is on several websites is a case where they're getting some call from their credit card company or another vendor. They're working on mostly the credit cards company telling them that there was a breach. Credit cards were stolen from their websites and when they're doing the deep dive, usually with some consultant when doing the deep dive trying to identify where and what and how the breach was made, they end up finding that actually there was no direct breach to the site, but a breach to a third party vendor. And that vendor was responsible and it was basically injecting additional code on the front end and sending data to some new destination. Now in practice, this is something that CSP by design should have stopped. And yet time and time again we see these cases happening on websites where even though that should have been in place and CSP in some cases was in place, still the attack vector succeeded and data was exfilterated from the site and we touched on a few points on why even though you have CSP you don't usually have it all the way and where are gaps and problems with that. So just in these word what is CSP? And I'm going to do a short technical session here on what is CSP and how it's actually being used and works. So CSP is a policy. First of all that's important to remember. It's a policy which adds another layer of security to the site, mostly to protect from XSS and data injection and data existration to different domains. First introduced by the way all the way back in 2004. But since 2013 went these multiple iterations of the common standard that we have today that we see today on many websites, with the final version of version three pretty close to being finished. So it's a very late draft and version two is the one most commonly used today in websites with CSP. So how does it work? Basically you have an HTTP header that you add on the back end and you have two of those. And we're going to touch on the difference. The header says that you have in this example what we have here. So we have default source saying self, default source, self mean by default sources of different elements can come from the domain itself, the parent domain that serve the website scripts can come from two destinations, self and these cDNJs net another network. And if these is any kind of validation, the report URL where data should go is the top level domain CSP logging. So that's these destination that will receive all the reports of all violations happening on the front end on different users to the CSP policy that we defined here. And then we have in the HTML page two elements, the image and the script. And both will work. The image will load because it's coming from on the default source and these script will load because it's allowed as a script source on that specific directive. Now if somehow in some way the last element here would have been added, the directives that we had would make that forbidden and we would have been receiving a report saying try to be accessed and to load a script. So where is the problem with that? Once you go into specifications, the problem is they're not fully defined. And even though going back here to this example, most of the directives are very well defined in what they should do and shouldn't do. It's still an RFC, it's still something that every browser need to improvements on their own. And nothing here says what should be the report. And I'm going to show example of where everything has all the variations. So what a report holds. For example, every browser can decide what they want to push into reports. We do see an improvement there with more considerations, but again there are variances that we've seen with different browsers reporting the same violation when to report. Another interesting point, should I report only once? Should I report every time per session, per page? And that leads to a lot of inconsistency and affects how the system that you're using can learn from that. Implementation itself may be lacking in different browsers. We're going to touch on one example for a specific CVE, but there are a lot of other cases where the browsers don't implement that complicated RFC as it should and it's usage dependent and that can be abused. And we're going to do a deep dive to an example of why by design there is a flaw in the concept of policy and a whitelist. So let's start with numbers. I think numbers talk better than anything else. It's a standard that was been existing since 2012, how much is it used, how often it is and how everybody are using it. So this data is based on information that I extracted from HTTP archives going over their scans on the past two years. Excellent data source if you want to research how the web changes and behaves over time, by the way. So an excellent data source to use. And what we have here is scan domains over time and show it with the mouse. So we have can domains over time. So that gives us the reference point of how many domains are being tested. And what we can see is that content security policy is actually being uses more and more over time, which signifies a positive trend until you're starting to dive into the details and you see what's the difference. So we see a great adoption of other security headers. You can see the list here on the left, on the right, sorry, which different security headers were found on those scans. And we see that CSP is behind adopted on the rise as more or lets about 10% of the websites. So it looks like a positive trend. But when you would deep dive to see what's actually being used along these different directives for CSP, these are the numbers that pop up when you're inspecting. So we had 690,000 domains that actually used CSP at all, out of 4 million websites, sorry, 6 million websites that were scammed. And the first, these are actually just a replacement of obsolete security headers that were common before. So the frame ancestors simply says, do you allow the browser to load your website in a frame or not. That's one upgrade insecure. Again, replacement says that for previous security header, mentioning that the traffic should only be HTTPs. So don't allow HTTP traffic to the parent domain only HTTPs traffic and block mixed content. So again an additional layer on that only the follow up if you're going to default source where it's actually getting interesting, actually use more complicated directives and trying to actually use the policy of where data should be loaded from or sent to. And that's only 17% out of the 620. That means a much lower number actually implementing CSP and trying to get all the value out of these directives. And that's a very sad data point. And I think a really big part of it is some of the reasons that we're going to talk on later on on the difference between the concept, which is great, and the difficulties in implementing it which makes it very hard to be uses out there. So and I'll give one example, diving into the directives themselves that we see being used in the wild here is one example. You see the default source and there is a very big difference between the two options here. What you see on the top one is on this one is on their website, allowing on these default source any unsafe eval, meaning any script can use eval and basically run any code you want and any inline code in the page. That basically means that between these two options anything can run on the page. You didn't really enable any additional security layer, you're allowing everything to run on the page. That's the worst kind. On the far left of the security spectrum you have actually nonsense of the hash of the script itself that should be allowed to run and that's great if you're using that feature. That means that only specific scripts can run and inline scripts can run and not everything. So being a very strict great option, but very few websites actually use that one. Besides that we've seen again deep diving into the data from actual websites, really poor usage and I was looking for common directives being used and there should be around 30 and I found over 700 with some really mind blowing examples here. I don't understand this, go for it. But then all kinds of just bad implementations. I don't know if it's in policy or the web servers, but it's really sad if somebody actually tried to use the policy and then broke it with invalid information in the policy itself. If you're trying to use it, please I beg you, uses something like this link here, the CSP evaluator by Google, which is really good, and save yourself the trouble of having worked so hard to create a policy and then having it be unavailable to websites because it has bugs in these configuration. Okay, so we talked a bit about the policy. Let's talk about the reports. I have a policy in place. I want to dissect the reports and understand them and the data isn't normalized at all. These two links here are actually fascinating when you inviting you to go and browse into them and you will see different types of examples of reports coming in from websites. And these reason is you will get violations from a lot of stuff which are unrelated to the website. And that can be very causing when you're trying to understand you see some two or three reports of some domain and you can't find how it's related to the website itself. And that could very well be coming from somewhere else, say extensions, ads, web proxies, both injecting code into the page, completely irrelevant to the policy and the website you actually build. So you need to find a way to reduce all that noise and focus only on the interesting reports. One way of doing that is by numbers. If the number of reports per incident per domain, for examples, is low or too low, it might be a good indication that it's noise and you can ignore that and focus only on the high number of reports. That's one example that you can use. But again, very interesting examples and I invite you to go through them. I didn't want to do that, waste our session for that. And these last is browser misalignment. That's actually a very big issue and you should be aware of that. Different browsers do different things. This is the latest information that I have might have changed a long time because the browsers are always updating the way they report. But from our last these, we saw that these kind of differences, I'll highlight only key ones for chrome. If you have a repetitive call to a blocked resource, you only get one report. For Firefox you will get repeating reports. So that's different. With Safari, you might get only the truncated top level domain and not the full blocked uri, which you might have wanted the full uri to see more information. So these kinds of differences make it very different to analyze the reports that you're getting between browsers. And like we saw here, between other things that might create noise leading to a problem of essentially log spamming. There is no validation, there is no validation on who is sending the data. And anybody can push information into your system on supposed violations. It could be even fake reports hitting directly your API and reporting fake CSP violations only to try and game your system. If you have say an automatic system that automatically whitelists domains per number of occurrences, somebody can try and use that and create some adversarial machine learning concept of tricking the system to whitelist a domain. Haven't seen that yet, but definitely a concept that is out there being discussed. Okay, another thing is it has an implementations gaps like everything. In this case you can see the cves over time with different browsers, specifically mentioning CSP and the various implementations that it has in browsers. And I want to touch on one specific CVE that we discovered and reported on about a year ago, and that is this one. So using the above policy, which seems very strict, objects can be loaded from nowhere and child from nowhere, and scripts only from the parent domain. And the trick here is we define a URL obviously coming from an unauthorized location, and we're creating can element and doing child append with that element. And the script runs and it doesn't run, sorry. And these script doesn't run. But if you're running the same thing this way this call will succeed and will be evaluated and these code will be loaded into the page. Why is that? Because of the complexities of how the engine, browsers engine works, and it's quite complicated to create a very bulletproof system. So this is an example where even though you had a very strict policy, we found a way where the code were still running and loaded, even though it should have been running. That CB has been reported, has been closed. But it's just an example where even though you think you have a very strict policy, there might be a bug in the browsers itself, causing it to be irrelevant. An interesting point to make. Websites that loaded, that used these nonsense for the timeline scripts were not vulnerable to this bug because they were restricting inline scripts to come only from those known hashes, which is why this works on some websites and not on other websites that were more strict in their policy. The point to make here is that a very strict policy, a very good policy, might also protect you from potential bugs in the browser's implementation. So what can possibly go wrong with these policy? We've talked a lot about different aspects of CSP, the implementation, the configuration, but there is a core issue with the concept of a policy that makes it vulnerable, and I want to touch on that because it's a very interesting one. In this research we took a different approach. We said, and this is over time, let's look at the most common allowed targets. Whatever it's coming from, the script, the default, the object, whatever it is, these are the common allowed targets. And we can see here a specific domain coming repeatedly Google Analytics on the different variations on March 2000 and went it was more common. It was common on June 2021 it was way more common. And we said okay, let's pick these top one the most commonly whitelisted domain on website and let's think what can we do with it and how can we game the concept and abuse the CSP policy simply because that domain is whitelisted? And it's a fascinating one once you have a safe list, if the safe list is a generic destination where everybody can create an account in, nothing really protects you from sending different kinds of information. And point to make here for Google Analytics is we added this code into the website that had CSP with a very strict policy but had Google Analytics allowed. And essentially what this means is that we can send information to any id that we want to show you here where it is. So the tid, we basically can define any id that we want to send the information to, which will allow us to see the information sent on our dashboard of Google Analytics and not another dashboard. And example here is you saw the code collecting the information and sending it and you can see it here, very simple. In the Google Analytics dashboard we have the hash, we can dehash it, we have the username and the password being sent from a website that had a policy but allowed Google Analytics. The next these was let's try to protect it, maybe by query programs or something else. How can we at least improve the system? So wouldn't this be nice if we could have said ok, you can connect to Google Analytics, but only to a specific target id, not any target id. And then you can protect the system but you can't. And the quote from the RFC basically says the exact point query strings have no impacts they're not being matched on, meaning you can't add that layer of protection. And we are focusing here on Google Analytics. But it's important to remember, if we go back to this list, there are other domains here which simply pick the top one and said can anybody create an account, in this case a completely free account, and use that to exfiltrate information simply because it was whitelisted. But other domains here are easily, easily applicable for them as well, simply because the way the concept works of the safe list, and it's not just a theory. We published a post about the method in June 17 and just a few days later, other security vendors found that specific usage being used in the wild by attackers to exfiltrate information and basically abuse that layer of protection coming from CSP. So think about it. We added all the layers of protection, we configured a very strict policy, we made sure it is working properly. But the basic flaw is that one domain that we uses is a generic domain that anybody can open an account on, top level domain, and that allows anybody to bypass all the protection that we're trying to add with CSP. Basically, it's crazy if you think about it now, one would claim that it might be valid, but where did the code come from? So they might be able to abuse the destination, but can they abuse the source of the data? And that's an interesting point to be made. A very common Tac vector would be to target an open destination that you're using and replace their code. It could be a third party vendor that you're using that you already whitelisted. It could be obsolete domains. And these are examples that we've seen, domains that were whitelisted. And because it's a whitelist policy, you don't get reports of the part of the policy not being used. So you had a vendor, maybe a startup that you tested and you worked with, you added them, you tried to see how it works, maybe even uses them for a while. They closed the domain, might even be up for sale, but you did not remove it from your policy. Because of the way these process works between say DevOps and front end development or whoever actually added it, it could be even somebody from the marketing team and these domain has been open for purchase and somebody could take over it. So we saw examples of domains being whitelisted that are no longer valid. But even taking can example from earlier this year, 2021 where Cloudflare had a bug was discovered in the CDNJs network that allowed an arbitrary person to come in and replace code with any library that sits on the CDN. That means that these risk there was that anybody could create a hijack and replace the code. And if you're loading libraries from that specific destination, you could have been exposed potentially to such a risk. Now that vulnerability was discovered and closed. So it's not actively a risk, but there are other such cdns and vendors that everybody are using that are always at risk. So the point to make here is both destinations are at risk because of the way the policy is defined with the whitelist. So somebody can come in through an allowed service and send exerted information to another allowed service. In the policy. So where it went wrong, it went wrong because first of all, managing a policy, it's hard. It doesn't always hold in today's modern web apps with these rate of changes and things being added and basic things of abusing the safe list to inject code and extract information simply breaks the entire concept that sits behind CSP, kind of rendering it invalid, which is a very bad using. So how can we make the best of it? Well, in coming to look at this problem, one would say it's a terrible idea, don't use CSP, there is no value in it. So I wouldn't go that far, but I gave examples. But once you understand the gaps, the potential gaps, you understand that CSP is a good layer of protection that you should add what you should use it for, but it's not these holy grail. It doesn't stop everything. So you shouldn't count on it as the only thing that will protect you against access or data injection or data exfiltration from the front end of the page. So a few would say tips on how to make the best of it. So filtering the report is definitely something that you should do and not spend your was your time going over all the violations? A b testing the policy a wonderful concept. One way to reduce the risk of having obsolete domains in the policy is doing a b test on the report only policy. So you could have a very strict report only policy, constantly adding and removing domains from the list. And if you see that you have a domain that you don't get any reports on, that means that it's not being used anymore. That means you can remove it from the strict blocking policy, because if you're not getting reports and this allows you to test if a specific domain is being used or not without damaging the experience of the users. So that allows you to keep a very clean and lean domain list in. The policy has different levels of strict policy for different pages. A sensitive page page with purchase login, things like that is definitely a place to have a very strict policy and also reduce the number of libraries that you have there. The Google Analytics was an example. Let's not have it in a specific page that has a risk of that specific link that we discussed. And if you don't have it, then you reduce the risk altogether. And you can limit the problem for specific pages with that PiI that you're trying to protect, not necessarily the entire website clean up every once in a while. That connects very well to the third point of how you can actually do it. Always consider adding additional layers of security, such as the nons and the hashes for the inline scripts and the external scripts. Again, it could sound very difficult and a lot of work, but if you limit that to sensitive pages then the work is much smaller and it's very specific, so it's more manageable. I would say for a modern web app with multiple components going back to being the same thing, context aware. And the last thing I really wish anyone here in this forum, especially with this conference, the conference two focusing on JavaScript and I don't know how much you want you like security, but it's a big part of what you can do with it on the front end. So contribute to the CSP three with comments and I think any improvement can make this better. And that's it. A few takeaways just to consider in mind. So we talked but skimmers in a brief those using the javascript to inject content and steal data from the website. It's an increasing risk and you should take it in mind when you're adding and removing libraries into your website, specifically JavaScript libraries, that CSP is not a silver bullet and we've covered very extensively why and that you should have the checklist for your own site, what you should do and which resources are critical. Yes or no. These are the three things I want you to take from this session, and I will have be able to answer questions on the discord or you can reach out to me if you want later on. Thank you,

Amir Shaked

Senior VP R&D @ PerimeterX

Amir Shaked's LinkedIn account Amir Shaked's twitter account

Awesome tech events for

Priority access to all content

Video hallway track

Community chat

Exclusive promotions and giveaways