← Back to the blog

ClickFix on WordPress: the fake CAPTCHA that infects your visitors (and how to actually clean it)

Your WordPress shows visitors a fake CAPTCHA («Verify you are human») and you never see it. What ClickFix is, how to detect it and how to clean it properly.

Quick summary: ClickFix is malware that installs itself on hacked WordPress sites and shows visitors a fake CAPTCHA («Verify you are human», «I’m not a robot», sometimes with the Cloudflare logo). The «CAPTCHA» tells them to press Win + R, paste and run a command that the site itself already copied to their clipboard. That command installs an infostealer which steals passwords, cookies and sessions. The site owner never sees it, because the malware deliberately hides from administrators. Cleaning it up means far more than deleting a file: you have to find every foothold, close the door they came in through and rotate every credential, or it comes back within days.

This article explains how it works, how to tell whether your site has it, what to do step by step, and which mistakes to avoid. It is written from a real case I handled in 2026: 13 infected domains in a single hosting account, 46 days before anyone noticed, and three waves of reinfection in 60 days.

Is your site showing a strange CAPTCHA right now? Don’t keep reading: message me on WhatsApp and we’ll look at it today. Come back and read the rest afterwards.

What ClickFix is

ClickFix is a social engineering technique that convinces victims to run a malicious command on their own computer, disguising that step as a «security check», an «error fix» or a CAPTCHA. That is where the name comes from: click to «fix» something that was never broken.

In its most widespread variant, the vehicle is legitimate, hacked WordPress sites. The attacker does not build fake pages: they infect real sites with real reputation, indexed in Google, and use that trusted traffic to attack the visitors. A local news outlet, a holiday rental, a sports association, a shop. Sites nobody would suspect.

What the visitor sees is an overlay on top of the page, neatly designed to imitate Cloudflare or Google reCAPTCHA:

  1. «Verify you are human», with a checkbox to tick.
  2. Ticking it reveals «verification steps»: press Win + R, then Ctrl + V, then Enter.
  3. Meanwhile, the site has already copied an obfuscated PowerShell or mshta command to the clipboard.

If the person follows the steps, they run the command on their own machine. No antivirus blocked it, because there was no download: the victim ran it voluntarily.

How it works: the full attack chain

Understanding the chain is useful for two things: knowing what to look for on the server, and explaining to a client why «I deleted the file, we’re fine» is not enough.

1. Breaking into the site

The attacker gets the ability to write files into WordPress. The vectors I saw in the real case, in order of appearance:

  • Hosting account level access (SSH, FTP or control panel): the same three files appeared across 13 domains in the same account within a two-minute window. A plugin vulnerability would have affected a single site.
  • Stolen WordPress administrator credentials: in the second and third waves, the attacker logged in with the legitimate admin account, from datacenter IPs in Malaysia, New York, Toronto and Berlin, with a Safari-on-Mac user agent the owner had never used. It was all recorded in WordPress’s own session table.
  • The panel’s file editor (Appearance → Theme File Editor): with an admin session, they wrote to the theme’s functions.php 34 seconds after logging in. No plugins, no exploits: with the tool WordPress ships by default.

2. Persistence: where it hides

This is where most cleanups fail. A single operator used six different hiding places in a matter of weeks:

Hiding placeWhat it looked likeWhy it is hard to spot
MU-plugin (wp-content/mu-plugins/)A .php file with a neutral nameMust-use plugins always run, cannot be deactivated from the dashboard and do not appear in the normal plugin list
A normal plugin with a plausible namesite-helper-<hash>, described as «Performance Lab Helper»One more plugin in a list of twenty does not stand out
The theme’s functions.phpOne line at the end of the file, with add_action('wp_footer', …)No integrity checker covers themes; the file is legitimate, the line is not
Legitimate plugin filesCode prepended to the start of a file belonging to Akismet, Elementor Pro or JetEngineThe plugin keeps working; the file carries the date of the real update
Database rowsThe injected <script> inside the content of 94 posts and revisionsScanning the homepage misses it entirely; it only shows up when you open a post
A service worker in the visitor’s browsernochain-sw.js in the site rootIt survives the server cleanup: it stays installed in every victim’s browser

