PCI 6.4.3 Reduce JavaScript Skimming Attacks!

JavaScript skimming attacks are posing a significant threat to e-commerce platforms. In response, the Payment Card Industry (PCI) has introduced new requirements in PCI DSS V4.0 and the latest SAQ A and A-EP. Notably, PCI 6.4.3 has attracted significant attention. Here's a developer's guide to effectively implementing this requirement.

PCI DSS 6.4.3 requirement calls for organizations to manage all payment page scripts loaded and executed in the consumer’s browser. It stipulates:

  • Confirmation that each script is authorized.
  • Assurance of each script's integrity.
  • Maintenance of an inventory of all scripts with a written justification for their necessity.

Mastering CSP and SRI: Your Arsenal Against Script Attacks

Content Security Policy (CSP) and Subresource Integrity (SRI) are our primary weapons against these threats.

CSP allows website administrators to restrict the content sources allowed on their site. A whitelist of authorized sources, included in the CSP, determines which scripts get loaded and executed on the payment pages.

Here is a sample CSP meta tag for your HTML document. It whitelists scripts from 'self' and 'trusted-source.com':

<meta http-equiv="Content-Security-Policy" content="script-src 'self' https://trusted-source.com;">

The given script is implementing a Content Security Policy (CSP) within a webpage. The CSP is a security feature used to prevent Cross-Site Scripting (XSS), clickjacking, and other code injection attacks. The policy is declared via the <meta> tag in the HTML document's <head> section.

The http-equiv="Content-Security-Policy" attribute in the <meta> tag is defining the policy, and the content attribute is specifying the policy details.

In this case, content="script-src 'self' https://trusted-source.com;" indicates that the policy allows scripts (script-src) to be loaded from two sources:

  1. 'self': This keyword allows scripts to be loaded from the same origin as the webpage. In other words, if your webpage is on https://example.com'self' would permit scripts to be loaded from https://example.com.
  2. https://trusted-source.com: This is a specific external domain that you trust and from which you want to allow scripts to be loaded.

Any attempts to load scripts from sources not specified in this policy will be blocked by the browser, increasing the security of your webpage by preventing unauthorized scripts from executing

Subresource Integrity (SRI) enables website administrators to ensure that only the intended version of a script is loaded on their site. To use SRI, generate a cryptographic hash of the script file and include it in the script tag. If the hash matches, the script is considered validated and executed.

Below is an example of how to use SRI with a script tag:

<script src="https://trusted-source.com/script.js" integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC" crossorigin="anonymous"></script>

This HTML script tag is instructing the browser to load a JavaScript file from the URL https://trusted-source.com/script.js. Additionally, the tag contains a couple of key attributes that relate to security and integrity verification:

  1. integrity: This attribute is part of Subresource Integrity (SRI), a security feature that enables browsers to verify that resources fetched from third-party servers have been delivered without unexpected manipulation. It does this by comparing the hash value (in this case, the SHA-384 hash) provided in this attribute with the hash value of the actual fetched resource. If the two hash values match, the browser understands the file hasn't been tampered with and loads the resource; if they don't match, the browser refuses to execute the script, preventing any potential injection attacks.
  2. crossorigin: The crossorigin="anonymous" attribute in the script tag is used in conjunction with the Subresource Integrity check. It enables the browser to fetch the resource in CORS mode without including user credentials (like cookies or HTTP authentication mechanisms). If the server does not return the Access-Control-Allow-Origin header (or it has not included the domain of the site in that header), the browser will stop the loading of the resource. This attribute is essential because, without it, the browser's same-origin policy would prevent the SRI check from working properly when the resource is fetched from a third-party site.

In summary, this script tag is loading a JavaScript file in a secure manner, ensuring that the file is fetched from a specific source and that it has not been manipulated or tampered with during the process.

Remember to set the crossorigin="anonymous" attribute when using SRI. Failing to do so can nullify its security benefits by ignoring the integrity attribute.

Inventorying Scripts: The Developer's Tools

As developers, we can use JavaScript in the developer tools console to identify the scripts running on our site. The resulting list of scripts should be logged for future reference, especially during audits.

Here's an example of a script that you can use to generate an inventory of scripts running on your webpage:

(function() { var scripts = document.getElementsByTagName("script"); var srcs = []; for (var i = 0; i < scripts.length; i++) { if (scripts[i].src) { srcs.push(scripts[i].src); } else { srcs.push("inline script"); } } console.log(srcs); })();

This JavaScript code is a self-invoking function (meaning it will automatically run as soon as it is defined) that collects information about all the scripts present on a webpage and logs it to the console.

Here's what each part does:

  1. var scripts = document.getElementsByTagName("script");: This line gets all the <script> elements on the webpage and stores them in the scripts array.
  2. var srcs = [];: This line creates an empty array named srcs. This array will be used to store the sources (src attribute) of all scripts found on the webpage.
  3. for (var i = 0; i < scripts.length; i++) {...}: This is a loop that iterates over every script found on the webpage.
  4. Inside the loop, there's a conditional statement: if (scripts[i].src) {...} else {...}. This checks whether each script has a src attribute (meaning it's linking to an external script).
  5. srcs.push(scripts[i].src);: If the script does have a src attribute (i.e., it is an external script), the value of the src attribute (the URL of the script) is added (pushed) to the srcs array.
  6. srcs.push("inline script");: If the script does not have a src attribute (i.e., it's an inline script), the string "inline script" is added (pushed) to the srcs array.
  7. console.log(srcs);: Finally, the srcs array, which now contains the sources of all scripts on the webpage, is logged to the browser's console.

In summary, this script provides a quick way to view all the script sources on a webpage, which can be particularly helpful for debugging or security auditing.

Browser extensions like ScriptSafe, NoScript, or uBlock Origin can also be employed to show scripts running on a page.

Implementing these practices aligns with the PCI DSS 6.4.3 requirements, fortifying our cybersecurity defenses and ensuring a secure e-commerce environment.

In an era of escalating cyber threats, adhering to standards like PCI DSS is not an option but a necessity. As software developers, we must integrate these security measures into our practices for safer, securer online shopping experiences.


Scroll to Top