910 133 741 / 657 392 366 info@hazmeweb.es
Photographer Alejandro Iglesia's website recovered after a WordPress hack: home page with the portfolio grid

Web security

Hacked WordPress site: how we recovered a photographer's website step by step

Alejandro Iglesia is a professional photographer specialising in advertising, portraits, lifestyle and beauty. His WordPress website is his portfolio: the place where agencies and brands look at his work. One day it simply stopped loading and showed the message "There has been a critical error on this website".

It looked like a broken plugin. It turned out to be a hack that had been active for two months. This is how we found out what had happened, how we got rid of it and how we brought the website back online without losing a single photo. If your WordPress site has been hacked, these steps will help you understand what to do (and what not to do).

Warning signs

The critical error was the visible symptom, but when we looked closer there were more signs that should set off alarms on any WordPress site:

  • Plugins that reactivated themselves. After deactivating every plugin, one of them was active again a few minutes later.
  • Administrators nobody knew. The site had 130 users with administrator rights. Only one was real.
  • Hidden files with random names inside wp-content: files starting with a dot and hexadecimal names, such as .e7d81efd.php.
  • An abnormal size. The plugins folder weighed more than 2 GB, when the usual size is a few hundred MB.

Step 1: don't touch anything and make a copy

The first instinct is to start deleting things. That's a mistake: you lose evidence and, if you don't know how the malware reinstalls itself, it will come back. We made a full copy of the files and the database and analysed it without running anything: reading the code, not executing it.

This matters. Running an infected website on your own computer (for example with Local or XAMPP) is risky: a PHP backdoor can read your files or use your connection. We analysed the database inside an isolated, network-less container.

Step 2: what we found

The infection was serious and combined three different malware families, all designed to sell spam links from the photographer's website:

  1. A link injection plugin (wp-link-helper) that inserted spam links and connected to an external server to receive instructions.
  2. A fake cache plugin (bold-cache-vox) with obfuscated code, hidden copies of itself and status files.
  3. A backdoor hidden inside a legitimate plugin folder, encoded several times over so it would not be detected.

On top of that there were the pieces that made it so hard to get rid of:

  • Mu-plugins (must-use plugins): WordPress always loads them and they cannot be deactivated from the dashboard. Their own code said what they were for: reinstalling and reactivating the main malware if anyone deleted it.
  • Configuration in the database: around 45 entries in wp_options and scheduled tasks (cron) to recover the malware even if the files were deleted.
  • 129 fake administrators, created over weeks.
  • A trap in the comments: a comment with malicious code (stored XSS). If an administrator opened the Comments screen, the code ran with their session and installed another malicious plugin on its own.
  • About 1,480 spam comments.

Step 3: how they got in

The server logs told the story. It wasn't a software flaw: they got in with a valid password. The account belonged to the administrator of another WordPress site hosted on the same shared hosting account.

  • In the days before the attack there were 16 successful logins from different IP addresses in several countries, with almost no failed attempts. That is not brute force: they already had the password. Everything points to that access being sold or shared between spam groups.
  • After several failed attempts, the attacker managed to upload and activate a malicious plugin. Eight seconds later, the malware was already copying itself to the other sites on the hosting account.
  • All the sites shared the same system user, so the infection spread to all of them, including an old 2012 WordPress install that had never been updated.

The lesson: an abandoned website on the same hosting puts all the others at risk, and a reused or leaked password is enough.

Step 4: why restoring a backup wasn't an option

The hosting kept only 14 days of backups. The intrusion was two months old, so every backup was infected. Restoring one would have brought back the same malware.

Step 5: clean the database without losing content

The photographer's value is in his content, and it was intact. We checked the database table by table:

  • Clean: all 3,862 content records (pages, posts, portfolio projects, galleries), with no injected code.
  • Deleted: the 129 fake administrators and their data, the 45 malware entries, its scheduled tasks, the comment with the XSS and the spam.

After the clean-up we scanned the whole database again for malware signatures: zero matches.

Step 6: rescue the photos one by one

A photographer's website can lose anything except its photos. We checked the more than 11,800 files (1.9 GB) in the media library to make sure they were real images and not PHP files disguised as images, a common trick. We left out the malicious code, the dangerous .htaccess and php.ini files and leftovers from the theme demo. Result: not a single photo was missing.

Step 7: rebuild on a clean WordPress

We did not reuse a single line of code from the infected server:

  • WordPress core downloaded from wordpress.org and verified against its official checksums.
  • Free plugins reinstalled from wordpress.org, also verified.
  • Theme and premium plugins downloaded from the author's official sources, in a newer version. The functions.php on the server had about 490 extra lines: the injected malware.
  • Same design as before: we compared the rebuilt site with an archived copy from before the attack.

Step 8: migrate to a new server and harden security

We moved the website to a new server with its own SSL certificate and updated the DNS, including removing old IPv6 records that still pointed to the infected hosting, so all traffic reached the clean server. Then we hardened WordPress:

  • PHP execution blocked in the uploads folder.
  • xmlrpc.php blocked, a common target for attacks.
  • Theme and plugin editor disabled in the dashboard.
  • User registration disabled.
  • Sensitive files (wp-config.php, readme.html) protected and a new administrator password.
  • Daily backups scheduled on the new server.

Checklist to protect your WordPress

What we learned from this case applies to almost any website:

  1. Unique, long passwords for each website and two-factor authentication for administrators.
  2. Delete old or test websites you no longer use, especially if they share hosting with your main site.
  3. Keep WordPress, the theme and the plugins up to date, and delete the ones you don't use.
  4. Review your users from time to time: an administrator you don't recognise is a red flag.
  5. Keep backups for more than a month, outside the server, and check that they can be restored.
  6. Monitor the website: many hacks are discovered weeks later, when the backups are already infected.

Has your WordPress been hacked?

If your website shows a critical error, redirects to other sites or has users you don't recognise, don't delete things blindly and don't restore backups without checking them first. At HazmeWeb we recover hacked websites: we analyse how they got in, clean the infection without losing your content and leave the site protected.

See the Alejandro Iglesia case study, check our web support and maintenance service or get in touch and we'll take a look.

Frequently asked questions

  • How do I know if my WordPress site has been hacked?
    The most common signs are a critical error for no apparent reason, administrators you don't recognise, plugins that reactivate themselves, oddly named files or files starting with a dot inside wp-content, redirects to other sites, warnings from Google Search Console or spam links you didn't add. If you see any of these, it is worth checking as soon as possible.
  • Is restoring a backup enough?
    Only if the backup predates the infection and you also close the door the attackers used. In this case the hosting only kept 14 days of backups and the intrusion was two months old, so every backup was infected. Restoring without changing passwords or fixing the entry point usually ends in reinfection within days.
  • Can a hacked site be cleaned without losing content?
    Yes, in most cases. Content (pages, posts, photos) lives in the database and the uploads folder, and it can be separated from the malicious code. What must not be reused is the code: WordPress core, the theme and the plugins are reinstalled from their official sources.
  • Is it enough to deactivate plugins or install a security plugin?
    No. A lot of current malware installs itself as mu-plugins, which WordPress always loads and which cannot be deactivated from the dashboard, and it stores its configuration in the database so it can reinstall itself. A security plugin helps prevent and detect attacks, but it does not replace a full clean-up once the site is compromised.
  • How long does it take to recover a hacked WordPress site?
    It depends on the size of the site and the type of infection. A simple clean-up can be done in a few hours; a case like this one, with several malware families, entry-point analysis, database clean-up and migration to a new server, takes one to two days of work.