And one detail that turns the cleanup into a trap: the malicious plugin reinstalls itself. It leaves a ZIP copy of itself disguised as an image at wp-content/uploads/2026/08/cache-63fcf1b7.jpg, and on every WordPress load it checks whether it has been deleted so it can install itself again. Delete the plugin but not the «image», and it is back shortly after.

3. Evasion: why the owner never sees it

This is what baffles site administrators the most: «I log in every day and it looks fine». The injector deliberately excludes administrators. The code checked:

  • whether the wordpress_logged_in_* cookie exists (logged-in user),
  • whether the URL is /wp-admin or /wp-login.php,
  • whether its own cookie (nc_skip=1) exists — one that the malware itself sets for every user with administrator privileges,
  • and whether the visitor already saw the CAPTCHA that day (so repetition doesn’t draw attention).

A later version went further: to the IP of an administrator who had visited wp-admin it served a harmless version of the script, and the malicious one to everybody else.

The result: the owner browses while logged in and sees a normal site; a new visitor arriving from Google gets attacked. So when somebody tells you «your site is showing me a weird CAPTCHA» and you can’t see it, the visitor is the one who is right.

4. EtherHiding: instructions stored on a blockchain

Current versions of ClickFix don’t carry the final payload on the server. The injected script loads a library (ethers.js) and reads the command-and-control address and the content to display from a smart contract on a public blockchain (Base, Polygon, BNB Smart Chain). The technique is called EtherHiding.

The practical consequences:

  • The attacker changes the payload without touching your server again: today a fake CAPTCHA, tomorrow a «Chrome error» that needs «fixing», the day after a crypto wallet drainer.
  • There is no malicious domain to block: the data lives on a blockchain nobody can take down, and the script carries eight fallback public RPC endpoints.
  • An antivirus that blocks today’s control domain is useless tomorrow.

In the real case, one operator used a contract on Base in June and another on Polygon in August, and kept an inventory of victims: each infected site had its own identifier in the call to the control server.

5. What happens to the visitor

The command the victim runs downloads and installs an infostealer (Lumma, Amatera and similar families). Within seconds it steals:

  • passwords saved in the browser,
  • cookies and active sessions (with those, the attacker gets into accounts without needing the password or 2FA),
  • autofill data and card details,
  • cryptocurrency wallets.

And here the circle closes: if the site owner or someone on their team fell for the CAPTCHA, the attacker now has the WordPress credentials. In the case I handled, the strongest hypothesis for the second wave was exactly that: admin credentials harvested during the first one.

How to tell whether your WordPress site is infected with ClickFix

Checks anyone can run, no technical knowledge needed, in five minutes:

  1. Open your site in an incognito window, logged out, ideally from a phone on mobile data (a different IP). Search for it on Google and click through from the result: the malware often only triggers when the Referer is a search engine.
  2. Check an individual post, not just the homepage. Some sites had a clean homepage and 14 infected posts.
  3. Look at Google Search Console: the Security & Manual Actions section reports when Google detects «malicious software» or «deceptive pages».
  4. Read your hosting mailbox. Providers scan and send an abuse notice giving you 24 hours to clean up before suspending the whole account. That email lands in the registration address, which often nobody reads.
  5. Take any visitor report seriously. In two of the three waves, the problem was spotted by a client or a reader, not by a tool.

