Loading..
Processing... Please wait...

Product was successfully added to your shopping cart.



Magento Skimmer Protection in 9 Steps

Protect Magento From Skimming Malicious Code

Disclaimer: The purpose of this post is to teach Magento store owners how to protect their online store.

Table of Contents:

How a Credit Card Skimming code could be added to a Magento 2 checkout page?

There are several ways a skimming malware could be injected into Magento.

They could use some clever exploit.

They could alter code files

OR

And that might be the easiest way - they could hijack an admin session and get administrative privileges.

I’ll show you how it could be done.

Let’s say, you have a long Magento admin session lifetime. Attacker doesn’t have to worry about session expiration.

They somehow got an active admin url, for example:
http://m247.goivvy.com/admin_nmkykw1/admin/system_config/edit/section/catalog/

If they try to access that url with curl they get a user/pass page:

curl  http://m247.goivvy.com/admin_nmkykw1/admin/system_config/edit/section/catalog/key/011c6928910d4ea3b41baa09c74b67fb8cefe6ef65bd036d960f2c2753374507/

Curl to Admin Backend

Not really helpful, as Magento wants them to authenticate.

Now suppose they not only got an admin URL but also had an access to cookies:

Admin Cookie

Now all they need to do is to supply curl with admin cookies and viola:

curl -H 'Cookie: admin=isdaupcmqjmum2uled34vc7n3m'  http://m247.goivvy.com/admin_nmkykw1/admin/system_config/edit/section/catalog/key/011c6928910d4ea3b41baa09c74b67fb8cefe6ef65bd036d960f2c2753374507/|grep catalog_search_opensearch_index_prefix

Magento 2 admin becomes accessible to hackers.

Curl to Admin

Magento 2 Admin Page

Now as long as the session is active and not expiring, an attacker has full access to your Magento configuration.

They can add malicious code to all of your pages (including the checkout) with a simple POST request.

I’m not going to show specific commands they’d run but getting ‘admin’ cookies could lead to serious damage.

We will look at ways to prevent Magento and Adobe Commerce skimming attempts.

1. Content Security Policy (CSP) and Magento 2

CSP tells a browser which Javascript code could be executed with everything else ignored.

Magento 2.4+ supports CSP policies with a core module Magento_CSP.

You can choose two modes: Report-Only or Restrictive and it’s set in vendor/magento/module-csp/etc/config.xml:

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd">
    <default>
        <csp>
            <mode>
                <storefront>
                    <report_only>1</report_only>
                </storefront>
                <admin>
                    <report_only>1</report_only>
                </admin>
            </mode>

With Report-Only set to 1 a browser doesn’t block suspicious JavaScript code but only reports it in Developer Console:

CSP Report

An example of how you can whitelist JS:

CSP Header

You set a special header Content-Security-Policy (add Report-Only if you only need to report) with a list of all domains you allow a browser to execute JavaScript (or run iframes) from.

Inline Javascript code needs to be whitelisted too. If you just try to add the following to the checkout page:

<script> console.log(‘test’) </script>

The script wouldn’t be executed and you’d get an error in developer console:

JavaScript code blocked

You’ll need to base64 and sha256 encode the code first:

$hash = base65_encode(hash(‘sha256’,’<script> console.log(“test”) </script>’,true))

And add the hash to etc/csp_whitelist.xml of a custom module:

<?xml version=”1.0”>
<csp_whitelist>
 <policies>
   <policy id=”script-src”>
     <values>
       <value id=”goivvy-script” type=”hash” algorithm=”sha256”>ENTER_HASH_HERE</value>
     </values>
   </policy>
 </policies>
</csp_whitelist>

Use vendor/magento/module-sales/etc/csp_whitelist.xml as a reference.

Starting from Magento 2.4.7 all frontend payment pages are in a CSP restrictive mode. Even if a malware code was added to the checkout page a browser wouldn’t execute it.

2. Limit Admin Session Lifetime

We saw in the beginning that with an active admin cookie an attacker can have full control over Magento 2 system configurations. This is called session hijacking.

The longer the session lifetime the more damage an intruder could cause.

By default, Magento 2 admin sessions live 900 seconds or 15 minutes.

Admin Session Lifetime

You can shorten it to 5 or 10 minutes. I’d never go above 15 minutes even though it’s annoying to have to login to the backend each time.

Go to Stores > Configuration > Advanced > Admin > Security > Admin Session Lifetime and set it to 300 seconds (5 minutes).

3. Change Admin Path Regularly

Most Magento 2 exploits require a hacker to know the admin path. By setting a hard-to-guess URI you make your ecommerce store more secure.

Set a bi-weekly timer to change the Admin Path.

Go to Stores > Configuration > Advanced > Admin > Admin Base URL and set ‘Use Custom Admin Path’ to Yes:

Use Custom Admin URI

Then enter a not-easy-to-guess custom admin path:

Hard to Guess Admin URI

Hit save and relogin to the backend.

4. IP and Password Protect the Admin Area

Restricting access to the admin area is another way of fighting off credit card skimmers.

You can either IP or Password protect the backend. You can also implement both.

If you are running Nginx, place the following directives inside nginx.conf for IP protection:

location ~ ^/admin_ {
    allow 127.0.0.1;
    deny all;
    fastcgi_pass   fastcgi_backend;
    fastcgi_buffers 16 16k;
    fastcgi_buffer_size 32k;
    fastcgi_param  PHP_FLAG  "session.auto_start=off \n suhosin.session.cryptua=off";
    fastcgi_param  PHP_VALUE "memory_limit=756M \n max_execution_time=18000";
    fastcgi_read_timeout 600s;
    fastcgi_connect_timeout 600s;
    fastcgi_param  SCRIPT_FILENAME  $document_root/index.php;
    include        fastcgi_params;
}

