Security Concepts

Security should always be a strong consideration for anything related to an e-commerce project. Without a strong security stance, the surface area that can be attacked is exponentially larger. The concepts and ideas presented provide methods that are proven to reduce the common vulnerabilities typically exploited.

The following concepts are not in any particular order. They are meant to provide some ideas and concepts to consider. Many are free or would require minimal setup and configuration and subsequent monitoring. Research these topics outside of this tutorial to ensure you have a deep enough understanding of the concepts presented here.

Read-only file system

The Read-only file system concept was borrowed from Adobe Commerce on cloud infrastructure. This completely removes one major area used by a bad actor. Many exploits have taken advantage of altering a file that is expected to be in the Commerce application to avoid detection. Instead of creating one, the bad actor changes the contents of an existing file to perform an unexpected action. Making the file system read-only reduces this attack vector significantly.

Use TWO Factor authentication and password managers

Never share passwords. Each admin user should have their own account with proper ACL. Ensure that two factor identification is never disabled or removed. If you provide admin access to a third party, ensure that the password is generated by a password manager and never reused.

Malware scans

Malware scans are typically found from a hosting provider that tries to specialize in Adobe Commerce. This library of known malware and exploits is an ever growing list as new threats are discovered, triaged, and diagnosed. Inquire if the hosting provider has such a service and if they can be run automatically or only upon request. There are also services that you can subscribe to that can use their own library of known exploits to constantly check your commerce application for exploits. Some of these are external only, some can be added to the infrastructure to provide an internal deep scan of all the folders, files, and even the database. There are a few providers with years of experience in this arena, from to Sucuri and of course MageReport. Some are free, and some come with an associated cost. Knowing this is available and having a thoughtful conversation with your Adobe Commerce architect and DevOps team will ensure you find the right solution.

Site-Wide Analysis Tool for Commerce

The Site-Wide Analysis Tool is a proactive self-service tool and central repository that includes detailed system insights and recommendations to ensure the security and operability of your Adobe Commerce installation. It provides 24/7 real-time performance monitoring, reports, and advice to identify potential issues and better visibility into site health, safety, and application configurations. It helps reduce resolution time and improve site stability and performance.

Enable and verify settings for Admin Actions Logging

This can be found after logging into the Adobe Commerce admin and navigating to Stores > Configuration > Advanced > Admin > Admin Actions Logging. This provides a list of events that are monitored and recorded. It is useful when doing forensic analysis on an exploited site, if the suspicion is they gained access to the Commerce admin. This logging and report can be helpful to see what events the bad actor performed. If any admin actions logging are disabled that is a sign that someone may have disabled them for cover remove the logging when performing certain actions.

Bastion Server for ssh access

This is harder to explain that most topics in the Security Concepts tutorial. The basic idea for this is to provide a server that acts as a middleman for ssh access. This way, your production servers never allow external ssh connections. You can create this bastion server and use a local IP mask to ensure that only designated servers are allowed to SSH into them.

Review ACL roles and permissions

Every admin user of Adobe Commerce is assigned an ACL role. This role should be created to provide only the functionality must perform the job. The ACL roles should be evaluated often, to ensure they do not provide more authority than necessary. If needed, create many ACL roles with responsibilities. If access is granted to a third party for some reason, they should be deactivated as soon as possible. Ask them how long they absolutely need access and setting an auto expiration date when creating their admin user.

Audit admin users and SSH user access frequently

To detect unwanted or unauthorized admin user creation, the admin users list should be audited frequently. A good rule of thumb is to check who has SSH and admin access to the Adobe Commerce application monthly. If any new users are detected, disable their account and follow any company policy and procedure for such an incident. It is easier to reinstate a users access than it is to recover from an exploit.

Database cleansing

