These mitigation options leverage Content Security Policy (CSP) response headers and Subresource Integrity (SRI) security features offered in modern web browsers. In a previous blog post, I introduced Security Response Headers and briefly discussed CSP. In this blog post, we will dive deeper into CSP and options that can help mitigate the Skimmer threat model.
Example Inline JS Skimmer Code
The highlighted section of the HTML page shows the injected code. There is some simple obfuscation techniques used, such as base64 encoding, which attempts to hide the code's intentions and purpose. This code attempts to steal customer data and then send it off to a 3rd party URL shown in the following screenshot:
Data Exfiltration URL
There are many websites that are still currently compromised with this payload. The domain name used to exfiltrate the customer data is purposefully named to look like a Google domain and to try to blend in with normal traffic. If we inspect the URL on the urlscan.io website, we can see an example of what the data exfiltration URL looks like and what type of data is being passed in the "image_id" query_string parameter.
Urlscan.io Analysis Page
Content-Security-Policy: script-src 'self'
A whitelist for specific inline scripts using a cryptographic nonce (number used once). The server must generate a unique nonce value each time it transmits a policy. It is critical to provide an unguessable nonce, as bypassing a resource's policy is otherwise trivial. See unsafe inline script for an example. Specifying nonce makes a modern browser ignore 'unsafe-inline' which could still be set for older browsers without nonce support.
The updated CSP policy header could look like this:
var something = 1;
CSP nonce Violation Message in Firefox
Nonce Implementation Considerations
CSP nonce values must be unpredictable and change with every page invocation. Google has some good information on this topic. This scenario is a bit reminiscent of Cross-site Request Forgery (CSRF) mitigations using synchronizer tokens. The main issue organizations need to figure out is how to add these CSP nonce values to the responses. If you are using an application templating system such as Closure, you may be able to use it to add in the CSP nonces.
A sha256, sha384 or sha512 hash of scripts or styles. The use of this source consists of two portions separated by a dash: the encryption algorithm used to create the hash and the base64-encoded hash of the script or style. When generating the hash, don't include the <script> or <style> tags and note that capitalization and whitespace matter, including leading or trailing whitespace. See unsafe inline script for an example. In CSP 2.0 this applied only to inline scripts. CSP 3.0 allows it in the case of script-src for external scripts.
There are many tools that can be used to create a hash of this content. Report-URI has a handy web tool that will generate a hash of the content for you:
Script Hash Tool
Now that you have a proper hash of the script contents, you can update your CSP policy header to look like this:
Multiple hash values can be specified in the CSP header to allow for all script tags to work.
If your script content is not static and may contain dynamic data, you might have to default back to using nonce instead.
There is an obvious security benefit in applying CSP hash validation to inline scripts, however this does come with some increased overhead and management to ensure proper functionality. Keep in mind that for the scope of this blog post we are focusing on combating a specific threat - malicious skimmer code on checkout pages. If you wanted to apply this CSP policy to a specific checkout page on your site, you could use Akamai's Property Manager to configure the desired behavior as shown in this screenshot:
CSP Behavior Logic in Property Manager
This example CSP behavior shows that our targeted policy will only be sent for a specific hostname and for a specific path location which corresponds with our checkpage where customers would be entering their credit card data. Perhaps this is the only page on your website where you utilize CSP hashes. You could very well use different, easier CSP policies on the rest of your site or even none at all. If you start with a targeted CSP use-case and focus on securing your checkout pages then CSP hash management becomes feasible.
Example JS Skimmer Script Tag
Obfuscated JS Skimmer Code
This obfuscated code is similar in functionality to the previous inline version. Do note the base64 decoded value I highlighted in the popup dialogue as it lists the 3rd party URL for data exfiltration. It is using a similar technique of trying to blend in with the ReactJS domains. As a matter of fact, if you attempt to access the main URL it will redirect you to the React website.
Specify All script-src Source Domains
Script Management Dashboard
Important Note - Akamai customers must also include specific domains in the CSP policy to ensure proper functionality on any Akamai products they might be using. For example, if you are using mPulse, you would need ensure that the proper Akamai domains are listed to support mPulse configuration downloads and data beaconing functionality.
Once you have identified all authorized 3rd party script locations including Akamai mPulse domains, advertising and analytics
networks, you can then modify your CSP header like this:
Content-Security-Policy: script-src 'self' c.go-mpulse.net
s.go-mpulse.net *.mpstats.us *.akstat.io *.doubleclick.net
Now that you have a listing of all of the legitimate domains of script sources, CSP could easily block the execution of the example injection we saw previously to the billgetstatus.com domain.
Specify All script-src Source URLs
Let's say that you are using jQuery to interact with Google's APIs. You could update your CSP header's script-src list to specify the exact URL for the jQuery version you are using like this:
Content-Security-Policy: script-src 'self'
This would only allow loading of that exact file over HTTPS versus whitelisting the entire ajax.googleapis.com domain.
If you don't want to have to maintain a whitelist of all script-src sources in your CSP header, then you use nonce values as we covered in the previous section. Remember, the CSP policy header could look like this:
Content-Security-Policy: script-src 'nonce-1182b04d9fA988B6EcD336EEfbe'
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js" nonce="1182b04d9fA988B6EcD336EEfbe"><script>
The strict-dynamic source expression specifies that the trust explicitly given to a script present in the markup, by accompanying it with a nonce or a hash, shall be propagated to all the scripts loaded by that root script. At the same time, any whitelist or source expressions such as 'self' or 'unsafe-inline' will be ignored. See script-src for an example.
The updated CSP policy header could now look like this:
Content-Security-Policy: script-src 'nonce-1182b04d9fA988B6EcD336EEfbe' 'strict-dynamic'
$ curl -s https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js | openssl dgst -sha384 -binary | openssl base64 -A
Now that you have a proper hash, you can use it in the integrity script attribute like this:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js" integrity="sha384 lifoBlbdwizTl3Yoe612uhI3AcOam/QtWkozF7SuiACaf5UJl5reOYu4MigVxrCH" crossorigin="anonymous"></script>
When the Firefox web browser receives this response, it will check the SRI integrity value, block the code from running and will generate the following error in the console:
SRI Hash Validation Error Message
Content-Security-Policy: script-src 'self' https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js; require-sri-for script
This is a great feature for ensuring that all scripts on the page have SRI enforced, however there is one current limitation. Although most modern browsers support this feature, it isn't actually shipped yet and enabled. Browser compatibility shows that end users must enable experimental feature options in their browsers for this to work.
Browser Support for require-sri-for option
Here is a screenshot of Firefox about:config showing CSP experimental features are disabled by default.
Same goes for Chrome chrome://flags/#enable-experimental-web-platform-features:
Until such a time as the browser vendors decide to actually ship these features and enable them, require-sri-for will not be enforced. That is except for those advanced users that have these features enabled. This doesn't mean that you should not use this feature. You should enable it now and when browsers start supporting the feature by default it will be enforced.
Data Exfiltration Defense
Important Note - There is much debate in the academic and practitioner communities around the effectiveness of CSP to prevent data exfiltration. We are not proposing that CSP can be used as a panacea for all data exfiltration techniques. The approach that follows is to outline current Magecart modus operandi tactics for data exfiltration and to show how CSP can be used to limit their effectiveness.
Exfiltration with XMLHttpRequest (XHR)
In the case of the Newegg Magecart compromise, the attackers used the following XHR code to send the captured customer data off to their domain:
Newegg Magecart Code
Controlling XHR with CSP connect-src
CSP v3 connect-src can control the following script interface APIs:
If you know that your checkout page should never be using any of these features, then use the following directive:
Content-Security-Policy: connect-src 'none'
This would prevent the Magecart code from being able to initiate one of these connection types to send snarfed data off to the attackers.
Exfiltration with Image() Constructor
Another sneaky method of sending captured data off to the attacker's site is to use Image fetching functionality. Here is an example showing the use of the Image() constructor:
Why would an attacker use this mechanism? Organizations might not be prioritizing controlling Image downloads and may therefore have left open this gap that attackers can use as a method of data exfiltration. If you know that your checkout page should only be calling image files from your own domain, then use the following directive:
Content-Security-Policy: img-src 'self'
CSP Violation Reporting
Implementing these CSP + SRI controls is the top priority for preventing Magecart attacks and protecting your website visitors. A close second priority is receiving CSP violation report telemetry. Oftentimes organizations who are implementing CSP use reporting during the initial testing phases but then will disable it for normal operation. This is unfortunate as this capability is critical for being able to quickly identify outbreaks of new attacks against your customers. CSP reporting is controlled via the report-uri or report-to (CSP v3) directives.
Akamai customers can use Property Manager to set these CSP headers as discussed previously. In this screenshot, we show adding a CSP header with a report-uri directive that points back on-domain so that any violation reports sent by clients will come back through the Akamai platform.
Property Manager Showing CSP Header Configuration
Another point to highlight here is the use of Property Manager built-in variables. In this case, I am using the AK_REQUEST_ID variable inside a query_string parameter of report-uri. I am doing this so that when the CSP header is set, Property Manager will dynamically add in the request ID that the Akamai Edge platform has assign to this unique transaction to the CSP header.
CSP Header Includes Request ID Data
This data can be useful when analyzing CSP violation report data if you need to trace back requests on Akamai's platform.
Enable CSP Violation Report Rules in Kona Site Defender (KSD)
KSD customers can enable a new rule that will identify and report on CSP violation reports that are configured to come back to the Akamaized customer domain.
New KSD Rule for CSP Report Alerting
Notice the different rule options that are available. Keep in mind - these rule actions are being applied to CSP violation reports that are being sent from the web client as defined by report-uri or report-to directive in the CSP response header. If you already have CSP reporting configured to send violation telemetry back to Origin and you would simply like to additionally log violation report data in KSD, you can set the rule to Alert. If, however, you would like for KSD to act as an actual CSP report-uri endpoint, you can configure the rule to Deny. This would stop the CSP violation report at our Edge platform and not forward it into Origin. Regardless of whether you choose Alert or Deny, KSD reporting will start capturing events when a CSP violation report is observed at the Edge.
Analyze CSP Violation Reports in Web Security Analytics (WSA)
Once the previous rule is activated and CSP violation reports start coming in, you will be able to view them in the WSA dashboard.
CSP Violation Reports in WSA