The latest version of PCI DSS just dropped and it’s really awesome to see that one of the most notorious threats that we face online when it comes to payment card data is now being directly addressed. Magecart has wreaked havoc on some really large brands and well known organisations over recent years and caused millions of dollars worth of damage. Maybe this is the beginning of the end for them?
PCI DSS v4.0
If you’re not familiar, the PCI is the Payment Card Industry, the set of organisations responsible for making credit and debit cards work like American Express, Visa, Mastercard, etc… The PCI SSC is the PCI Security Standards Council and they are responsible for producing the PCI DSS, the PCI Data Security Standard. If you handle Payment Card Data (PCD), you are required to comply with PCI DSS in some way. Even at Report URI, where we don’t do any payment processing ourselves and we use Stripe, we are still required to comply with PCI DSS in the form of PCI DSS SAQ A and you can see our attestation of compliance linked in the footer of our site.
The latest version of PCI DSS, v4.0, has just landed and it has been over 8 years since the last major update. In that time, Magecart and similar attacks have caused huge problems and financial losses for the PCI and, unsurprisingly, the PCI SSC has added some new requirements in PCI DSS aimed solely at neutralising such attacks in the future. What follows is my reading and interpretation of the new PCI DSS requirements that combat Magecart.
Protecting Payment Pages
The PCI DSS gives the following definition of a payment page:
A web-based user interface containing one or more form elements intended to capture account data from a consumer or submit captured account data. The payment page can be rendered as any one of:
- A single document or instance,
- A document or component displayed in an inline frame within a non-payment page,
- Multiple documents or components each containing one or more form elements contained in multiple inline frames within a nonpayment page.
In the typical flow of an ecommerce transaction you will have the checkout page, that lists all of the items you want to buy. You then confirm that’s what you want to buy and you are taken to the payment page, where you insert your PCD and pay for the items. Once the payment is successfully processed on the payment page, you are then taken to the payment confirmation page that says thanks for your purchase and confirms it was completed. It makes sense that the new requirements target only payment pages, as those are the pages where a hostile skimmer would have access to the PCD to steal.
Requirement 6: Develop and Maintain Secure Systems and Software
6.4 Public-facing web applications are protected against attacks.
Looking over requirement 6.4.3, it’s pretty clear that the objective here is to combat Magecart and similar attacks, even though they’re not called out by name. The associated guidance for this section gives a detailed explanation of how a typical Magecart skimming attack would take place and how these new requirements are intended to combat it. Looking at the main bullet points in 6.4.3, we have the following three things that need to happen:
- A method is implemented to confirm that each
script is authorized.
- A method is implemented to assure the integrity
of each script.
- An inventory of all scripts is maintained with
written justification as to why each is necessary.
The first bullet point is of course Content Security Policy and the second bullet point is Subresource Integrity, but the final bullet point implies something quite interesting. For scripts on the payment page you must have a “written justification as to why each is necessary“. Not a justification for why it is desired or why it is there, but why it is necessary. The PCI SSC also provided a clear definition of exactly what it means by “necessary”:
“Necessary” for this requirement means that the
entity’s review of each script justifies and confirms
why it is needed for the functionality of the
payment page to accept a payment transaction
That’s pretty clear that JS on the payment has to be necessary for the purposes of accepting a payment transaction, and not any other purpose. This is really important because historically, when investigating Magecart and Cyrptojacking attacks, I’ve noticed that sites seem to have a whole load of JS on the payment page because it was “required”. The JS on the payment page that was used in some of the more notable attacks was “required” for tracking the user through the checkout flow, providing chat bots or widgets, or it was simply there because JS tags were present on all pages throughout the application and the payment page was no exception. The payment page only needs to do one thing and that’s accept the PCD from the user to process a transaction, and it’s now really clear that the only JS allowed on the page is JS used for that purpose alone.
A great example of where this would have stopped a large scale attack was the Ticketmaster and Inbenta case covered by RiskIQ here. Inbenta provided a chatbot that Ticketmaster loaded on their site and, as I see so often, Google Tag Manager was used to inject the JS tag on every page of the site. Inbenta were compromised and the JS was used to skim PCD because the chatbot was loaded on the payment page. Imagine a user navigating your whole site, putting items in their basket, going to the checkout and finally arriving at the payment page, only to think “oh yeah, I could do with starting a customer support chat now“… That JS simply shouldn’t have been on the payment page and if it hadn’t been there, this whole attack would have never happened. Under the new rules, the presence of this chatbot on the payment page would be prohibited.
Another common argument I receive for arbitrary JS on the payment page is conversion tracking, but this is so easily remedied. If you track the user to the checkout page, skip the tracking on the payment page and then track them to the payment confirmation page, you know they converted! There’s always a way to solve the problem without having heaps of JS on the payment page, and now as an industry we’re going to have to exercise those solutions.
At the end of 6.4.3 we get some examples on how we might be able to achieve the requirements set out above.
- Sub-resource integrity (SRI), which allows the
consumer browser to validate that a script has
not been tampered with.
- A CSP, which limits the locations the
consumer browser can load a script from and
transmit account data to.
- Proprietary script or tag-management
systems, which can prevent malicious script
SRI is a clear and obvious win for avoiding scenarios where the 3rd-party script that you load is modified, like the Ticketmaster and Inbenta example above. The only script that should now be loaded on payment pages is script that is required for processing the transaction, but still, you should be using SRI on any 3P JS wherever possible.
CSP is also called out as the obvious choice for how we can authorise certain scripts to be allowed on our payment page and not allow any other scripts to run. What’s more interesting though is that the PCI SSC has picked up on a couple of things that are often missed with CSP. First, with CSP you can control where content, like JS, is loaded from, but you can also control where data is sent with features like connect-src and form-action! If you have a payment page, it’s going to be pretty likely that there’s only a single location that data from that page should be sent to, and you can make sure that happens with CSP. The other one is that you can control where iframes are loaded from, and again, it’s very likely that when taking payment, you should only be loading an iframe from one place, and that’s your Payment Services Provider!
The final bullet seems to be giving site operators the ability to use an alternative to CSP and/or SRI, but I’m not really aware of a tag management system that can prevent malicious script from executing, but maybe those features will come in time. I’m looking at you, GTM…
Requirement 11: Test Security of Systems and Networks Regularly
The other major requirement of note is one that also targets payment page monitoring with CSP. Essentially, this is a detective control to complement the protective controls in 6.4.3.
11.6 Unauthorized changes on payment pages are detected and responded to.
Looking at a couple of phrases here, it’s clear what is being required.
11.6.1 A change- and tamper-detection mechanism
is deployed as follows:
- To alert personnel to unauthorized modification
… to the HTTP headers
and the contents of payment pages as received
by the consumer browser.
- The mechanism is configured to evaluate the
received HTTP header and payment page.
I think one of the key points to note here is that this requirement applies to the contents of the payment page “as received by the consumer browser”. We’re not talking about an inventory or monitoring of scripts added on the server side, but looking at what happens in the client. It’s pretty clear to me why that’s the case, but the requirement goes on to clarify for the reader:
Therefore, the only place to detect changes or
indicators of malicious activity is in the consumer
browser as the page is constructed and all
Bingo! This is precisely what is required because unless you’re doing some pretty slick synthetic browsing and monitoring activity, the only place to know for sure what’s happening is on the client and CSP is already there to help you do that. The final examples given in this section are also food for thought.
- Violations of the Content Security Policy (CSP)
can be reported to the entity using the report-to or report-uri CSP directives.
- Changes to the CSP itself can indicate
- External monitoring by systems that request
and analyze the received web pages (also
known as synthetic user monitoring) can
pages and alert personnel.
- Embedding tamper-resistant, tamper-detection
script in the payment page can alert and block
when malicious script behavior is detected.
- Reverse proxies and Content Delivery
Networks can detect changes in scripts and
To see CSP reporting called out in the guidance is absolutely epic. I’ve long been a fan of CSP and reporting, of course having gone on to found Report URI, because it is genuinely useful and it really can help you detect and mitigate attacks like Magecart. The other point in there that I noted was the final one, that CDNs can detect changes in scripts and alert personnel. It might not seem immediately obvious how that could happen, but one thing jumped to mind for me right away and that was the recent Cloudflare acquisition of Zaraz. By taking the execution of JS from the browser and moving it to the CDN edge node, the CDN provider has a clear view of what that JS is doing and can take protective action if required. Cloudflare also went on to blog about how Zaraz supports CSP and they’re doing dynamic CSP modification at the edge to allow their own JS on the page. It’s certainly an interesting time and these new PCI DSS requirements are going to make solutions like this look very attractive. We already do CSP nonces the easy way with Cloudflare Workers at Report URI, and I think interest in this area is only going to increase now.
Start working towards compliance
Whilst these new requirements are currently a best practise, meaning they are not yet required, they still exist for a reason and honestly, you should be taking steps to protect your ecommerce now! From March 2025 all of the above will be required so it’s probably best to start the process of investigating and implementing these measures sooner rather than later.
We’ve been working on solutions to help combat Magecart for quite some time now and if you want to know how easy it can be to get started on creating a CSP and using this awesome feature, check out the following blog posts:
To summarise though, I’m really impressed and happy with these latest requirements from the PCI SSC. Calling for the absolute minimum possible amount of JS on a payment page is always going to be the best approach and using a combination of CSP and SRI to make sure that happens is the icing on the cake.
Setting up CSP can be difficult on a large site and I’ve worked with a lot of customers where this is the case, but setting up a CSP on a single page, just the payment page, well that would be an absolute breeze!
If you want a TLDR summary of the new rules to share, here you go:
- Payment pages must only load JS required for processing payments.
- Payment pages must restrict what JS loads, for example with CSP.
- Payment pages must integrity check JS, for example with SRI.
- Payment pages must be monitored for changes, for example with CSP reporting.
Keep an eye out for more blog posts and announcements from Report URI on how we plan to do even more to help organisations comply with these new PCI DSS Requirements and help to protect against serious attacks like Magecart.