Limit access to production data. These designated teammates should have the ability to pull down production databases, and cleanse them of real data. If removing the data is an option, truncate the appropriate tables such as orders, quotes, and customers. However, sometimes you want the complete set of data, but the values can be anonymized. This is typically true in a staging environment. It is also useful prior to upgrades. By having the real volume of data, but anonymized ensures you are testing and validating the time to execute a deployment for upgrade properly. Should you have a limited set of data, you may underestimate the upgrade process and timing.

Randomize customer information example

Here is an example for how to change out customer email address with a random string and all first name and last mane fields in some standard tables that Adobe Commerce stores data. Remember to check all tables for sensitive data, this list is not all inclusive to the tables that may store customer data

code language-sql
UPDATE customer_entity SET email = REPLACE(email, SUBSTRING(email, LOCATE('@', email) +1), CONCAT(UUID(), '.com'));
UPDATE email_contact SET email = REPLACE(email, SUBSTRING(email, LOCATE('@', email) +1), CONCAT(UUID(), '.com'));
UPDATE sales_invoice_grid SET customer_email = '', customer_name  = 'Jack Smith';
UPDATE sales_order SET customer_email = '', customer_firstname = 'Sally', customer_lastname = 'Smith', remote_ip = '';
UPDATE sales_order_address SET region = 'Ohio', postcode = '12345-1234', lastname = 'Smith', street = '123 Main street', region_id = 44, city = 'Phoenix', telephone = NULL, firstname = 'Jane', company = NULL;
UPDATE sales_order_grid SET customer_email = '', shipping_name = 'Jack', billing_name = 'Jack Smith', billing_address = '123 Main Street', shipping_address = '321 Pine Street', customer_name = 'Jane Smith';
UPDATE sales_shipment_grid SET customer_email = '', customer_name = 'Jane Smith', billing_address = '123 Main street', billing_name = 'Jack Doe', shipping_name = 'Susie Smith';
UPDATE quote SET customer_email = '', customer_firstname = 'Sally', customer_lastname = 'Jones', customer_dob = NULL, remote_ip = '';
UPDATE quote_address SET email = '', firstname = 'Jack', lastname = 'Smith', company = NULL, street = '123 Main st', city = 'AnyCity', region = 'Some State', region_id = 44, postcode = '12345-1234', telephone = NULL;
UPDATE magento_rma SET customer_custom_email = '' WHERE customer_custom_email IS NOT NULL;
UPDATE customer_address_entity SET firstname = 'Jack', lastname = 'Smith', telephone = '909-555-1212', postcode = NULL,  region = NULL, street = '123 Main street', city = 'Anycity', company = NULL;
UPDATE customer_grid_flat SET name = 'Jane Doe', email = '', dob = NULL, gender = NULL, taxvat = NULL, shipping_full = '', billing_full = '', billing_firstname = 'Jack', billing_lastname = 'Smith', billing_telephone = NULL, billing_postcode = NULL, billing_country_id = NULL, billing_region = NULL, billing_street = '123 Main street', billing_city = 'Anycity', billing_fax = NULL, billing_vat_id = NULL, billing_company = NULL;
UPDATE sales_creditmemo_grid SET billing_name = 'Sally', billing_address = '123 Main Street', customer_name = 'Jack Smith', customer_email = '';

UPDATE magento_rma_grid SET customer_name = 'Jack Smith';
You can also truncate tables instead of trying to anonymize
code language-sql
TRUNCATE customer_log;
TRUNCATE customer_visitor;
TRUNCATE magento_logging_event;
TRUNCATE oauth_consumer;
TRUNCATE oauth_nonce;
TRUNCATE oauth_token;
TRUNCATE password_reset_request_event;
TRUNCATE acknowledgement;
TRUNCATE acknowledgement_report;
TRUNCATE avatax_log;
TRUNCATE avatax_queue;
TRUNCATE cron_schedule;
Remove information completely example

Here is an example for removing all orders, quotes, credit memos, and more prior to launch or for a lower dev environment

