Sometimes an online store hack does not look like a classic website failure. The store may still open, the catalog may still work, and some orders may still be placed, while the real problem only appears in one place — for example, in the cart, during checkout, or in a mismatch between an actual payment and the order history.
This kind of scenario is especially dangerous. It does not always immediately show that the issue is not a module bug or a random integration error, but a sequential compromise with several stages: initial access, persistence, hidden payment flow manipulation, and attempted monetization.
Below is a practical story of how such an incident can be uncovered, which files usually attract attention, and which tests help reveal an infection and confirm that the active phase of the compromise has truly been stopped.
How the Incident Developed
Based on the internal timeline of file changes, it became clear that the attack developed in stages rather than all at once.
At first, the site catalog was affected. This was an early stage of the compromise, when changes appeared in the file structure that did not match the store’s normal activity. About two weeks later, the attackers took the next step: they created or reinforced additional access points — backdoors and helper files that allowed them to return to the system and continue interfering even after partial cleanup.
Then came a period of relative silence. At first glance, it could have seemed that everything was limited to local file changes, but in reality this was only the preparation stage.
About two months later, the first obvious business incident occurred: the one-page checkout page was compromised. A link to a third-party card payment processor appeared in the cart. This link had nothing to do with the store’s legitimate payment flow and redirected the customer to an external payment route. At that stage, the replacement was detected and removed, which temporarily stopped the first fraud scenario.
However, the investigation showed that this was not the end, but only one episode. About three weeks after the malicious link was removed, the next stage of the attack followed — this time at the payment module level. As a result, Google Pay and Apple Pay payments began to go somewhere other than the legitimate flow. At the same time, purchases were not recorded in the store history: normal orders did not appear in the system, the expected payment records were not created, and for the administrator it could look like orders were simply disappearing.
Which Signs Revealed the Problem
In incidents like this, there is rarely one perfect indicator. Usually the full picture is built from several warning signs:
- an unexpected link or payment route appears on the checkout page;
- a customer completes payment, but the order does not appear in the store history;
- files change even though no administrator edited them;
- service entry points remain in the system and can be used for repeated access;
- the timing of changes is stretched across weeks, suggesting repeated attacker returns;
- some modified files look almost legitimate but were changed at suspicious times;
- there is a gap between the payment logic on the frontend and what is actually recorded in the order system.
Which Files Were Affected or Required Separate Review
During an investigation, it is important to separate two groups honestly: files that were truly modified at suspicious times and became part of the main review, and standard system files that do not by themselves prove a compromise but must still be checked as potential entry points.
1. Suspiciously Modified or Affected Files
In this type of incident, attention is usually drawn to the following file types:
- the application configuration file with connection parameters and keys;
- the payment module controller;
- the cart AJAX controller;
- controllers of review, subscription, and wishlist modules;
- individual files in the site root;
- service PHP files that appeared or changed at unusual times.
A typical list of files that often falls into this group includes:
app/config/parameters.phpmodules/.../controllers/front/payment.phpmodules/.../controllers/front/ajax.phpmodules/.../controllers/front/verification.phpmodules/.../controllers/front/lists.phpmodules/.../controllers/front/PostComment.php- root-level files such as
phpinfo.php.
2. Potentially Dangerous Standard Entry Points That Must Be Checked
It is also necessary to review files that can make access, upload, or data extraction easier for an attacker:
- a file manager in the admin area;
- a service file upload handler;
- a backup download handler;
- old administrative scripts;
- upload routes;
- any outdated helper tools for working with files.
In a typical case, this may look like:
admin.../filemanager/upload.phpadmin.../backup.php- various old
ajax.php,drawer.php, andget-file-admin.phpfiles; - service upload/download handlers;
- the root-level
phpinfo.php.
3. Directories Where Persistence Traces Were Searched
The following locations were also reviewed separately:
config/controllers/override/classes/modules/- the admin directory;
- the site root;
- image directories for unusual
index.phpfiles; - places where hidden uploaders or mini backdoors could have been placed.
Why You Should Not Treat Every eval, base64_decode, or move_uploaded_file as Malicious
One of the most common mistakes during an investigation is to mark every file as malicious just because it contains scary-looking functions. That is incorrect.
In many CMS platforms and modules, the following can be completely legitimate:
move_uploaded_file()— in image and file upload forms;base64_decode()— in APIs, PDF libraries, cryptography, logos, and webhooks;php://input— in API, webhook, and AJAX handlers;gzuncompress()— in PDF and graphics libraries;eval()— in older CMS core code, autoloaders, and module logic.
So the danger is not the function itself, but its context:
- the file was modified recently without a clear reason;
- it is located in an unusual place;
- it does not match the official version;
- it introduces an external URL;
- it alters the payment flow;
- it creates a hidden access channel;
- it does not fit the business logic of the website.
A Set of Tests That Helps Detect an Infection
Below is a practical checklist of tests that is useful when an online store compromise is suspected.
1. Search for Recently Modified PHP Files
The first test is to find all PHP files changed during the suspicious period, excluding cache, vendor, uploads, and media. This quickly narrows the review to the files that were actually touched.
What to look at:
- modification date;
- file owner;
- unusual change windows;
- mass updates to groups of files at the same time.
2. Syntax Check of Modified Files
Each suspicious PHP file should be checked with php -l.
This does not directly prove a compromise, but it gives important information:
- whether the file is valid or broken;
- whether this is random damage or carefully inserted code;
- whether the attacker intended to leave an executable file behind.
3. Search the Source Code for Dangerous Functions
The next test is a search for patterns such as:
eval(assert(base64_decode(gzinflate(gzuncompress(str_rot13shell_execsystem(passthruproc_openpopenphp://inputfile_put_contentsmove_uploaded_file- suspicious
includeandrequirestatements.
This is not a final verdict, but a filter for manual analysis.
4. Review Files in the Site Root
Any PHP files in the site root deserve special attention, especially if they are:
phpinfo.php;- test uploaders;
- old debugging scripts;
- temporary migration files;
- one-off service pages.
Even if such a file is harmless, it increases the attack surface.
5. Check Admin File Managers and Backup Scripts
If the admin area contains a file manager, upload handler, backup download function, or outdated maintenance scripts, they must be reviewed separately. These points are often convenient tools for both initial access and repeated persistence.
6. Search for PHP Code in Non-PHP Files
You should search not only for .php files, but also for any files containing <?php:
.txt.ico.jpg.phtml.phar- temporary files;
- files without an extension.
This helps detect disguised malicious code.
7. Check Image Directories and Nested index.php Files
A large number of index.php files in image directories may be normal, but it is important to verify:
- whether they match the expected content;
- whether their size differs from the standard version;
- whether they contain extra code;
- whether they appeared in suspicious waves on particular dates.
8. Compare with a Clean CMS and Module Version
A very important test is to compare modified files with the official originals of:
- the CMS core;
- the payment module;
- the cart;
- the checkout module;
- third-party integrations.
This is how hidden link injections, redirect replacements, webhook logic changes, or inserted external URLs are most often discovered.
9. Manually Test the Payment Flow
It is not enough to just read the code; the business logic must also be tested:
- what happens after the payment button is clicked;
- where the link leads;
- which URLs are called;
- whether the order appears in the system;
- whether the cart status changes;
- whether a payment record is created;
- what happens with Google Pay, Apple Pay, and card payments.
If money goes through but no order appears, that is one of the strongest indicators of compromise.
10. Check Web Server and PHP Logs
You should review:
access.logerror.logphp-fpm logs- payment module logs;
- webhook logs.
You should look for:
- unexpected POST requests;
- requests to non-standard controllers;
- calls to upload and AJAX handlers;
- abnormal redirects to external URLs;
- requests to hidden service routes.
11. Check File Permissions and Ownership
It is important to confirm that:
- files belong to the expected user;
- there are no unexpected
root-owned files inside web directories; - permissions are not overly broad;
- upload directories are not executable unless absolutely necessary.
12. Check for Reappearing Changes
One of the most important checks after cleanup is observation. If new file changes appear again after a few days or weeks, it usually means the original malicious code was not fully removed, a backdoor remained, or the compromise continues through the panel, a module, or stolen credentials.
What Matters Most in Investigations Like This
The biggest mistake is to stop at the first symptom.
If you found and removed a malicious link in the cart, that still does not mean the problem is solved. In the case described here, that is exactly what happened: first, the external card processor link was found and removed, but three weeks later it became clear that the attacker had kept access and had already interfered with the payment module more deeply. As a result, Google Pay and Apple Pay began to operate in the attacker’s interest, while purchases were no longer recorded in the store history.
Practical Conclusions
Several important conclusions can be drawn from this investigation.
- An online store compromise often develops in waves. First comes preparation and persistence, then a pause, and later a business-focused attack on payments.
- If checkout is affected, do not inspect only the cart templates. Payment controllers, redirect logic, webhooks, and order history must also be analyzed.
- You cannot limit the investigation to finding one malicious file. You need to look at the whole chain of events, the timing of changes, and repeated anomalies.
- Standard service files such as phpinfo.php, file managers, backup scripts, and upload handlers sharply increase risk. They should either be removed or tightly restricted.
- The best way to confirm that the active phase of the attack has stopped is to complete the full verification cycle. Files, logs, permissions, payment flow, comparison with originals, and post-cleanup observation all need to be treated as one process.
Conclusion
This incident showed a typical but very dangerous pattern: first, a compromise of the file structure; then persistence through backdoors; then manipulation of checkout behavior; and later, direct interference with the payment module itself.
From the outside, this can look like a strange cart bug or an issue with missing orders. In reality, it may be a long-running attack in which the intruder first gains access, then preserves it, and only later starts extracting money by hijacking the payment flow.
That is why any situation in which an extra link appears in the cart, a customer pays but no order appears in the system, the payment module code changes without authorized maintenance, and incidents are separated by weeks should be treated as a full compromise until proven otherwise.
🛡️ Need a Post-Breach Store Review?
SOLLER.LV can help audit your store, review checkout and payment modules, detect persistence traces, compare files with official originals, and assess whether the active phase of the compromise has truly been stopped.