Add more allow directives with IPs you’d want to whitelist. The system will block anything else automatically.

Next you can add HTTP Basic Authentication. Anyone trying to access the backend will be asked for user and password:

HTTP Basic AUTH

Create an authentication details for admin user with htpasswd command:

htpasswd -c /etc/nginx/.htpasswd admin

And then add basic_auth directives to Nginx:

location ~ ^/admin_ {
    satisfy all;
    allow 127.0.0.1;
    deny all;

    auth_basic 'Restricted';
    auth_basic_user_file .htpasswd;

    fastcgi_pass   fastcgi_backend;
    fastcgi_buffers 16 16k;
    fastcgi_buffer_size 32k;
    fastcgi_param  PHP_FLAG  "session.auto_start=off \n suhosin.session.cryptua=off";
    fastcgi_param  PHP_VALUE "memory_limit=756M \n max_execution_time=18000";
    fastcgi_read_timeout 600s;
    fastcgi_connect_timeout 600s;
    fastcgi_param  SCRIPT_FILENAME  $document_root/index.php;
    include        fastcgi_params;
}

Here, with ‘satisfy all’ directive you choose to enforce both IP and Password protection.

You can set ‘satisfy any’ and then a user could access the admin panel if it either has the right IP or the right user/pass pair.

location ~ ^/admin_ {
    satisfy any;

    allow 127.0.0.1;
    deny all;

    auth_basic 'Restricted';
    auth_basic_user_file .htpasswd;
    ….

5. Two Factor Authentication for Admin Panel

Two-Factor authentication (2FA) is when you need more than a password to log in.

Magento 2 supports various 2FA including Google Authenticator App, U2F and others.

Magento 2 Two-Factor Authorization

You can set available providers to use at Stores > Configuration > Security > 2FA.

Starting from Magento 2.4 2FA is on by default, you don’t have to specifically enable it.

To turn it off do the following SSH commands:

php bin/magento module:disable Magento_TwoFactorAuth Magento_AdminAdobeImsTwoFactorAuth

php bin/magento deploy:mode:set production

I’m strongly recommending to keep 2FA always on for all admin users.

You can reset providers for a user on a user edit page:

User 2FA

A user will get a request for code when attempting to log in:

2FA Email

6. Force a Regular Admin Password Change

Adobe Commerce and Magento Open Source have the whole configuration settings tab dedicated to Admin Security.

It lives at Stores > Configuration > Advanced > Admin > Security:

Admin Security

Two important settings here: Password Change and Password Lifetime (days):

Password Change

You can either ‘Force’ or ‘Recommend’ a backend user password change every N days.

I’d recommend forcing an admin to change a password every 30 days for better security.

7. Monitor the site with an official Magento Security Scan Tool

Adobe offers a free Magento security scan service. It checks the site against known threads, bugs and exploits.

Magento Security Scan Tool

It can scan the site daily or weekly. It emails a report with issues if any.

Scan Report

I find this tool very useful. It did alert us of an injected skimmer code on several occasions.

8. Spot a Change in the Payment Page HTML

Credit card skimming code is invisible and is hardly noticeable. You cannot visually detect it if it was placed.

But you can detect a change in the payment page HTML. This will alert you of any potential hack attempt.

Here is what you can do to spot malicious code on the payment page:

  • Save the checkout page HTML on disk and make it read-only
  • Each morning download the current checkout page HTML and compare it against the one you saved earlier
  • If there is a change, inspect it to see if it looks suspicious. If it does - delete it and notify a system administrator or a developer.

PHP API library for Selenium WebDriver can help automate this process.

PHP WebDriver API

Selenium WebDriver is a framework for web browser automation. You can control a browser, open and navigate pages, click links and fill out forms. This all could be done programmatically.

You’d need to create a script that:

  • Opens your website
  • Adds a product to the cart
  • Proceeds to the checkout
  • Downloads the checkout HTML
  • Compares this HTML against what was saved on disk
  • Send an alert if a change is detected

9. Monitor File Changes with GIT

Bad guys can also alter code files to add skimming code.

If you could spot a change early you could prevent a disaster.

GIT is a popular version tracking system. It can help monitor for unwanted code edits.

GIT

git status command will tell you if any changes were made.

Add it to cron jobs and setup alerts if changes were detected.

Summary

Skimming malware poses a threat to Magento websites. You have to be proactive to stay safe and protect customers’ sensitive information.

There are easy yet effective measures you can take to fight off online credit card thieves:

  • Keep Content-Security-Policy in a restrict mode on the payment page
  • Set Admin Session Lifetime to 15 minutes or less
  • Change Admin path to something hard to guess
  • Put the admin area behind HTTP Basic Authentication
  • Allow only certain IPs to view the admin area, block access for the rest
  • Keep 2FA for backend logins
  • Make admin users change password regularly
  • Use a free Magento Security Scan tool
  • Monitor the payment page HTML for unauthorized changes
  • Track unwanted code changes with Git version control system

Follow these guidelines to keep Magento 2 checkout secure. Report any suspicious skimming activity to the hosting company for investigation.

If you need help with an ecommerce site - contact me today!

  

Find this article useful? Share it on LinkedIn with your professional network, spread the knowledge!

If you find this post interesting do not hesitate to sign up for our newsletter and join the 1007 people who receive Magento news, tips and tricks regularly.


Thank You!