code language-sql
DELETE FROM `gift_message`;
DELETE FROM `inventory_reservation`;
DELETE FROM `quote`;
DELETE FROM `quote_address`;
DELETE FROM `quote_address_item`;
DELETE FROM `quote_id_mask`;
DELETE FROM `quote_item`;
DELETE FROM `quote_item_option`;
DELETE FROM `quote_payment`;
DELETE FROM `quote_shipping_rate`;
DELETE FROM `reporting_orders`;
DELETE FROM `sales_bestsellers_aggregated_daily`;
DELETE FROM `sales_bestsellers_aggregated_monthly`;
DELETE FROM `sales_bestsellers_aggregated_yearly`;
DELETE FROM `sales_creditmemo`;
DELETE FROM `sales_creditmemo_comment`;
DELETE FROM `sales_creditmemo_grid`;
DELETE FROM `sales_creditmemo_item`;
DELETE FROM `sales_invoice`;
DELETE FROM `sales_invoiced_aggregated`;
DELETE FROM `sales_invoiced_aggregated_order`;
DELETE FROM `sales_invoice_comment`;
DELETE FROM `sales_invoice_grid`;
DELETE FROM `sales_invoice_item`;
DELETE FROM `sales_order`;
DELETE FROM `sales_order_address`;
DELETE FROM `sales_order_aggregated_created`;
DELETE FROM `sales_order_aggregated_updated`;
DELETE FROM `sales_order_grid`;
DELETE FROM `sales_order_item`;
DELETE FROM `sales_order_payment`;
DELETE FROM `sales_order_status_history`;
DELETE FROM `sales_order_tax`;
DELETE FROM `sales_order_tax_item`;
DELETE FROM `sales_payment_transaction`;
DELETE FROM `sales_refunded_aggregated`;
DELETE FROM `sales_refunded_aggregated_order`;
DELETE FROM `sales_shipment`;
DELETE FROM `sales_shipment_comment`;
DELETE FROM `sales_shipment_grid`;
DELETE FROM `sales_shipment_item`;
DELETE FROM `sales_shipment_track`;
DELETE FROM `sales_shipping_aggregated`;
DELETE FROM `sales_shipping_aggregated_order`;
DELETE FROM `tax_order_aggregated_created`;
DELETE FROM `tax_order_aggregated_updated`;
DELETE FROM `magento_rma`;
DELETE FROM `magento_rma_grid`;
DELETE FROM `magento_rma_item_entity`;
DELETE FROM `magento_rma_status_history`;
DELETE FROM `magento_sales_creditmemo_grid_archive`;
DELETE FROM `magento_sales_invoice_grid_archive`;
DELETE FROM `magento_sales_order_grid_archive`;
DELETE FROM `magento_sales_shipment_grid_archive`;
DELETE FROM `sequence_creditmemo_0`;
DELETE FROM `sequence_creditmemo_1`;
DELETE FROM `sequence_creditmemo_2`;
DELETE FROM `sequence_creditmemo_7`;
DELETE FROM `sequence_invoice_0`;
DELETE FROM `sequence_invoice_1`;
DELETE FROM `sequence_invoice_2`;
DELETE FROM `sequence_invoice_7`;
DELETE FROM `sequence_order_0`;
DELETE FROM `sequence_order_1`;
DELETE FROM `sequence_order_2`;
DELETE FROM `sequence_order_7`;
DELETE FROM `sequence_rma_item_0`;
DELETE FROM `sequence_rma_item_1`;
DELETE FROM `sequence_rma_item_2`;
DELETE FROM `sequence_rma_item_7`;
DELETE FROM `sequence_shipment_0`;
DELETE FROM `sequence_shipment_1`;
DELETE FROM `sequence_shipment_2`;
DELETE FROM `sequence_shipment_7`;


