Cloaker Malware Stopped in 48 Hours, 22K Visits Saved
Four months after taking a medical tourism clinic from 7,600 to 22,000 organic visits a month, someone tried to delete all of it. A cloaker was serving Indonesian gambling pages to Google’s crawler while showing the clean site to every human visitor. It had been doing it for weeks.
The outcome if we had not caught it is not speculative: Safe Browsing flag, then a hacked-content manual action, then de-indexing, then 22,000 visits a month to zero, and for a healthcare client the loss of commercial credibility on top of the traffic.
It did not happen. 48 hours from identification to confirmed clean, seven consecutive verification checks over 32 hours, zero rankings lost, zero Search Console warnings, zero Safe Browsing flags. This is the protocol, written to be repeated rather than admired, plus the part almost nobody in SEO knows about: the cloaker was not the vulnerability. It was the second stage.
Client: anonymised, a medical tourism clinic in a YMYL sector · Target market: Italy plus cross-border international · Incident window: second half of 2026 · Attack type: GRESIKTOTO cloaker malware plus dormant DNS TXT hijacking of Search Console ownership · Traffic at risk: 22,000 organic visits a month · Time to clean: 48 hours · Consultant: Jeansy Sese
Executive summary
Entry vector: hosting credentials compromised months earlier, before two-factor authentication was enabled, combined with a pre-authentication vulnerability in a mainstream WordPress plugin.
Potential impact: Google Safe Browsing flag, a hacked-content manual action, total de-indexing, loss of the featured snippets the site had won.
Actual impact: zero. Clean-up completed in 48 hours, seven consecutive Googlebot checks clean across 32 hours of monitoring, no ranking movement, no Search Console warning, no traffic lost.
The part worth your time is not the malware. It is the dormant vector: a google-site-verification TXT record planted in the DNS zone months in advance, which silently granted the attacker Search Console ownership the moment a subdomain went live. No file integrity monitor, no plugin scanner and no WAF would have found it, because it was never on the filesystem.
How we found it
SEO is also the discipline of reading weak signals, the patterns that will never show up in a rank tracker but that an attentive operator notices within hours. Four of them, in order of appearance:
- Unexpected title changes on two core URLs,
/it/and/en/, in the Search Console coverage report. - A spike of gambling queries in Performance,
slot gacor,situs slot,jalur link, with zero clicks. Impossible for an aesthetic surgery site. - Newly indexed URLs matching a
/cache-*.htmlpattern that was nowhere in the sitemap. - Time on page collapsing on desktop but not on mobile, the classic signature of asymmetric cloaking.
The decisive test was trivial, and it should be monthly routine in any serious SEO audit:
curl -A "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" \
-s https://[client].tld/it/ | grep -iE "gresiktoto|slot gacor|situs slot|jalur link"47 matches on a single request. The same URL opened in a browser: zero matches, a perfectly clean site.
Anatomy of the GRESIKTOTO cloaker
GRESIKTOTO is the name given to a family of Indonesian cloakers that specialise in diverting SEO traffic into illegal gambling networks. The business model is surgical:
- It does no visible damage, so the owner does not notice.
- No pop-ups and no redirects for human visitors.
- Gambling content is served only to Google’s crawler, identified by user agent.
- It exploits the victim domain’s authority to index thousands of doorway pages.
- It monetises by hijacking the click on gambling queries only.
It is the perfect parasite: it lives on the client’s SEO without killing it immediately. Google penalises cloaking when it detects it, which can take weeks. Meanwhile the attacker earns.
Why medical tourism sites are chosen
High-authority YMYL sites are preferred targets for three reasons. Pre-accumulated trust, because the domain already has solid credibility signals, so gambling doorways index faster. International traffic, because a multi-country target means multi-language doorways without building authority from scratch. And non-technical owners, because clinics, medical practices and health tourism agencies rarely have a security engineer in house. This client had all three.
The mechanism
The payload was a modified index.php in two strategic directories, /it/ and /en/, precisely the folders carrying the most SEO weight. In pseudo-code:
<?php
if (stripos($_SERVER['HTTP_USER_AGENT'], 'googlebot') !== false
|| stripos($_SERVER['HTTP_USER_AGENT'], 'bingbot') !== false) {
// Serve gambling payload with spam title, H1 and body
include 'wp2.php'; // static payload, deliberately never touches the DB
exit;
}
// Otherwise: continue the normal WordPress bootstrap
require __DIR__ . '/wp-blog-header.php';Two non-obvious details deserve attention, because they are why the usual defences missed it.
The payload was static, not dynamic. The file wp2.php, named to sit comfortably among legitimate WordPress files, served pre-generated HTML without ever querying the database. No suspicious MySQL queries, no anomalous database access pattern. Database-oriented intrusion detection does not see this at all.
It was a fork of the bootstrap, not a replacement. The index.php was not wholly malicious. It ran the payload only on a user-agent match and otherwise let WordPress run normally. That makes detection by diff harder and, more importantly, means the file works for anyone testing it from a browser in an admin session.
The SEO impact that was avoided
| Risk | Estimated probability | Impact |
|---|---|---|
| Google Safe Browsing flag | 70% within 30 days | Minus 100% organic traffic within 24 hours |
| Manual action, hacked user-content | 40% within 45 days | Selective de-indexing of infected URLs |
| Manual action, pure spam | 15% within 60 days | De-indexing of the entire domain |
| Loss of featured snippets | 90% within 14 days | Minus 40% click-through on target queries |
| Loss of topical authority | Certain | Three to six months to recover after clean-up |
Probabilities are my own estimates based on documented cases of this cloaker family, not measured outcomes. They are here to size the decision, not to be quoted as data.
The most common scenario in the literature is the first: a Safe Browsing flag, which makes Chrome show the red “Deceptive site ahead” interstitial to anyone opening the site. For a healthcare client that is the end of commercial credibility, not just of traffic. The worst is the third, where recovery needs a reconsideration request, a certified clean-up and generally six to twelve months to return to pre-incident levels.
The dormant vector: DNS plus Search Console hijacking
The cloaker was not the vulnerability. It was the symptom. The real vulnerability was two dormant elements, triggered in sequence.
Vector 1 — Compromised hosting credentials
The credentials for the client’s managed shared hosting account had been compromised months earlier, most likely through phishing or password reuse. The attacker sat on them without using them, which is a typical pattern: steal today, monetise later, avoid the temporal tripwires that catch an immediate login.
When the client later enabled two-factor authentication on the hosting account, the attacker did not lose access. They had already placed dormant TXT records in the domain’s DNS zone, weeks before. Those records did nothing visible. They waited.
Vector 2 — The phantom google-site-verification TXT
This is the trick most SEOs do not know. A google-site-verification TXT record on the domain root verifies ownership in Search Console not only for that domain, but for any URL-prefix property that starts with it. Subdomains included. Specific paths included.
The attacker had planted a google-site-verification=R1VT... record in the DNS months earlier. As long as the target subdomain was not live, the Search Console verification stayed pending. Silent. Invisible.
When the client launched a subdomain, a new landing page on the same infrastructure, Search Console completed the pending verification automatically. The attacker became a legitimate owner of that subdomain in Google’s eyes without touching anything at deploy time. The only trace was a notification email: new owner added.
At that point the attacker held:
- Search Console access to the subdomain: queries, sitemap submission, re-indexing requests.
- The ability to submit a disavow file and sabotage the link profile.
- The ability to remove URLs through the removals tool.
- Visibility into the client’s traffic, useful for calibrating the next attack.
The cloaker on /it/ and /en/ was the second stage. The first stage was ownership, planted months earlier and triggered at the right moment.
Why this changes the job description
Most WordPress incident response frameworks concentrate on file integrity monitoring, plugin and core vulnerability scanning, and malware detection in PHP files. None of those would have found the dormant DNS TXT records. They are not on the site’s filesystem, not in a plugin, not in a PHP file. They are in the DNS zone: a separate system, often managed from a different panel, with audit logs nobody reads.
If you do SEO on domains with commercial value, DNS TXT records belong in your monthly audit, not your client’s IT team’s, because the consequence of a malicious TXT record is an SEO consequence.
The clean-up protocol
The exact operational sequence, in priority order.
Step 1 — Isolate, do not delete
The golden rule: never delete malicious files before taking a forensic copy. You need it to understand the vector, find the other compromised files and reconstruct the timeline. Copy every suspect file out of the document root into a directory the webserver does not serve, and preserve the original timestamps with cp -p.
Step 2 — Vanilla restore, not manual cleaning
For compromised core files, do not attempt to clean them by hand. The risk of leaving a nested backdoor is too high. Replace them with a vanilla copy downloaded directly from wordpress.org, preserving wp-config.php only after verifying it. If the client has legitimate customisations in index.php, which is rare, document them first and reapply them after.
Step 3 — Hard credential rotation
In this order: hosting passwords for every account and not just the admin, SSH keys revoked and regenerated, the MySQL password with wp-config.php updated, WordPress passwords for every user at editor level or above, WordPress salt keys regenerated, API keys for every integrated service such as mailer, CRM and payments, and two-factor authentication everywhere it is available, including hosting, Search Console and the WordPress admin.
Step 4 — Full DNS audit
This is the step most protocols skip. Export the complete DNS zone and check every single TXT record, particularly google-site-verification, facebook-domain-verification, expired _acme-challenge entries, and any SPF or DKIM record with an undocumented selector.
For each google-site-verification record: identify which Google account it belongs to by asking the presumed owner directly; if nobody on the team confirms creating it, delete it immediately; then regenerate a verification you control, to keep legitimate ownership.
Step 5 — Search Console clean-up
Remove every owner or user you do not recognise, check owners on every property and sub-property, check whether the disavow file has been modified by looking at its timestamp, check the removals tool for recent requests, and confirm that the submitted sitemap is yours and not an injected one.
Step 6 — Patch the upstream vulnerability
Here the re-entry vector was a mainstream WordPress plugin with an open pre-authentication CVE: authentication bypass with remote code execution through an unvalidated file upload. Updated during the clean-up week.
The principle: cleaning without patching the entry point is bailing out a boat without plugging the hole. It fills back up.
Step 7 — Googlebot verification, the step everyone skips
Without this step, never declare a clean-up finished. Test eight to ten representative URLs, including the homepage, the language roots, deep pages and a deliberate 404, requesting each one with Googlebot’s user agent and checking four things in the response:
for url in "https://client.tld/" "https://client.tld/it/" \
"https://client.tld/it/sub-page-1/" "https://client.tld/en/" \
"https://client.tld/it/does-not-exist-xyz/"
do
response=$(curl -A "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" -s "$url")
hits=$(echo "$response" | grep -icE "gresiktoto|slot gacor|situs slot|jalur link|gresikvip")
title=$(echo "$response" | grep -oE '<title>[^<]+</title>' | head -1)
canonical=$(echo "$response" | grep -ciE 'rel=["'\'']canonical["'\'']')
size=$(echo -n "$response" | wc -c)
echo "$url -> size=$size | hits=$hits | canonical=$canonical | $title"
doneWhat the output must show:
- Zero gambling hits on every URL, including the 404.
- One canonical on every 200, zero on the 404s.
- A per-page title, not the same title everywhere, which confirms WordPress routing is actually running.
- A response size consistent with the expected content, with no unexplained 2KB or 500KB pages.
Repeat the test every four to six hours for 24 to 36 hours. A cloaker can be time-scheduled, active only in certain windows, or set to reappear automatically through cron. One clean check proves nothing.
On this client we ran seven consecutive checks from T+0 to T+32 hours. Five of nine URLs were byte-identical to the previous check, confirming the WordPress cache had reached steady state. Zero gambling hits. Correct titles and canonicals. Working 404. Only then did we call it clean.
Step 8 — Thirty days of monitoring
An automated Googlebot check every six hours through cron, an immediate alert on any gambling hit, Search Console coverage monitoring for unexpected URLs, Performance query monitoring for gambling patterns, and a weekly DNS TXT audit.
The legal dimension: YMYL, GDPR and liability
This case had a dimension classic SEO case studies do not: legal liability. The client operates in healthcare. Pure YMYL. The site collected contact requests containing health information, specific questions about treatments and optional patient photographs. Under GDPR those are special category data, Article 9.
An attack that potentially exposes health data triggers the obligation to notify the supervisory authority within 72 hours under Article 33, where there is a likely risk to the rights and freedoms of the people concerned. Here the forensic analysis concluded that the cloaker served a static payload and never read the patient database, that there was no evidence of access to the user database from the moment of compromise, no evidence of exfiltration, and that the attacker’s objective was SEO hijacking for gambling revenue rather than data theft.
That was documented in a data protection assessment and the event was classified as a near miss: contained potential risk, no mandatory notification. The point is that the assessment has to be written down and signed by the data protection officer or equivalent, not left implicit.
Who answers if data had been exfiltrated? The short version: the data controller, which is the client. External processors, hosting, agency, developers, answer only for the parts under their direct control and only within the data processing agreement they signed. With no written DPA, liability defaults entirely to the controller.
The lesson: if your SEO agency has Search Console, FTP, database or DNS access to a client processing special category data, you need a signed DPA. That is not bureaucracy. It is the difference between being involved and being named.
Why security here is SEO, not IT
| Discipline | What it looks at | What it does not look at |
|---|---|---|
| Traditional IT security | File integrity, CVEs, WAF, backups | DNS TXT records, Search Console ownership, user-agent cloaking |
| Classic SEO | Keywords, backlinks, content, crawl budget | Malware, shells, plugin vulnerabilities |
| Security-SEO | The intersection: anything that can destroy rankings through a technical vector | — |
A security engineer will protect you from a data breach but will not flag a malicious google-site-verification record, because it is not an IT risk. A classic SEO will optimise your Core Web Vitals but will not request index.php with Googlebot’s user agent, because it is not an SEO job. In between there is an operational gap, and it is exactly the gap this family of cloaker is built to exploit.
The monthly Security-SEO checklist
Week 1, files and infrastructure. Diff index.php, wp-load.php and wp-config.php against the official repository. Check plugins for open CVEs. Audit WordPress users at editor level or above and remove dormant ones. Confirm two-factor authentication is active on hosting, the WordPress admin and Search Console.
Week 2, DNS and domain. Dump the full DNS zone and diff it against last month. Audit every TXT record, identify its owner, delete the phantoms. Check WHOIS privacy and that the domain expires more than a year out. Check SPF, DKIM and DMARC for consistency.
Week 3, Search Console and ownership. Users and permissions on every property, authorised owners only. Verify the disavow file by timestamp and content. Check the removals tool for recent requests. Confirm the submitted sitemap is the real one.
Week 4, behaviour and crawling. Googlebot curl test on eight to ten representative URLs, checking spam patterns, titles and canonicals. Server log analysis for anomalous user-agent patterns. Search Console query review for off-topic patterns. Coverage report review for unexpected indexed URLs.
Four hours a month. The cost of not doing it is the case you have just read.
Limits and honesty about the data
- Single sample. One client, one attack, one recovery. This is an operational proof of concept, not statistical evidence that the framework works in every context.
- Favourable timing. We found the cloaker before Google issued a Safe Browsing flag or a manual action. Had we found it afterwards, the recovery scenario would have been radically different: reconsideration request, three to six months of rebuilding authority. The framework leans on proactive detection precisely to avoid that path.
- A specific entry vector. Pre-2FA hosting credentials plus one plugin CVE. Other vectors, a supply chain attack through a nulled theme, script injection through comments, reflected XSS, would need the framework adapted.
- Zero impact is verified in the short term. No ranking loss in the 30 days after the clean-up. Six to twelve month monitoring is ongoing, so delayed effects are not 100% excluded. So far there are no negative signals.
- The probability table is an estimate, built from documented cases of this cloaker family, not from measured outcomes on this site.
- Anonymised data. The client and the specific host are anonymised for reputational protection. The technical details, malware family, cloaking technique, TXT pattern, plugin CVE class, are public and already documented in threat intelligence feeds, malware analysis reports and CVE databases. No zero-day is disclosed here.
Is the framework repeatable?
Yes, with three preconditions.
- Real technical access to hosting, DNS, Search Console and the WordPress admin. If your agency does not have these or cannot use them, the framework does not apply: it needs an operator with a sysadmin mindset alongside the SEO one.
- Client consent for tests that look aggressive. Repeated curl requests with Googlebot’s user agent can be read as a malicious bot by some firewalls, so they need whitelisting or an authorised IP.
- Tolerance for false positives. A monthly TXT audit will find, on average, one or two records nobody remembers creating. In 95% of cases they are legitimate: old services, retired tools, verifications from a previous agency. But you cannot assume legitimacy. You have to check them one at a time, which takes time and a certain amount of patience.
Conclusion: SEO without security is a sandcastle
Building SEO authority takes months. Destroying it takes days.
Organic growth is not an asset until it is a defended asset. A ranking is not yours while a cloaker, a phantom DNS TXT record or an unpatched plugin can take it from you in 48 hours.
That is why my audits now include a dedicated Security-SEO block. Not as an optional extra. As a prerequisite.
And the detail I would keep from the whole incident is the smallest one: the attacker never needed to break in again. They had written one line into a DNS zone months earlier and waited for the client to deploy something. The defence was not a firewall. It was reading a TXT record.
Want to know whether your site is exposed to a cloaker? A Googlebot scan across ten URLs, a DNS TXT dump with phantom verification records identified, a Search Console owner check, a plugin CVE list and a remediation report. Advanced SEO consulting.
Italian version: Caso studio Security-SEO: cloaker malware fermato in 48 ore.