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
- 1. Use Content Security Policy
- 2. Limit Admin Session Lifetime
- 3. Reset Admin Path Regularly
- 4. IP and Password Protect the Admin Area
- 5. Two-Factor Authentication
- 6. Force an Admin Password Change
- 7. Use the Official Magento Security Scan Tool
- 8. Monitor the Payment Page HTML for Changes
- 9. Spot a Code Change with GIT
- Summary
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/
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:
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.
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:
An example of how you can whitelist JS:
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:
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.
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:
Then enter a not-easy-to-guess custom admin path:
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:
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.
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:
A user will get a request for code when attempting to log in:
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:
Two important settings here: Password Change and Password Lifetime (days):
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.
It can scan the site daily or weekly. It emails a report with issues if any.
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.
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 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!