Aloha Pixel

Book a call
English,
Infrastructure and troubleshooting

Hacked WordPress site: clean up, back online, no relapse

Strange redirects, spam, a security warning: how to confirm the hack, clean the site thoroughly, bring it back online and close the door behind you.

By Justin Deboves8 min read

Coral reef under turquoise water, dark coral heads and light falling from the surface

You rarely discover a hacked WordPress site by looking at its code. You hear about it from a client reporting a redirect to a dubious online store, from a red warning in the browser, from your host writing to announce a suspension for sending spam, or from a sudden collapse in traffic. This article follows the real order of an intervention, from the first findings to hardening. And it begins with the most expensive mistake: deleting the suspicious files before you have understood how the attacker got in.

Confirm that it really is a hack

An outage and an intrusion are not handled the same way, and confusing them wastes hours. Five signs do not lie:

  • Unknown pages in the index. A site:yourdomain.com search brings up titles in a foreign language or counterfeit-goods pages you never published.
  • Conditional redirects. The site looks normal when you visit it directly, but sends people elsewhere when they arrive from a search engine or from a phone. That is the signature of an injection: the code tests where the visitor comes from before firing, which is why the owner is the last to know.
  • Administrator accounts nobody recognizes, often created in the small hours.
  • Recently modified files when nothing has been published. Over SSH, find . -name "*.php" -mtime -7 lists the PHP files touched in the last seven days.
  • Mass email sending from the server, usually flagged by the host before you notice it yourself.

Two places confirm it in two minutes: the “Security issues” section of Search Console, which names the type of infection detected, and the server access logs, which give the IP address and time of the abnormal requests. If the site is simply unreachable with none of these signs, you have not been hacked: follow the protocol for the first 60 minutes of a site outage instead.

The first six decisions, in order

The order matters as much as the actions. Reversing it is the main cause of reinfection.

  1. Put the site into maintenance mode rather than leave it serving malicious content to your clients and to the search engines. Every extra hour online makes the blacklisting worse.
  2. Tell your host. They often already have material to hand: logs, alerts from their own scanner, the date of the first anomaly. That is diagnostic time handed to you for free.
  3. Copy the infected state before any cleaning, files and database. It is your only usable evidence, to understand the entry point, for a possible police report, and to recover content deleted by mistake during the clean-up.
  4. Change every password from a clean machine: WordPress admin, SFTP, database, hosting account, domain registrar, associated mailbox. If the owner’s own computer is compromised, changing the passwords from it amounts to handing them over.
  5. Regenerate the security keys and salts in wp-config.php using WordPress’s official generator. Every active session is invalidated at a stroke, including the attacker’s.
  6. Restore a backup only after you have understood the vulnerability. This is the point almost nobody writes down: restoring an earlier copy puts back the vulnerable version that let the attacker in. The site is clean on Monday and reinfected by Thursday.

Clean thoroughly

One guiding idea: cleaning is done by replacement, never by patching. Removing one malicious line of code from a file leaves the other fifteen where they are.

Replace rather than repair

Reinstall the WordPress core from the official archive, then the plugins and the theme from their original sources, in the same versions or newer. Keep only two things, both inspected: the wp-content/uploads folder and the database. With WP-CLI, the preliminary check takes a few seconds:

wp core verify-checksums
wp plugin verify-checksums --all
wp core download --force --version=$(wp core version) --locale=en_US

The first two commands compare your files against the checksums published by WordPress.org and list everything that has been modified or added. A premium plugin from outside the official repository is not covered: it is reinstalled from the vendor’s account.

Hunt down the backdoors

A backdoor is a small file that lets the attacker come back without going through the original vulnerability. The usual hiding places: a PHP file dropped into wp-content/uploads, where there is never any reason to find one; the wp-content/mu-plugins folder, loaded automatically and looked at by nobody; a modified child theme; a plugin abandoned two years ago; a scheduled task that reinstalls the code every night; a dormant administrator account. The search logic is always the same: compare against the official archives, sort by modification date, and treat as suspect anything that cannot be explained.

Clean the database

Injected code does not live only in files. Look for iframes, script tags and links added to posts, to the options table and to widgets. Check in particular the siteurl and home options, often hijacked to redirect the entire site. Work on a copy, keep a record of every replacement, and flush every cache afterwards: a page cache keeps serving the infected version long after the clean-up.

Check what does not belong to the site

The final inspection round, the one that gets forgotten: unknown scheduled tasks (wp cron event list), recently created SFTP accounts, SSH keys added to the server, redirect rules slipped into .htaccess or into the server configuration, and application tokens still valid. A serious attacker always leaves more than one door.

