Version 2: major revision (2026-10-04). This article has been rewritten after an external counter-review and my own re-check of several of its claims. Two “fingerprints” that turned out to be Google Sites platform components are withdrawn, the network chain attributed to a URLScan scan is corrected, the email vector is reframed and the certainty of several kit capabilities is lowered. What changed and why is in the errata. Withdrawn claims no longer appear in the body or the tables.
Table of contents
- What this case shows and what it does not
- The email: a Google auto-responder
- Google Sites as a container for the lure
- Which pages are related (and how strongly)
- Observed infrastructure
- The “gats” kit: what the code contains and what it does not prove
- Timeline
- Open questions
- Indicators, by use
- MITRE ATT&CK
- Why SPF, DKIM and DMARC are not enough (and what helps)
- YARA rule
- Evidence inventory
- Errata 2026-10-04
- Update history
- Appendix: indicators in plain text
On 30 May 2026 I received an email from security-noreply@google.com with valid SPF, DKIM and DMARC and a phishing link in the subject. This article documents what can be shown from it.
What this case shows and what it does not
I use three levels: observed (an artifact shows it), inferred (consistent with what was observed, without direct proof) and not shown (claimed in the previous version without sufficient basis).
| Claim | Status | Evidence |
|---|---|---|
Legitimate Google services sent emails containing a phishing link, with SPF/DKIM/DMARC pass |
Observed | Headers of the three emails |
One of them was sent by a security-noreply@google.com auto-responder |
Observed | Message body (screenshot 1) |
| That email was triggered by an Account Recovery flow | Not shown | The text “Account recovery initiated” is written by the attacker in the subject |
| The lure pages use Google Sites to embed external content | Observed | Preserved HTML of six pages |
Three pages load the same malicious destination (123753243[.]com) |
Observed | Preserved HTML |
That destination served a fake Google login kit (shim.js, codename “gats”) |
Observed | Preserved sample, SHA256 published |
A July 2026 page loaded an identical shim.js (same SHA256) from another domain |
Observed | URLScan scan 019f32f6 (E-06) |
| The six May pages are a single operation lasting ≥6 months | Not shown | Relied on two values that belong to the Google Sites platform |
| The kit relays credentials and MFA in real time | Inferred | Routes, status polling and code comments; no login or relay tested in a lab |
| The kit is operated by one Kameleo browser per victim | Inferred | Two code comments mention “Kameleo profile” |
The email: a Google auto-responder
From: security-noreply@google.com
Reply-To: noreply@google.com
Subject: Re: Account recovery initiated. Wasn't you? Secure your account: sites.google.com/view/G-733828
Received: Fri, 29 May 2026 23:43:40 -0700 (= 2026-05-30 06:43 UTC, mailbox Received)
IP: 209.85.220.69 (mail-sor-f69.google.com)
SPF: pass (MAIL FROM in *.apphosting.bounces.google.com)
DKIM: pass (d=google.com, s=20251104)
DMARC: pass (p=REJECT, aligned via DKIM)
App-ID: s~google.com:roach-hotel
Gmail: Spam label visible in the screenshot
The email, with the Spam label visible. The body is the automatic reply from an unattended Google mailbox (“This e-mail address is not monitored by humans”), pointing to bughunters.google.com. The subject, carrying the lure, starts with “Re:”.
What the screenshot shows is an auto-responder, not an account recovery notification. The body says nobody reads the mailbox, points to bughunters.google.com and states that this channel does not solve account security problems. The subject starts with Re: and repeats text Google does not write: the lure with the URL. The h= field of ARC-Message-Signature lists auto-submitted, in-reply-to and references, which are typical of an automatic reply; that list alone does not prove they exist in the message, and their presence and values would need to be checked in the original.
The simplest reading: someone sent a message to a Google mailbox with an auto-reply, using the lure as the subject, and the reply ended up in the victim’s mailbox. How that reply was directed to the victim (a forged sender in the triggering message, backscatter or another mechanism) is not confirmed: that would require the triggering message. The text “Account recovery initiated” is part of the lure and does not prove that a real recovery flow was used.
Authentication-Results. All three checks pass because the email really did leave Google infrastructure: the sender domain is not spoofed. The Received header is in Pacific time (-0700); in UTC the email is from 30 May.
Two points the previous version did not cover:
- Date. The mailbox
Receivedheader is in-0700. The email was received on 30 May at 06:43 UTC, not on the 29th. - Delivery. The message shows the Spam label in the screenshot. It has not been established whether it was delivered there or moved later, or whether automatic classification, a rule or a manual action was involved. This image cannot be used to judge how well the filters worked.
The emails via Google Workspace (Marketo)
Two other emails (29 May at 01:27 UTC and 30 May at 12:13 UTC) came from workspace@google.com through Marketo. They are the automatic reply to a Google Workspace contact form, with the lure placed in a free-text field:
From: Google Workspace <workspace@google.com>
Via: Marketo (oak.mktdns.com, 199.15.214.195)
SPF/DKIM/DMARC: pass
Reflected text: "We noticed a new sign-in from Miami, Florida [...]
secure your account: sites.google.com/view/g-733828"
808-GJW-314 (the identifier of Google’s Marketo account) and the X-MSYS-API header with tracking disabled belong to the sending platform, not to the attacker: the Google/Marketo template sets them. The two emails arrive at different aliases of the victim’s address (+api6506976 and +api4020596), which someone had to type when filling in the form. This is consistent with a per-send or per-victim identifier, but does not show its exact purpose or that it is automated.
Sequence of the three emails. To compare them, the same reference is used for all three: the Received header added by the Gmail server of the destination mailbox (the same server in all three), normalized to UTC. These are receipt times, not send times, so they are not read as the attacker’s cadence.
Mailbox Received (raw value) |
UTC | Interval | |
|---|---|---|---|
| Workspace/Marketo | Thu, 28 May 2026 18:27:14 -0700 |
2026-05-29 01:27:14 | — |
security-noreply auto-responder |
Fri, 29 May 2026 23:43:40 -0700 |
2026-05-30 06:43:40 | +29 h 16 min |
| Workspace/Marketo | Sat, 30 May 2026 05:13:21 -0700 |
2026-05-30 12:13:21 | +5 h 30 min |
The previous version gave “25 hours” between the first two, based on non-normalized dates.
Google Sites as a container for the lure
Google Sites does not act as a proxy: the page is a visual container inside a trusted domain, and the browser loads the attacker’s content as an embedded document, with its own origin rules. The six preserved pages use two embedding methods.
Iframe by code (G-733828 and g-798225, identical):
<style>
body, html { margin: 0; padding: 0; height: 100%; overflow: hidden; }
iframe { width: 100%; height: 100vh; border: none; overflow: hidden; }
</style>
<iframe
src="hxxps://123753243[.]com/v3/identity/login"
allow="clipboard-read; clipboard-write;"
scrolling="no">
</iframe>
g-624594 points to the same destination with a different snippet: allow="camera;microphone" and sandbox="allow-scripts allow-same-origin allow-popups allow-forms allow-top-navigation".
Whole-page embed by URL (“Whole page embed”: case-159331, ticket-179902, ticket-925681). Here the site author only provides a URL, which Google loads through its own embed frame.
Snippet embedded in the page. The iframe is stretched to the size of the embed frame’s viewport via CSS (height: 100vh).
On the clipboard: allow="clipboard-read; clipboard-write" declares that the embedded content may use those features, subject to the browser’s effective permissions policy, focus and user interaction; it does not mean access is granted. In the preserved artifacts examined (shim.js and the login HTML), no calls to the Clipboard API were found, and no capture was observed.
The Google Sites page trying to load the embedded content, stopped by an anti-bot challenge.
Which pages are related (and how strongly)
A URLScan search for Google Sites pages with login titles returned six with the pattern sites.google.com/view/(g|G|ticket|case)-NNNNNN, indexed between December 2025 and May 2026. I saved the HTML of each one.
URLScan.io results: Google Sites pages with similar slugs and titles. A pattern match is the starting point, not proof of a relationship.
The previous version presented two values shared by the six pages as the actor’s fingerprint: productName: 6b8ce7c0… and an “embed hash” 16cb204c…. Neither of them distinguishes anything:
productNameappears in the same platform configuration block (window['ppConfig']) on legitimate Google Sites pages. I checked it on three sites unrelated to the case, two of them with/view/URLs like the actor’s.- The “embed hash” is a path segment of Google’s generic embed frame (
<N>-atari-embeds.googleusercontent.com/embeds/16cb204c…/inner-frame-minified.html). It appears in public issues unrelated to this case, such as Ruffle #7131 (June 2022), and in public sandbox reports.
With those two values removed, the relationship between pages rests only on what each site’s author controls:
| Page | Embedded destination | Link to the “gats” kit |
|---|---|---|
| G-733828, g-798225, g-624594 | 123753243[.]com/v3/identity/login |
Strong: same destination, where shim.js was captured |
| ticket-7371564 (2026-07-05) | xvcbxcvxncvbn[.]xyz/v3/signin/identifier |
Strong (client component): loads /shim.js with the same SHA256 |
| case-159331 | view-requests[.]com |
Weak: same registrar and same type of lure; the observed client API is different (see below) |
| ticket-179902, ticket-925681 | ephemeral *.trycloudflare.com tunnels |
Weak: slug pattern, title and embed method; the destination content was not preserved |
The July scan was submitted to URLScan by a third party (019f32f6-c0bd-74ab-aae1-0cf9a04c697d, 2026-07-05 15:47 UTC). It records:
sites.google.com/view/ticket-7371564 (title "Signin")
└─ embed → xvcbxcvxncvbn[.]xyz/v3/signin/identifier?_g=… (behind Cloudflare)
└─ GET xvcbxcvxncvbn[.]xyz/shim.js HTTP 200, 16,613 bytes
SHA256 9322530b01376deb2cac6c35ad34a5e5405fdedb4a26fd71d7cbd9c778274a6e (= May sample)
What can be supported: the three May pages share a destination, and the same client component (shim.js) was reused on two different domains, in May and in July. Neither shows the same operator, an identical backend or operational continuity between those dates. That case-159331 and the ticket- pages from December 2025 to May 2026 are related to all this is a reasonable hypothesis, but it is not shown. That is why the claim of “at least six months of confirmed activity” is withdrawn.
It is worth separating same technique (Google Sites as a container), same code component (same shim.js), same infrastructure and same operator. There is strong proof of the same infrastructure for the three May pages and of the same component between May and July. Same operator is not shown.
Observed infrastructure
123753243[.]com
Registered on 2026-05-23 with NICENIC (IANA 3765). It resolved to Cloudflare anycast IPs, so it cannot be acted on at IP level. It served the fake login and shim.js on 30 and 31 May. On 2026-06-04 it was observed in clientHold and no longer resolving. An abuse report had been sent on 2026-05-30. The causal link is not confirmed: the only fact is that the suspension was observed four days after the report. RDAP last changed (2026-06-04T17:20:05Z) records a change to the object, without saying which field changed.
The domain’s first certificate appears in CT 12 minutes after registration. This is consistent with automatic provisioning by the DNS/CDN provider, but does not show that the whole infrastructure was operational at that time.
view-requests[.]com and 45[.]92[.]1[.]158
Registered on 2026-03-14 with NICENIC. The strongest observation is the URLScan scan of 2026-05-06 of case-159331 (019dfe9e…), which predates this investigation:
sites.google.com/view/case-159331
└─ embed → view-requests[.]com → 45[.]92[.]1[.]158 (HTTP 200, Let's Encrypt E8 cert served on that connection)
├─ POST view-requests[.]com/api/status (×6) → 45[.]92[.]1[.]158
└─ GET ipapi.co/json/ (×4) → 172.67.69.226 (Cloudflare, the ipapi.co service)
The previous version summarized this as “Google Sites → view-requests → Cloudflare → 45.92.1.158”. That was wrong: the Cloudflare IP in the scan belongs to ipapi.co (an IP geolocation service the page queries), not to an intermediate hop towards the malicious domain. On 6 May the domain was already served directly from 45[.]92[.]1[.]158.
Two details of that scan:
- The client API of
view-requests[.]com(POST /api/statusplus an ipapi.co query) is not theshim.jsAPI (/api/sessions/...). It may be another stage of the flow (for example, a filter before the login), another version or another kit. There is no code link to “gats”. - That day, on that connection, a Let’s Encrypt certificate for
view-requests[.]comwas served from the IP. This is a handshake observation for that domain and that date, and cannot be generalized to other domains or other dates.
Later observations (June to August 2026, from an isolated node): in the requests and SNI values tested (single accesses, with no kit routes or tokens), HTTP 406, a *.yandex.tr certificate and headers with Yandex markers were observed (x-yandex-req-id with identifiers of different data centres, _yasc cookies). I treat this as a separate observation, without showing that it is the same service that was running in May:
- An isolated
406has several possible explanations (virtual host selection, application policy, another network component). It does not identify the filtering mechanism.CF-Connecting-IPis a header Cloudflare adds to the request towards the origin, so its absence from a response means nothing. - The Yandex markers are consistent with a shared Yandex Cloud layer, a tenant, or a proxy relaying responses from another service. They do not allow attributing who administers the machine.
- Port 22, reported by Censys, is not confirmed as the actor’s.
The certificate renewals observed for view-requests[.]com are consistent with automation and do not prove human intervention; the specific mechanism has not been determined. That 123753243[.]com stopped receiving new issuances after its suspension coincides in time, but it is not an experimental control: clientHold removes the domain from DNS and does not show that the actor lost access to the backend. A wildcard certificate proves what it covers and the corresponding validation, not that subdomains were deployed. The issuing CA alone does not tell whether a certificate sits at the origin or at the edge.
Provider overlaps
Both domains share a registrar (NICENIC) and use different pairs of Cloudflare nameservers. A shared registrar discriminates poorly: it is widely used in abuse, and the overlap is only useful combined with more specific technical evidence. Different NS pairs indicate different DNS configurations. A single Cloudflare account can receive different pairs, so nothing can be inferred about account identity or about deliberate separation. The IP 45[.]92[.]1[.]158 appears in a 2023 ISC feed, but that does not extend the operation to that year.
The “gats” kit: what the code contains and what it does not prove
Between 30 and 31 May, 123753243[.]com served a replica of the Google login and the script /shim.js (16,613 bytes, SHA256 9322530b01376deb2cac6c35ad34a5e5405fdedb4a26fd71d7cbd9c778274a6e). The code uses “gats” as an internal name (gats-session, window.gats, gats-bouncing) and its header describes it as “shared client glue loaded by every sign-in template”. “gats” is a label taken from the code, not the identity of an actor or a commercial product.
Google login replica at /v3/signin/identifier. The _g parameter follows the victim through the whole flow.
What is in the code
- A session API:
POST /api/sessions, polling ofGET /api/sessions/:id/statusevery ~800 ms,POST /api/sessions/:id/action(actionsretry_email,change_account,retry) andDELETE /api/sessions/:id. - Routes for the full Google login flow: password, method selection, TOTP, SMS, push with number matching, backup codes, identity checks by email and phone,
/challenge/wa(WebAuthn), forced password change, a waiting screen (/verify) and a rejection screen (/rejected). - Two comments mentioning “Kameleo profile” (for example: “retry_email action so the same Kameleo profile navigates back with the corrected email”).
- Explicit handling of Safari cookie restrictions and iframe partitioning, consistent with a design meant to work inside an embed.
- The word “Google” built character by character (
["G","o","o","g","l","e"].join("")). This is consistent with an attempt to avoid text signatures, although the intent is not established. - A
_themecookie that selects the light or dark colour scheme on the client. It is an interface preference: it does not show that an admin panel exists.
State /v3/signin/verify: the waiting screen the code shows while it polls the backend for the session status.
State /v3/signin/rejected with the text “Captcha solver coming soon”. It is a message present in the interface; it may be leftover, aspirational or inherited.
Evidence scale per capability
| Level | What it would allow claiming | Reached? |
|---|---|---|
| 1. Route or string present | The client handles that state or method | Yes, for all listed methods |
| 2. Client code calling an API | There is communication logic designed for that flow | Yes, for the session lifecycle, polling and actions |
| 3. Real backend response | The API responded to the observed state or action | Not shown: the waiting and rejection screens were captured, but no API responses that would attribute those states to the backend |
| 4. Effective relay in a lab with a test account | Relay works for that specific method | No |
| 5. Authenticated session shown | Impact confirmed | No |
Classification: a phishing kit with strong signs of being designed for authentication relay (AiTM). It is not publicly verified that it works against each MFA method. A phishing kit can implement AiTM, so the previous version’s “AiTM platform, not a kit” contrast is withdrawn. That it is operated by a Kameleo browser, with one profile per victim, and where that browser runs, are inferences from two comments. On WebAuthn: the /challenge/wa route only shows that the flow handles that state. Passkeys are cryptographically bound to the origin, which is qualitatively different from typing an OTP into a fake page.
The code does not match the public kits I reviewed (Evilginx, EvilProxy, Tycoon 2FA, Rockstar 2FA, Sneaky 2FA, Mamba 2FA, Greatness, ONNX/Caffeine). That comparison is not documented here in detail, so it should be read as indicative, and it is in no way proof of in-house development: it could be a private PhaaS or a fork. The quality of the comments is a documented design choice and says nothing about the authorship or experience of whoever wrote it.
Timeline
Times in UTC. The right-hand column states where each item comes from.
2025-12-02 ticket-925681 indexed (embed → trycloudflare tunnel) URLScan; link to gats NOT shown
2026-03-14 view-requests[.]com registered (NICENIC) RDAP
2026-03-15 view-requests[.]com → 45[.]92[.]1[.]158 OTX passive DNS
2026-05-06 case-159331 → view-requests[.]com @ 45[.]92[.]1[.]158 URLScan 019dfe9e (transactions + cert)
2026-05-23 123753243[.]com registered (NICENIC) RDAP / CT
2026-05-29 01:27 Workspace/Marketo email, lure G-733828 Mailbox Received
2026-05-30 06:43 security-noreply@google.com auto-responder email Mailbox Received; Spam label
2026-05-30 12:13 Second Workspace/Marketo email, same lure Mailbox Received
2026-05-30 Abuse report to NICENIC
2026-05-30/31 123753243[.]com serves fake login + shim.js (gats) Preserved sample (E-04)
2026-06-04 123753243[.]com observed in clientHold RDAP (last changed 17:20:05Z); causality not confirmed
2026-06/08 45[.]92[.]1[.]158 returns 406 with Yandex markers Single accesses from isolated node
2026-07-05 ticket-7371564 → xvcbxcvxncvbn[.]xyz loads the same shim.js URLScan 019f32f6, third-party scan (E-06)
2026-08-21 Fewer new candidates in URLScan Visibility of one source, not real pace
2026-10-04 Negative control: productName / embed hash belong to Google HTML of legitimate Google Sites pages
Open questions
- How the auto-responder was triggered and how the reply reached the victim. This needs the triggering message, which I do not have. The abuse has been reported to Google’s vulnerability programme (bughunters.google.com), which can see that side.
- What
view-requests[.]comis in relation to “gats”. On 6 May it used a different client API. Is it a pre-login stage, another version or another kit? - Whether the
ticket-pages from December 2025 to May 2026 belong to the same operator. The tunnel content was not preserved. - “Miami, Florida” in the subjects. The simplest explanation is that it is part of the lure’s invented text. The alternatives (that it comes from the attacker’s infrastructure or the victim’s profile) have no support.
- Effectiveness of the relay for each MFA method. This would require a controlled lab test, which has not been done.
Indicators, by use
Specific blocking
123753243[.]com # clientHold observed on 2026-06-04; useful retrospectively
hxxps://123753243[.]com/v3/identity/login
xvcbxcvxncvbn[.]xyz # served shim.js on 2026-07-05 (scan 019f32f6); current status not verified
shim.js SHA256 9322530b01376deb2cac6c35ad34a5e5405fdedb4a26fd71d7cbd9c778274a6e
sites.google.com/view/G-733828
sites.google.com/view/g-798225
sites.google.com/view/g-624594
sites.google.com/view/ticket-7371564
Hunting with context (requires human review)
view-requests[.]com # link to gats not shown; associated with case-159331 (2026-05-06)
sites.google.com/view/case-159331
Slug pattern: sites.google.com/view/(g|G|ticket|case|portal|verify)-[0-9]{6,7}
# combined with a Google login title and an embed to an external domain
google.com email whose subject or body reflects a sites.google.com/view/... URL
YARA rule GATS_AiTM_shimjs (v7) # signature for this build, see YARA section
Shared or platform infrastructure: do not block indiscriminately based on this report alone
45[.]92[.]1[.]158 # associated with view-requests[.]com on 2026-05-06; later, Yandex markers and possible shared layer
security-noreply@google.com, workspace@google.com, noreply@google.com
X-Google-Appengine-App-Id: s~google.com:roach-hotel
Marketo 808-GJW-314, oak.mktdns.com [199.15.214.195]
X-MSYS-API with tracking disabled
NICENIC (IANA 3765) # widely used registrar; low discrimination
Historical (no preserved content)
aimed-activities-erik-magnetic.trycloudflare.com # ticket-925681
nursing-nominations-spirituality-origin.trycloudflare.com # ticket-179902
Withdrawn in this version
productName 6b8ce7c01e3dacd3d2c7a8cd322ff979 # Google Sites platform configuration
embed hash 16cb204cf3a9d4d223a0a3fd8b0eec5d # path of Google's generic embed frame
hxxps://view-requests[.]com/v3/... # routes never observed on that domain
MITRE ATT&CK
ATT&CK Enterprise consulted on 2026-10-04. Statuses: observed / inferred.
| ID | Official tactic | Technique | Specific evidence | Status | Confidence |
|---|---|---|---|---|---|
| T1566.002 | Initial Access | Phishing: Spearphishing Link | Google Sites link reflected in authenticated Google emails | Observed | High |
| T1583.001 | Resource Development | Acquire Infrastructure: Domains | 123753243[.]com registered a week earlier and used as the embed destination |
Observed | High |
| T1583.006 | Resource Development | Acquire Infrastructure: Web Services | Google Sites pages created to host the lure | Observed | High |
| T1608.005 | Resource Development | Stage Capabilities: Link Target | Google Sites page prepared as the link target | Observed | High |
| T1656 | Defense Evasion | Impersonation | Google login replica; lures imitating Google security notices | Observed | High |
| T1557 | Credential Access, Collection | Adversary-in-the-Middle | Session API with polling and per-method actions; no relay tested | Inferred | Medium |
| T1111 | Credential Access | Multi-Factor Authentication Interception | Routes and flow for TOTP, SMS, push and backup codes; no interception tested | Inferred | Medium |
Removed compared with the previous version:
- T1102 and T1665 belong to the Command and Control tactic, not Defense Evasion, and there is no evidence here of the C2 use they describe.
- T1056.003 describes code installed on real externally facing portals, not a login clone.
- T1566.003 is not added: T1566.002 is kept as the main mapping for the phishing link. T1566.003 can include personal webmail, so the use of email does not exclude it; what is missing is a justification of how the abuse of these services fits its scope.
- T1036.005 is replaced by T1656, which fits better.
Why SPF, DKIM and DMARC are not enough (and what helps)
The three protocols check different things. SPF checks whether the IP is authorized for the SMTP identity (MAIL FROM). DKIM binds a cryptographic signature to the d= domain. DMARC requires one of the two to be aligned with the domain in the visible From:. None of them assesses whether the content is legitimate, and the DMARC standard itself warns that a passing result does not guarantee a message is safe or wanted. If an authorized service reflects text controlled by a third party (a subject in an auto-reply, a form field), the result is a phishing email with perfect authentication.
The message shows the Spam label, but how it got there has not been established, so this case cannot be used to judge how well the filters worked. Reading the headers did help: they give the sending platform, the timeline and the vector itself (the subject is a header). What is not enough is stopping at three pass results.
What helps:
- Rules that combine message content, the full URL, the destination embedded in the page and behaviour, instead of blocking legitimate senders or all of Google Sites.
- Analysis of the final destination of links, including content embedded in pages on trusted platforms.
- Phishing-resistant MFA (FIDO2/WebAuthn, passkeys) where the environment allows it, reviewing alternative and recovery methods: if the policy allows them, an attacker could lead the user to use a less resistant mechanism. That behaviour has not been shown in this case. The technical reason is origin binding; it is not absolute immunity against every form of account compromise.
- Training users to judge the destination, not the sender.
BIMI would not have changed anything here: the sender was legitimate.
YARA rule
Download: gats_aitm.yar (v7). It is a hunting signature for this specific build of shim.js, based on literal strings. It is not a structural signature of the framework, and every match needs human review.
What was verified (yara 4.5.5 on the preserved sample):
- All 15 declared string identifiers match, with 36 occurrences in total (previously published as “36/36 strings”, which mixed identifiers with occurrences).
- Evasion: if the
gatscodename is renamed and the header comment ($h1) is changed, the rule stops firing even if “Kameleo profile” ($k1) is kept, because branch 4 needs two$s*strings. v6 said$k1also had to be changed, which was wrong. If onlygatsis renamed, the rule still fires through branch 2. - Static analysis, not tested:
$a1,$g1,$h1and$k1appear only in comments, so a process that removes comments would stop finding them. No specific minifier has been tested, nor its final effect on the condition. - It also fires on text describing the kit (reports, this very article). A match does not mean the sample is present.
Limits of the published validation:
- The negative result (0 matches in 58,208 local JS files) counts files, not independent examples. The corpus is not published or deduplicated.
- Benign transformations such as minification or reformatting have not been tested.
- Reviews by two AI models help find mistakes, but do not count as two independent sources.
Changes from v6 to v7, checked with diff: 4 lines of metadata (modified, version, fp_validation and scope). The strings and condition blocks are identical.
gats_aitm.yar v6 SHA256 e0f7b287ae16459084f8368758f890af8874b6237457efcfdb8412828e114a6c
gats_aitm.yar v7 SHA256 51feefbc66ddb415d5e781d49f4a526b922f17c5ccd776095b982725db97926c
Evidence inventory
| ID | Evidence | Date (UTC) | Acquisition | Reference | Availability |
|---|---|---|---|---|---|
| E-01 | Auto-responder email | Received 2026-05-30 06:43 | Own mailbox | Screenshots 1 and 2 in this article | Original under controlled access (personal data) |
| E-02 | Two Workspace/Marketo emails | Received 2026-05-29 01:27 and 2026-05-30 12:13 | Own mailbox, header and .eml export |
Received values quoted above |
Controlled access |
| E-03 | HTML of the six Google Sites pages | 2026-05-30 | Direct download | SHA256 below | Controlled access |
| E-04 | shim.js |
2026-05-30 | Download from 123753243[.]com |
SHA256 9322530b…274a6e |
Public hash; sample under controlled access |
| E-05 | Scan of case-159331 | 2026-05-06 18:48 | URLScan, submitted by a third party | 019dfe9e-581d-76ff-8500-fd9324483f08 | Public |
| E-06 | Scan of ticket-7371564 | 2026-07-05 15:47 | URLScan, submitted by a third party | 019f32f6-c0bd-74ab-aae1-0cf9a04c697d | Public |
| E-07 | productName negative controls |
2026-10-04 | GET to three legitimate Google Sites |
URLs and SHA256 below | Public URLs; their content may change |
| E-08 | RDAP for 123753243[.]com |
2026-06-04 and 2026-06-09 | Registrar and registry RDAP | Status client hold, last changed 2026-06-04T17:20:05Z |
Queryable (current state) |
| E-09 | Observations of 45[.]92[.]1[.]158 |
2026-06-09 and 2026-08-21 | Single accesses from an isolated node | Headers quoted in the text | Own record |
| E-10 | YARA rule v7 | 2026-10-04 | — | SHA256 51feefbc…97926c |
Download in this article |
# E-03 · page HTML (SHA256)
G-733828 85eb7ceda2a87124f60bda4d56aad945425aad17f43aa6decefc1e3410afdb14
g-798225 200764fcb0e9de77af48559c9349efa2a9ce1e8d10897916e2e7c6e1fba3d241
g-624594 7ae9f36baf5e75e04e077ba93d0ae7bd61b95bb02742cd91eb8f8de7a613d304
case-159331 0486fed8da5cb14d5bc19a541a8b6dcb2bf6fcde9e60352cde6fef36dfc68acf
ticket-179902 fd925794461f270856e8223e07ca12ffa282033a14d4021f2223a349d17a2871
ticket-925681 19df54fca42a228752ebad868fa04eea2b15fb7ecf49a86a3f5c7a31cc1a34f9
# E-07 · negative controls (HTML downloaded on 2026-10-04, SHA256)
https://sites.google.com/uchicago.edu/yudeng 7650948ed4ff3c4a956acc0320b749a590e72be345c3e6a0ca38b326d5368460
https://sites.google.com/view/yuding/home 499dbfb75c1b928e475d8ba5923b461a565c80bd0f2f28389a673b468df11088
https://sites.google.com/view/sites-help 698daf1b0bc3cd82214cd4f2aa84ef4a466aeb2f8a0854141d8b11ca252872f3
# In all three: window['ppConfig'] = {productName: '6b8ce7c01e3dacd3d2c7a8cd322ff979', ...}
The actor’s pages and the emails are not published in full because they contain live URLs or personal data. They can be shared with researchers on request.
Errata 2026-10-04
This revision corrects specific errors in page grouping, network interpretation, the email vector, the scope of attributed capabilities and several infrastructure interpretations. They are grouped into five blocks; the detail is in the expandable table.
- Page grouping. The two “cluster fingerprints” (
productNameand the embed hash) are Google Sites platform components. Without them, the six pages do not hold up as a single operation, nor do the “six months of activity”. What is shown is the same destination for three May pages and the same client component in May and in July. - Network. The chain “Google Sites → view-requests → Cloudflare → 45.92.1.158” mistook a query to
ipapi.cofor a network hop. The/v3/...routes attributed toview-requests[.]comwere never observed on that domain. - The email. The observed artifact is an auto-reply; it has not been shown that Account Recovery triggered it. It was received on 30 May (UTC), not the 29th; it shows the Spam label; and the “25 hours” interval was wrong.
- Kit capabilities. MFA relay, Kameleo, admin panel, clipboard capture and “senior developer” move from confirmed to inferred or withdrawn. The “AiTM platform, not a kit” contrast is withdrawn.
- Infrastructure interpretations. CA ≠ network position, wildcard ≠ subdomains, renewal ≠ maintenance, 406 ≠ header filtering, shared registrar ≠ attribution link, different NS ≠ different accounts, temporal proximity ≠ causality of the abuse report. MITRE corrected.
What went wrong in the process
The earlier re-verifications (9 June, 4 July, 21 August) repeated queries and confirmed the data was still there, but did not test the interpretations. The one on 9 June went as far as saying that “the whole technical body was confirmed”, and it was not: the errors in this section were already in the text and in the preserved evidence. They checked whether the infrastructure existed, not whether the conclusions followed from it.
What I am changing in my method
- Negative control before calling something a fingerprint: check the value against legitimate pages on the same platform.
- Every graph edge with its source: URL, initiating frame, destination, date and type of evidence. A flat list of contacted IPs is not a chain.
- All dates in UTC before calculating intervals.
- Evidence scale for capabilities: a route or a code comment does not confirm that something works.
- Re-verifications try to refute, not just repeat queries.
Detail of the corrections (25 items)
| Claim in the previous version | Correction | Basis |
|---|---|---|
productName and the embed hash are the actor’s fingerprint and link the six pages |
They are Google Sites platform components; withdrawn | They appear on legitimate pages (checked on three sites); the embed hash is the path of Google’s generic frame |
| Operation with “at least six months of confirmed activity” since December 2025 | Same destination (three May pages) and same client component (May and July); the rest is a hypothesis | What remains after withdrawing the fingerprints; scan E-06 |
| The URLScan scan confirms “Google Sites → view-requests → Cloudflare → 45.92.1.158” | The Cloudflare IP belongs to ipapi.co; the domain was served directly from 45.92.1.158 |
Transactions of scan 019dfe9e |
| “Account Recovery” vector | Observed auto-reply from security-noreply@google.com; Account Recovery not shown; trigger mechanism unconfirmed |
Message body |
| Email of 29 May | Received on 30 May, 06:43 UTC | Mailbox Received in -0700 |
| “25 hours” between the first two emails | 29 h 16 min between receipts | Mailbox Received, normalized to UTC |
| DKIM/SPF/DMARC “are not enough”, without mentioning delivery | The message shows the Spam label; how it got there is not established | Message screenshot |
| Google Sites “as a transparent proxy” | Visual container: the browser loads an embedded document | How the iframe works |
| The clipboard permission allows “silent capture” | Permission declared in the iframe; no calls in the artifacts examined | shim.js and login HTML |
Snippet with a height="100vh" attribute |
The real snippet uses CSS height: 100vh; g-624594 uses another snippet |
Preserved HTML |
| TOTP, SMS, push and backup codes “confirmed”; Kameleo “confirmed” | Capabilities inferred from the code (levels 1-2 of the scale) | No relay tested |
| “Professional AiTM platform, not a phishing kit”; “senior developer” | Phishing kit designed for relay; authorship and experience not established | — |
_theme cookie implies an authenticated admin panel |
Client-side theme preference | shim.js, lines 23-39 |
| “Captcha solver coming soon” confirms active development | Message present in the interface, of uncertain origin | — |
| The shared registrar is the “strongest attribution link” | Provider overlap with low discrimination | — |
| Different NS pairs = different accounts / deliberate separation | Different DNS configurations, nothing can be inferred about the accounts | One account can receive different pairs |
| Let’s Encrypt at origin and Sectigo/GTS at edge, by CA; wildcard = deployed subdomains | The CA does not indicate network position; a wildcard does not prove hosts | Only one observed handshake (2026-05-06, view-requests) |
| Certificate renewal = actor maintenance | Consistent with automatic renewal; specific mechanism not attributed | Already corrected in August; now propagated to the body |
| “406 without CF headers” = header filtering | The 406 does not identify the mechanism; CF-Connecting-IP is in the request, not the response |
— |
| “Same origin gate active” from May to August | Separate observations, continuity not shown | — |
| “The abuse report took effect in ~4 days” | Suspension observed 4 days later; causality not confirmed | — |
| “The campaign has collapsed” | Fewer candidates observed in one source | — |
| T1102/T1665 under Defense Evasion; T1056.003; T1566.003 | Tactics corrected or techniques removed | ATT&CK, consulted on 2026-10-04 |
/v3/... paths attributed to view-requests[.]com |
Withdrawn: never observed on that domain | Scan 019dfe9e |
YARA: evasion requires also changing $k1 |
The codename and $h1 are enough |
yara 4.5.5 on the sample |
Update history
- 2026-05-30. First publication. The same day, the second Workspace/Marketo email arrives with the same lure.
- 2026-05-31. Capture of the fake login and
shim.json123753243[.]com. - 2026-06-04.
123753243[.]cominclientHold. - 2026-06-09. Re-verification from an isolated node. Yandex markers on
45[.]92[.]1[.]158; port 22 unconfirmed. - 2026-07-04. Corrections: T1584.001 → T1583.001; the Google and Marketo identifiers are not the attacker’s;
X-MSYS-APIcannot be attributed to the attacker;shim.jshash published. - 2026-08-21. Certificate renewals do not show maintenance. New candidate pages with
portal-/verify-slugs, no link shown;ticket-7371564loads the sameshim.js. - 2026-08-22. YARA rule v6.
- 2026-10-04. Version 2: major revision after an external counter-review and my own negative control. See the errata. YARA rule v7 (metadata only). The July scan is documented and an evidence inventory is added. The auto-responder abuse has been reported to Google’s vulnerability programme.
Methodology: the investigation (headers, pivots, screenshots, re-verifications) is my own work. This version incorporates an external counter-review and was drafted with AI assistance (Claude, Anthropic). The artifacts are preserved and listed in the evidence inventory: the two URLScan scans and the negative controls can be verified publicly; the rest can be shared with researchers under controlled access. Observations not yet corroborated by a third party are marked as such.
Operation reported to Google Safe Browsing, Google Cloud Abuse, Google Workspace and NICENIC. The security-noreply@google.com auto-responder abuse has also been reported to Google’s vulnerability programme (bughunters.google.com).
Appendix: indicators in plain text
# ============================================================
# SPECIFIC BLOCKING
# ============================================================
123753243[.]com # clientHold observed on 2026-06-04; RDAP last changed 2026-06-04T17:20:05Z; exact time of application not confirmed
xvcbxcvxncvbn[.]xyz # served shim.js on 2026-07-05 (URLScan 019f32f6); current status not verified
hxxps://123753243[.]com/v3/identity/login
hxxps://123753243[.]com/v3/signin/identifier
sites.google.com/view/G-733828
sites.google.com/view/g-798225
sites.google.com/view/g-624594
sites.google.com/view/ticket-7371564
# shim.js ("gats" kit, 16613 bytes)
# SHA256 9322530b01376deb2cac6c35ad34a5e5405fdedb4a26fd71d7cbd9c778274a6e
# SHA1 8b74b60567160b1753059452406638d27dce2c0a
# MD5 7bbd1d7d485b6f6ebbeb28b469970670
# Kit API (shim.js, 2026-05-31)
POST /api/sessions
GET /api/sessions/:id/status
POST /api/sessions/:id/action
DELETE /api/sessions/:id
# Flow routes (shim.js / login HTML, 2026-05-31)
/v3/signin/challenge/pwd /v3/signin/challenge/pwd/retry /v3/signin/challenge/pwd/last
/v3/signin/challenge/selection /v3/signin/challenge/totp /v3/signin/challenge/sc
/v3/signin/challenge/dp /v3/signin/challenge/dp/number /v3/signin/challenge/bc
/v3/signin/challenge/ipe /v3/signin/challenge/ipe/collect /v3/signin/challenge/ipp
/v3/signin/challenge/kpp /v3/signin/challenge/wa /v3/signin/verify
/v3/signin/review /v3/signin/review/done /v3/signin/rejected
# ============================================================
# HUNTING WITH CONTEXT
# ============================================================
view-requests[.]com # associated with case-159331 (2026-05-06); link to gats not shown
sites.google.com/view/case-159331
# slug: sites.google.com/view/(g|G|ticket|case|portal|verify)-[0-9]{6,7} + Google login title + external embed
# ============================================================
# DO NOT BLOCK INDISCRIMINATELY (platform / shared)
# ============================================================
45[.]92[.]1[.]158 # AS210558; associated with view-requests[.]com on 2026-05-06; later, Yandex markers
security-noreply@google.com / workspace@google.com / noreply@google.com
X-Google-Appengine-App-Id: s~google.com:roach-hotel
Marketo 808-GJW-314 / oak.mktdns.com [199.15.214.195]
# ============================================================
# HISTORICAL
# ============================================================
aimed-activities-erik-magnetic.trycloudflare.com
nursing-nominations-spirituality-origin.trycloudflare.com
# ============================================================
# WITHDRAWN 2026-10-04 (do not use)
# ============================================================
# productName 6b8ce7c01e3dacd3d2c7a8cd322ff979 -> Google Sites platform
# embed hash 16cb204cf3a9d4d223a0a3fd8b0eec5d -> Google's generic embed frame