CASO DI STUDIO · E-COMMERCE

WooCommerce Store Reinfected Every Night: Skimmer, Cron, and an In-Memory Process

  • CLIENTOnline store (anonymized data)
  • PLATFORMWooCommerce

A skimmer on the WooCommerce checkout came back every night after cleanup: a hidden cron job and a PHP process resident in memory. Site clean within 6 hours.

An online store page next to a shopping cart with a red bug, surrounded by a circular arrow and a moon, symbolizing the nightly reinfection

Background

A mid-sized WooCommerce online store with a few thousand products and orders every day. The site was hosted on a virtual server managed by a web agency, which also handled the updates. For confidentiality, the client’s name, product sector, and details that could identify them have been omitted or changed.

Symptoms

Some customers had reported suspicious charges on their payment cards after buying on the site. The agency had found a foreign script on the checkout page, removed it, and updated all the plugins. The next morning the script was back. The same sequence had repeated for three nights: cleanup by day, reinfection overnight, always between two and four a.m.

When the client contacted us, the priority was clear: stop the theft of payment data immediately and understand why the cleanup would not hold. They chose the service with a response within 6 hours.

What we found at the application level

The script on the checkout page was a skimmer: it intercepted the data entered in the card form and sent it to a domain imitating an analytics service. It was added to the site by a file in the mu-plugins folder, named like a cache plugin, which WordPress loads automatically and which does not appear among the active plugins but only in the separate “Must-Use” tab, where nobody had looked. The code was obfuscated with a chain of base64_decode and gzinflate and activated only on checkout pages.

We also found a recently created administrator user, with an email address similar to the owner’s, and a copy of the backdoor inside the uploads folder, with an image file extension, included by a line added at the bottom of the child theme’s functions.php.

What we found at the system level

This was the explanation for the nightly reinfection. In the crontab of the user the site ran as, there was an entry executed every night at 2:30, hidden below a series of blank lines, which downloaded an updated version of the malware from an external address and reinstalled it wherever it had been removed. Alongside it was an @reboot entry, which would have reactivated everything at the first server restart.

It was not the only mechanism. Among the running processes was one named [kworker/1:2], which at first glance looked like a kernel thread. But it ran as the site’s user, its parent was a PHP process, and its executable, seen from /proc, was the PHP interpreter with a startup script that had since been deleted from disk. It was a PHP process resident in memory, started days earlier, which every few minutes checked that the file in mu-plugins existed and recreated it if it was missing. This is why, even before the nightly cron run, some cleanups were undone within a few minutes.

Analysis of the access logs traced the initial entry to a form-management plugin that had not been updated in over a year, with a known vulnerability that allowed file uploads.

How we removed it

Before touching anything we preserved the evidence: a copy of the suspicious files, the crontab, the process list, and the running script, recovered from memory through /proc. Then we proceeded in this order:

  1. terminated the resident process and disabled the two crontab entries, to stop the persistence;
  2. removed the skimmer, the file in mu-plugins, the copy in uploads, and the line added to the theme;
  3. compared core, plugins, and theme with the original versions and replaced every modified file;
  4. deleted the unauthorized administrator and checked the other accounts with elevated privileges;
  5. checked the database, triggers, and options, which in this case contained no other malicious code;
  6. changed all credentials: administrator passwords, WordPress keys and salts, database password, SFTP and SSH access, and the API keys of the payment services.

We also advised the client to notify their payment service provider, as required in the event of a possible compromise of card data.

Hardening

The vulnerable plugin was replaced with a maintained alternative. We blocked PHP execution in the uploads folder, restricted the site user’s crontab, replaced visit-triggered WP-Cron with a controlled system cron, and enabled monitoring of changes to the checkout files, the theme, and the mu-plugins folders.

The result

The site was declared clean within the 6 hours guaranteed by the service. Over the following thirty days the monitoring detected no unauthorized changes, and the script on the checkout page never reappeared. The client received a report with a reconstruction of the attack, a list of the work performed, and the measures to prevent it from happening again.

THE NEXT STEP

Is your site
infected?

Every hour counts: the malware keeps hitting visitors and customers, and Google, your host and the blacklists won’t wait. Choose a plan, pay online and share your access: the cleanup starts right away, at a fixed price and with guaranteed times.

Request a cleanup

Takes you to the plans: cleanup within 6, 12 or 24 hours of receiving access.

MANAGED SERVER S.R.L.info@malwarecleanup.com +39 02 5656 9681

Monday – Friday · 9:30am – 7:30pm Italian time (CET)

Prefer an online form?
Contact us at managedserver.it ↗