Technical checks, for anyone with server access:

  • List wp-content/mu-plugins/ and open every file you don’t recognise.
  • List plugins by install date and look for generic names (site-helper, wp-helper, performance-*, cache-*) with a hexadecimal suffix.
  • Read the last line of the active theme’s functions.php.
  • Search the whole installation for the patterns atob(, new Function(new TextDecoder, eth_call, eval(base64_decode and 0x followed by 40 hexadecimal characters (a contract address).
  • Look for .jpg, .png, .css or .js files that start with <?php or with PK (a disguised ZIP).
  • Search for the same <script> pattern inside wp_posts and wp_options, not just in files.
  • Review each administrator’s active sessions (session_tokens in wp_usermeta): it records the IP, the browser and the time of every login. It is the best intrusion evidence WordPress gives you.

The real case: 13 domains, 46 days, three waves

I’m telling this story because the decisions that had to be made are the same ones anyone going through this will face.

Wave 1 (June–July). The three malware files appeared across 13 of the 14 domains in a shared hosting account, all within the same two-minute window. It stayed active for 46 days before a CAPTCHA in an incognito window gave it away. An earlier audit had already listed the suspicious MU-plugin and classified it as «informational». The lesson: an unidentified executable file in production is never «informational».

That same day, hours after the cleanup, the hosting abuse notice arrived: 24 hours to remove the malware or they would suspend the entire plan — all 14 domains.

Wave 2 (August). Four sites in 76 seconds, across two separate infrastructures whose only common factor was the person administering them. It was no longer an MU-plugin: it was a normal plugin with a plausible name, plus injections inside legitimate Akismet, Elementor Pro and JetEngine files, plus an installer hidden as a .jpg. That ruled out hosting access and pointed at WordPress administrator credentials in the attacker’s hands.

Wave 3 (August, two days after rotating passwords). They got in with an administrator session that was still valid after the password change (WordPress does not close open sessions when you change the password) and used the theme editor. This time the injected content was in 94 posts on one site and 14 on another.

What ended the problem was not the cleanup: it was rotating every credential, destroying every session, enabling 2FA on all sites, blocking the file editor, and extending all of that to client sites hosted with other providers where the same administrator account existed. One of those sites, outside the perimeter being watched, stayed infected for eleven more days for that single reason.

What to do if your WordPress is infected: step by step

This is the procedure I follow. The order matters.

Step 0: don’t delete anything yet

Preserve the evidence. Copy the suspicious files to a directory outside the public folder keeping their timestamps (cp -p), note each one’s modification time (stat), and export the sessions table. Without the timestamps you cannot reconstruct when and how they got in, and without that you cannot close the door.

Step 1: a full backup, even though it is infected

Files and database, outside the webroot. If the cleanup breaks something, you have somewhere to go back to. An infected backup beats no backup.

Step 2: find every foothold

Build the complete list before touching anything: MU-plugins, plugins, functions.php, altered files inside plugins, posts, options, cron jobs, unknown administrator users, files with a fake extension. Clean one foothold and leave another, and it reinstalls itself.

Watch out for what wp core verify-checksums does not cover: it only verifies the WordPress core. It does not look at plugins or themes. A core that «verifies clean» says nothing about a functions.php or an Akismet file.

Step 3: clean the files and the database

  • Plugins from the official repository with altered files: reinstall them from scratch (wp plugin install <slug> --force). Do not hand-edit them.
  • Altered premium plugins: reinstall from the original licensed package. There are no public checksums to compare them against.
  • Themes: restore the original functions.php or remove the injected line, and check the syntax with php -l before uploading it.
  • Posts: strip the <script> block with a regular expression tested in dry-run mode first, counting how many bytes it removes from each post. In the real case, every post lost exactly 3,177 bytes: if one lost more or fewer, the regex was wrong. Remember that revisions keep their own copy of the content: clean the post but not the revision and the script is still there.
  • Delete the ZIP disguised as an image, and any PHP file inside uploads.
  • Remove from active_plugins any entry whose file does not exist: that is a dormant loader waiting for the file to come back.

Step 4: neutralise the service worker (do not delete it)

If the malware registered a service worker (nochain-sw.js or similar), do not delete the file. The service worker already installed in each victim’s browser keeps running its cached logic even after the file disappears from the server, and at that point there is no way left to reach it.

Replace its contents with a kill switch: a script that on its next activation clears its caches, unregisters itself and reloads the page. Leave it published for several weeks. And tell your host why that file still exists, or their scanner will flag it again purely because of the name.

Step 5: close the door

This is what separates a cleanup from a cleanup that lasts:

  1. Rotate every password: WordPress administrators, database, hosting panel, FTP, SSH. All of them, all unique, all generated by a password manager.
  2. Destroy every session for every user (wp user session destroy <id> --all). Changing the password does not close open sessions.
  3. Rotate the salts in wp-config.php: this invalidates any stolen cookie.
  4. Review and revoke application passwords: they survive any password change.
  5. Block the file editor with define('DISALLOW_FILE_EDIT', true); in wp-config.php. It is the exact tool they used.
  6. Enable two-factor authentication on every WordPress site and on the hosting panel.
  7. Shut down FTP if you don’t use it: it is plain text.
  8. Delete administrator users you don’t recognise, and review the ones you do: is the email address correct?

Step 6: check your own computer

If the attacker has administrator credentials and there is no vulnerability that explains it, the question is where they got them. The most likely answer is an infostealer on the computer of somebody who administers the site. Run a full antivirus scan (not the quick one), close every browser session, and change passwords from a clean machine.

Step 7: purge caches and verify from outside

Purge LiteSpeed, WP Rocket, Cloudflare or whatever you use. Then check from outside the server, with a Chrome user agent and a Google Referer, the homepage and several posts. «The command didn’t error out» is not verification; an HTTP 200 response with no injected script is.

Step 8: respond to your host and to Google

If there was an abuse ticket, answer it in detail: what it was, what was removed, how to verify it, and why a file with a suspicious name still exists (the kill switch). If Search Console flagged the site, request a review once it is clean.

Step 9: tell the people who need to know

If it is a client’s site, their visitors were exposed. Telling them is part of the job, however uncomfortable.

If you are a visitor and you ran the command

Treat your computer as compromised, because it is.

  1. Disconnect it from the internet and run a full scan with an up-to-date antivirus.
  2. From another, clean device, change your passwords starting with your email, then Google/Microsoft/Apple accounts, banking, wallets, social media and work accounts.
  3. Sign out of every active session on each service (the «log out of all devices» option). The thief has your cookies: with those, they get in without a password.
  4. Enable 2FA anywhere you didn’t have it.
  5. If you administered a website from that computer, tell whoever maintains it immediately: the attacker has those credentials.

Why ClickFix comes back (and how to prevent reinfection)

Reinfection is the norm, not the exception, for three reasons:

  • People clean the symptom, not the access. Deleting the file that shows the CAPTCHA without rotating credentials is an invitation to come back tomorrow — and they will, with a different hiding place.
  • Sessions and application passwords survive a password change. You rotate the password, the attacker is still inside on the old session.
  • The perimeter is bigger than what you’re looking at. If the vector is the administrator’s credentials, the scope is everything that person administers, on any server.

The prevention that works is boring and consistent:

  • Real monthly maintenance: core, plugins and themes up to date, with a backup beforehand and verification afterwards. A plugin without an active licence does not announce updates and goes blind to patches: one case involved an unpatched remote code execution vulnerability for exactly that reason.
  • A password manager and 2FA on every account, with no exceptions and no «for now».
  • Least privilege: one user per person, with the role they actually need. No shared administrator accounts.
  • DISALLOW_FILE_EDIT on every site, always.
  • Monitoring published vulnerabilities per plugin (with the WPScan API, for instance), because an intact but outdated plugin passes the checksum and is exploitable anyway.
  • Periodic sweeps of MU-plugins, theme functions.php files and obfuscation patterns, with modification dates.
  • Read your hosting email.

Common mistakes when cleaning a hacked site

  • Restoring a backup without knowing the date of the intrusion. If the compromise was 46 days ago and the backup is 30 days old, you restore the malware.
  • Deleting the service worker. That leaves every victim with the malware installed in their browser forever.
  • Trusting core verify-checksums alone. It doesn’t cover plugins or themes, which is exactly where it hides.
  • Scanning only the homepage. Posts can be infected while the homepage is clean.
  • Looking for a single marker. The same operator changed contract, network and obfuscation within weeks. You have to hunt by behaviour (atob, TextDecoder, new Function, eth_call), not by a file name.
  • Cleaning without closing the access. This is the most expensive mistake. They came back in 9 days the first time and in 2 the second.
  • Assuming a site that isn’t on «your» server is fine. If you administer client sites on other hosts with the same account, they are in scope.
  • Using the host’s scanner as your only source. It finds some of it, sometimes replaces files badly, and its quarantine is not always visible over SSH.

Indicators of compromise (IOCs) observed

For anyone searching their own server. The names change between campaigns; the behavioural patterns change less.

TypeIndicator
MU-pluginwp-content/mu-plugins/nc-dropin.php
Service worker/nochain-sw.js, wp-content/nochain/sw.js, dynamic route /?nochain_sw=1
Fake pluginwp-content/plugins/site-helper-<12 hex>/ with assets/ethers.min.js or assets/lib.umd.js and assets/diag-runner.js
Disguised installerwp-content/uploads/<year>/<month>/cache-<8 hex>.jpg (it is a ZIP)
Variables in the HTMLwpCacheProbe<N>, wpPerfSample<N>, handles sh<12 hex>_vendor-js / _runtime-js
Evasion cookienc_skip=1
Obfuscationatob(...) + single-byte XOR + new Function(new TextDecoder().decode(...))()
Contracts0x58460d0b3d4d6b03761c89120393c0c676676496 (Base) · 0xB6bC9e1D0b2fB96Ab7C47E04Cb0BE477410bC1f2 (Polygon)
Session signatureAdministrator logins from datacenter/VPN IPs with a Mac / Safari 18 user agent, followed by a functions.php write less than a minute later
Ghost adminUsers named adm<6 alphanumeric> with an @example.com address

Frequently asked questions

What is the fake «Verify you are human» CAPTCHA showing on my site?

It is the visible symptom of ClickFix: malware installed on your WordPress that shows visitors a fake verification so they run a command on their computer. It is not a problem with the visitor’s browser or with Cloudflare: your site is the one that is infected.

Why can’t I see it when my visitors can?

Because the malware detects that you are logged in or that you visited wp-admin, and deliberately excludes you. Try it in an incognito window, from another device, arriving from a Google result.

Is it dangerous for me or for my visitors?

For your visitors, very: anyone who runs the command ends up with an infostealer taking their passwords, sessions and wallets. For you too: the attacker has access to your site, and if someone on your team fell for it, they have your credentials. On top of that Google can flag the site as dangerous and your host can suspend the account.

Will Google penalise me?

Google can show the «This site may harm your computer» warning and drop you out of results until you clean up and request a review from Search Console. The longer it takes, the more traffic and reputation you lose.

Is deactivating the suspicious plugin enough?

No. The plugin reinstalls itself from a copy disguised as an image, and there are usually other footholds: the theme’s functions.php, altered files inside legitimate plugins, posts in the database and a service worker in the victims’ browsers. And even if you removed all of it, without rotating credentials and closing sessions they come back.

Does restoring a backup work?

Only if you are certain the backup predates the intrusion, which is usually weeks before anyone notices. And even then you have to rotate every credential, because the backup doesn’t fix how they got in.

How long does a cleanup take?

Containment (stopping the site from serving the malware) happens the same day. The full cleanup, credential rotation, hardening and verification take between one and three days depending on how many sites and footholds are involved. If several sites share an account, all of them get cleaned: the infection is almost never limited to one.

What is EtherHiding?

It is the technique of storing the malware’s configuration in a smart contract on a public blockchain. It lets the attacker change what the script does without touching your server, and makes their infrastructure impossible to take down. It is the reason cleaning the server without closing the access doesn’t work: they hold the controls, from outside.

What do I do if I already ran the command on my computer?

Treat it as compromised: full scan, change your passwords from another device starting with your email, sign out of every service and enable 2FA. If you administered a website from that computer, tell whoever maintains it right now.

How do I stop it from happening again?

Real monthly maintenance, a password manager, 2FA everywhere, the file editor disabled, one user per person, vulnerability monitoring and somebody who reads the hosting notices. There is no magic control; there is consistency.

WordPress malware removal and recovery

At BelkCar Informática I handle incidents like this as part of the WordPress maintenance and security service, and also as a one-off engagement when a site is already infected. The procedure is exactly the one in this article:

  • Containment the same day: your site stops serving malware to visitors.
  • Forensic diagnosis: I find every foothold and reconstruct how and when they got in, with evidence (file timestamps, sessions, logs).
  • Full cleanup: files, database, plugins reinstalled from source, service worker neutralised.
  • Closing the access: rotation of every credential, session destruction, 2FA, editor blocked, server hardening.
  • Real verification from outside, a reply to the host’s abuse ticket and a review request to Google.
  • A report for you and for your clients, in plain language, covering what happened and what was done.
  • Prevention: a monthly maintenance plan so it doesn’t happen again.

I work with sites on Hostinger, SiteGround, cPanel and self-managed VPS, in Argentina and abroad.

Direct contact:

If you write to me, send the domain and, if you can, a screenshot of what your visitors are seeing. That is enough to get started.

Also worth reading


Federico Díaz is the technical lead at BelkCar Informática (Santa Fe, Argentina). He has administered and maintained WordPress sites for news outlets, shops, sports institutions and holiday rentals for over a decade. This article is based on real incidents handled between June and August 2026; the affected sites remain anonymous out of respect for their owners.

Shall we talk?

Tell us what you need and we'll get back to you with clear guidance.

I want to improve my online presence