Get off the blacklists and reassure the search engines

The most painful consequence for a business is not technical: it is the red “Deceptive site ahead” screen your clients see, and the loss of trust that follows. Once the clean-up is finished and verified, open the “Security issues” section of Search Console, describe precisely what was done, and request a review. Google says these reviews take from several days to several weeks, and advises against submitting a new request before a decision: asking again too early lengthens the wait (Search Console documentation).

A request sent before the clean-up is complete is refused and costs you a week. So check before sending: no more unwanted pages in the index, no more redirects from a phone, no more flagged files. If the server was used to send spam, also check the sending reputation of your domain and of the IP address, and verify that the SPF, DKIM and DMARC records are correct: a business mailbox whose messages no longer arrive is the second wave of the disaster.

The blind spot: your obligations when data has leaked

An online store holds addresses, orders and sometimes customer accounts. A simple contact form already holds personal data. An intrusion that gave access to that information is a personal data breach within the meaning of the GDPR, and it triggers concrete obligations.

The CNIL, the French data protection authority, must be notified as soon as possible, within 72 hours where feasible, whenever the breach presents a risk to the people concerned; any overrun has to be justified. Where the risk is high, the people concerned must be informed too. In every case, the incident must be documented internally: nature of the breach, categories and approximate number of people affected, likely consequences, measures taken (notifying a breach to the CNIL, in French). That is one more reason to keep an intervention log from the first hour.

In parallel, a police report is possible, and the public platform Cybermalveillance.gouv.fr offers quick-reference sheets and a directory of service providers, also in French. We do not give legal advice: we simply make a point of raising this side of things, because it almost never gets discussed, even though it is the one that leaves the business owner most exposed.

Close the door for good

Cleaning settles the present. What follows settles the future, and it is almost always the same gaps:

  • Delete, do not deactivate, unused plugins and themes. A deactivated plugin stays on the server and stays exploitable.
  • Two-factor authentication on every administrator account, and a limit on login attempts to snuff out brute-force attacks.
  • Correct file permissions: 644 for files, 755 for folders, and a tighter setting still for wp-config.php. A folder set to 777 is an open invitation.
  • File editing disabled from the dashboard, with define( 'DISALLOW_FILE_EDIT', true );: a stolen administrator account no longer gives direct access to the theme’s code.
  • Upstream filtering by a web application firewall, so that malicious requests never reach PHP. An edge service lets you filter requests before they reach the site, whatever the hosting.
  • Updates applied fast. Between the publication of a patch and its automated exploitation, there is often less than a week.

The detail of these measures is set out in the 8 essential WordPress security measures and in our step-by-step guide to securing a WordPress site.

Our position: how long it takes, and when to hand it over

We quote durations, never a flat fee sight unseen: a brochure site with proper backups is cleaned in a few hours; an online store without a sound backup takes one to two days, most of that time going on hunting for backdoors and revalidating orders. Three situations justify handing over without hesitation: no backup predating the infection, a hack that comes back after a first clean-up, or a store that is trading, where every hour of closure is counted in lost orders.

Our position is simple: we refuse to clean a site without fixing the cause. A clean-up on its own is a service that can be sold again every two months, and we want no part of that model. An intervention and clean-up by ticket always runs in the same order: written findings, a copy of the infected state, cleaning by replacement, hardening, a review request to the search engines, then a report naming the vulnerability identified and the measures applied. Without that last point, the job is not finished.

After the clean-up comes prevention: that is the job of monthly WordPress maintenance.

Conclusion

A hacked site is not an unloved site, it is a poorly maintained one. The attacks are automatic, they target nobody in particular, and they always find the same things: a forgotten plugin, a reused password, an out-of-date version of PHP. Cleaning settles the present; only maintenance settles the future. If you have any doubt about the state of your site today, start with the “Security issues” section of Search Console: it is free and it takes two minutes.

Have my site cleaned Talk about my site’s security

Questions fréquentes

Is installing a security plugin enough to clean the site?
No. A scanner spots some of the infected files, but it misses the custom-written backdoors and the code injected into the database. It is useful for detecting, not for cleaning.
Do you have to start again from scratch?
Rarely. Rebuilding by replacement, with the core and the plugins reinstalled from their official sources, is enough in the great majority of cases. Starting the site over costs more and does not fix the original vulnerability.
Is my SEO lost?
Not if the infection is dealt with quickly. The lasting losses come not from the hack itself but from the weeks spent on a blacklist, with a red warning shown to every visitor.
Why was my site targeted?
Almost never personally. The attacks are automated: bots crawl the web looking for a known vulnerable plugin version. They target a flaw, not a business.
All articles