Magento 2.3.5 + Content Security Policy (CSP): A Fool's Errand
Published: April 29, 2020
On April 28, 2020 Magento 2.3.5 was announced. It included an exciting new security enhancement, implementation of a Content Security Policy (CSP), available for both Magento Commerce and Magento Open Source.
This release includes a set of powerful new security tools for Magento installations. Content Security Policies (CSP) provide additional layers of defense by helping to detect and mitigate Cross-Site Scripting (XSS) and related data injection attacks.
While this sounds great in theory, in practice, as things stand in Magento 2.3.5, Content Security Policy offers little to no value. In this post we’ll take a look a why.
Taking A Step Back - The Threat Model
Currently the biggest security concern facing Magento merchants is what’s known as “Magecart”.
Hackers commonly do this by gaining access to their target’s Magento admin panel, such as through a weak or stolen credential. They then take advantage of the Miscellaneous HTML feature of Magento (intended to allow administrators to add benign tags) to inject their malicious payload.
Given this threat model, Content Security Policy on the surface seems like the perfect solution…a whitelist of allowed scripts which can prevent these malicious scripts from running.
unsafe-inline. This alone is pretty much game over given the previously outlined threat model as all the attacker needs to do is use an inline
However, even if Magento is able to remove all inline script from the codebase there’s still a long journey before we can feel safe with our CSP. Let’s look at some more issues…
In addition to inline scripts, Magento currently requires specifying
unsafe-eval to operate. Magento’s CSP architecture design document explains this a bit:
There is no way to disable unsafe-eval right now since we use it for UI components and some of the front-end libraries we employ need it (like jQuery). A strategy must be created to remove eval() usage from UI components.
The document makes no mention of KnockoutJS which essentially will need to be ripped out to work with CSP.
<div data-bind="value: alert(1)"></div>
Lack of strict-dynamic support
Currently, Magento’s Content Security Policy uses a whitelist approach. It ships with a list of domains that must be whitelisted for core functionality to work, and offers an extensible framework for developers to whitelist additional domains.
The problem is, back in 2016 Google found that 95% of whitelist based CSPs can be trivially bypassed. One of the most common reasons for this is that whitelisted domains contain JSONP endpoints that can be abused to bypass the CSP.
Here’s an example of how whitelisting the required domains to embed Twitter tweets allows attackers to bypass your CSP:
<script src="https://platform.twitter.com/widgets.js"></script> <script src="https://cdn.syndication.twimg.com/timeline/profile?callback=__twttr/window.alert&screen_name=shinkbr"></script>
Google’s CSP Evaluator tool helps with identifying known dangerous hosts. The CSP on Magento Marketplace (which runs Magento 2.3.5) currently whitelists 4 separate domains that contain flagged JSONP endpoints.
Google essentially concluded their research that whitelist based CSP is “infeasible in practice” and recommend an alternate approach called
strict-dynamic, which involves adding a nonce or hash to each script tag, and whitelisting those in the CSP.
strict-dynamic will then propagate trust to additional scripts that are loaded by these scripts.
strict-dynamic is not a panacea. There are many known bypasses including bypasses abusing KnockoutJS
Magento’s architecture document states they plan to support
strict-dynamic in the future, but as of 2.3.5 it is not an option.
But CSP Can Block Exfiltration, Right?
Most Magecart payloads exfiltrate data by sending an AJAX request to the 3rd party server, and occasionally use an image tag, so you may be thinking that even if you can’t stop scripting you can keep yourself safe by preventing exfiltration via the
img-src directives. Unfortunately, that’s not true.
Sebastian Lekies can school you about this on Twitter:
CSP will not prevent or mitigate this attack and it should not be advertised this way.— Sebastian Lekies (@slekies) January 7, 2018
Ultimately, there’s a long list of ways to exfiltrate data from the page that are not subject to CSP, and it should be considered as a means for blocking scripting, not exfiltration.
Then What Can I Do?
There are a number of things I would recommend a merchant begin to do before considering Content Security Policy. Let’s go back to the original threat model. Typically it involves a malicious code being injected into Miscellaneous HTML. A good first step would be to regularly review the contents of this field for changes. Make a snapshot of the contents and store it in a separate location. At some regular schedule check Magento to see if it’s changed. If it has, check whether it was authorized (e.g. marketing team updated something) or malicious. Assuming it was authorized, update your snapshot and check against that.
As a next step, you can consider doing the same with your CMS content, particularly if you inject a CMS block into checkout page. This could be a lot of content, so you probably don’t want to do this manually. My MwscanUtils2 module may help you.
You can also consider doing this with Google Tag Manager, which has the potential to also be abused for Magecart.
If you’re doing all these things and you still want to take things to the next level Content Security Policy could be an option for you at some point. As of Magento 2.3.5, it’s not a good option though. And even if all the issues called out above are resolved in Magento core, keep in mind it will likely be a big investment to integrate it into your website, will be difficult to get right, will be expensive to maintain, and in the end should not be perceived as offering a guarantee of any sort.