The plugin that changed without changing

· · Security Infrastructure

If your business website runs on WordPress, somebody has probably told you the rule: keep your plugins updated. It is good advice. It is also, this month, not enough.

Between March and early August, seven WordPress plugins were used to create hidden administrator accounts on live sites. No plugin file was modified. No update was pushed. Anyone who checked their site during that window would have seen correct version numbers, an unremarkable plugin list, and nothing to update. The sites were compromised anyway.

The plugins belong to BdThemes, a vendor of add-ons for Elementor, the page builder behind a large share of UK small business websites. The biggest of the seven, Element Pack, has more than 100,000 active installations.

What actually happened

The plugins include a component that fetches promotional banners from the vendor's servers and displays them in your WordPress admin dashboard. It pulls a small data file each time an administrator loads a page.

Two things went wrong, and it took both.

First, BdThemes introduced a coding error on 1 March. The script dropped one field from that data file straight into the page without escaping it, meaning whatever arrived in that field would be treated as instructions rather than text. Wordfence, the WordPress security firm that published the analysis on 8 August, traced it through the code history and reads it as an oversight: a neighbouring field in the same few lines is handled correctly.

Second, attackers got write access to the storage bucket holding that data file. They did not need to touch the plugin. They just changed what the plugin was told.

From there it ran on its own. The injected code fired silently in the browser of every logged-in administrator, on every dashboard page load. It used the administrator's own logged-in session to create a second administrator account through WordPress's own interface, then installed a fake plugin carrying a web shell, a small file that lets an attacker run commands on your server.

Then it hid. One module grants entry through a special web address with no password required. The other hooks into WordPress's database queries so the rogue accounts do not appear in your user list, and adjusts the displayed user count to match. If you went looking through the admin screens, you would find nothing.

Why the usual advice missed it

Almost everything a small business is told about website security assumes the danger arrives as a file. Install updates, because updates replace bad files with good ones. Check your versions. Scan for changes.

None of that engages with what happened here. The files on disk were the genuine, unmodified, correctly-versioned files from the official WordPress directory, right up until the moment the attack installed its own. The malicious instruction arrived over the network, seconds before it ran, from a server you have no visibility of and never agreed to trust directly.

That is the shape worth taking away, because it is not specific to WordPress or to these plugins. Software that phones home for content is normal and mostly harmless. But every one of those connections is a supplier who can change what your system does tonight, without shipping you anything. It is the same pattern as the third-party scripts running on your website, moved from your visitors' browsers to your own admin dashboard, which is a considerably worse place for it.

The vulnerability record rates the underlying flaw 5.4 out of 10, medium severity. Taken alone, as a coding error requiring an attacker to already control the vendor's data feed, that is fair. It also demonstrates why a severity score is a poor guide to whether something matters to you. The score describes the flaw. It does not describe somebody actively using it to make themselves an administrator of your website.

What to check

The plugins are Element Pack, Prime Slider, Pixel Gallery, Ultimate Post Kit, Ultimate Store Kit, Live Copy Paste, and Smart Admin Assistant. WordPress closed all seven for review on 7 and 8 August, so they cannot currently be downloaded. Both attacker endpoints were clean by 8 August.

If you ran any of them, updating is not the fix, and neither is removing the plugin. Anything the attack installed stays behind. Ask whoever looks after your site to check four things:

  • The full user list, from the database rather than the admin screen. The stealth module hides rogue accounts from the normal view, so the admin user list is the one place that will lie to you. One payload generated predictable usernames beginning bd_, which means a responder can work out exactly what to search for.
  • The must-use plugins directory (wp-content/mu-plugins). Plugins here load automatically and do not show up in the ordinary plugin list. This is where the persistence was hidden.
  • The plugin directory for anything nobody installed, particularly a file named emer-run.php.
  • The options table for entries that do not belong.

If anything turns up, changing passwords is not enough on its own. Assume the site needs restoring from a backup that predates the compromise, and that any credential stored on that site should be treated as known to somebody else.

For everyone else, the useful question is not about these seven plugins. It is how many plugins your site runs, who is behind each of them, and how you would find out if one of those vendors had a bad week. Most business sites carry between 15 and 40. Very few owners can name the people behind more than a handful.

How Steelwise can help

Working out what your website actually runs, who can change it, and what a compromise would reach is the kind of security review we do for small businesses without an in-house technical team. Get in touch.

Further reading

← All filings