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.
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.
In incidents like this, there is rarely one perfect indicator. Usually the full picture is built from several warning signs:
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.
In this type of incident, attention is usually drawn to the following file types:
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.phpphpinfo.php.It is also necessary to review files that can make access, upload, or data extraction easier for an attacker:
In a typical case, this may look like:
admin.../filemanager/upload.phpadmin.../backup.phpajax.php, drawer.php, and get-file-admin.php files;phpinfo.php.The following locations were also reviewed separately:
config/controllers/override/classes/modules/index.php files;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:
Below is a practical checklist of tests that is useful when an online store compromise is suspected.
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:
Each suspicious PHP file should be checked with php -l.
This does not directly prove a compromise, but it gives important information:
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_fileinclude and require statements.This is not a final verdict, but a filter for manual analysis.
Any PHP files in the site root deserve special attention, especially if they are:
phpinfo.php;Even if such a file is harmless, it increases the attack surface.
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.
You should search not only for .php files, but also for any files containing <?php:
.txt.ico.jpg.phtml.pharThis helps detect disguised malicious code.
A large number of index.php files in image directories may be normal, but it is important to verify:
A very important test is to compare modified files with the official originals of:
This is how hidden link injections, redirect replacements, webhook logic changes, or inserted external URLs are most often discovered.
It is not enough to just read the code; the business logic must also be tested:
If money goes through but no order appears, that is one of the strongest indicators of compromise.
You should review:
access.logerror.logphp-fpm logsYou should look for:
It is important to confirm that:
root-owned files inside web directories;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.
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.
Several important conclusions can be drawn from this investigation.
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.
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.