ALTER TABLE sequence_creditmemo_0 AUTO_INCREMENT=1;
ALTER TABLE sequence_creditmemo_1 AUTO_INCREMENT=1;
ALTER TABLE sequence_creditmemo_2 AUTO_INCREMENT=1;
ALTER TABLE sequence_creditmemo_7 AUTO_INCREMENT=1;
ALTER TABLE sequence_invoice_0 AUTO_INCREMENT=1;
ALTER TABLE sequence_invoice_1 AUTO_INCREMENT=1;
ALTER TABLE sequence_invoice_2 AUTO_INCREMENT=1;
ALTER TABLE sequence_invoice_7 AUTO_INCREMENT=1;
ALTER TABLE sequence_order_0 AUTO_INCREMENT=1;
ALTER TABLE sequence_order_1 AUTO_INCREMENT=1;
ALTER TABLE sequence_order_2 AUTO_INCREMENT=1;
ALTER TABLE sequence_order_7 AUTO_INCREMENT=1;
ALTER TABLE sequence_rma_item_0 AUTO_INCREMENT=1;
ALTER TABLE sequence_rma_item_1 AUTO_INCREMENT=1;
ALTER TABLE sequence_rma_item_2 AUTO_INCREMENT=1;
ALTER TABLE sequence_rma_item_7 AUTO_INCREMENT=1;
ALTER TABLE sequence_shipment_0 AUTO_INCREMENT=1;
ALTER TABLE sequence_shipment_1 AUTO_INCREMENT=1;
ALTER TABLE sequence_shipment_2 AUTO_INCREMENT=1;
ALTER TABLE sequence_shipment_7 AUTO_INCREMENT=1;

Use Environment Variables

[Adobe Commerce on cloud only]{class="badge informative"}

Using environment variables helps by allowing you the ability to set certain values that can and should be changed for each environment. For example, you may want to have different admin URL for every environment. By setting this value as an Environment Variable, you are able to configure this and also reference this value quickly from the Cloud UI when necessary.

You can read more on this topic in Experience League Commerce on Cloud infrastructure Environment Variables

Software vulnerability scanning tools

The CI/CD pipeline can be a powerful tool and help automate some tasks. In particular, the opportunity for a developer to commit code that may be exploitable is always a real possibility. Peer code reviews normally catch such items, but because it is a human, mistakes happen. Automated code scanning helps reduce the opportunity for unexpected vulnerabilities in a newly introduced feature. These tools can even be in place to block merging of code into the live codebase. There are many ways and tools to offer automated code security and quality scans. There can be robust custom developed tools, but they do require constant updates and adjustments. An alternative is to apply proactively updated tools such as and Amazon’s code inspector.

Web Application Firewall

A Web Application Firewall or WAF as is often used when talking to DevOps or a hosting provider.

Web Application Firewalls (WAFs) prevent malicious traffic from entering sites and networks by filtering traffic against a set of security rules. Traffic that triggers any of the rules is blocked before it can damage your sites or network.

Adobe Commerce’s cloud WAF provides a WAF policy with a rule set designed to protect your Adobe Commerce web applications from a wide range of attacks. If you choose a self-hosting option, finding a WAF, and configuring the rules are your responsibility. Some hosting providers and WAF providers have a generic set of rules that are a good start, however expect some work to get things working for your project.

The WAF examines web and admin traffic to identify any suspicious activity. It evaluates the GET and the POST traffic (HTTP API calls) and applies the rule set to determine which traffic to block. The WAF can block a wide variety of attacks, including SQL injection attacks, cross-site scripting attacks, data exfiltration attacks, and HTTP protocol violations.

As a cloud-based service, the WAF requires no hardware or software to install or maintain. Fastly, an existing technology partner, provides the software and expertise. Their high performance, always-on WAF resides in each cache node across Fastly’s global delivery network.

For more information on the WAF on the Adobe Commerce on cloud provide by Fastly, read the Adobe Commerce Knowledge Base FAQ.

Self Hosting resources