We Had UNC6671's Phishing Infrastructure Within Hours at Confidence 70. Our Auto-Block Path Ignored It. The Feed Did Not — and We Got That Wrong the First Time We Published This.
- Patrick Duggan
- 57 minutes ago
- 6 min read
Google's threat intelligence team published research this week on UNC6671, the extortion crew formerly branded BlackFile and now operating simultaneously as REDACT, PINK, HELIX and FALCON. They have been calling hedge fund and private equity employees on their personal mobile phones, spoofing the corporate helpdesk, and telling them they need to enrol a passkey. Point72, Millennium, Two Sigma and Citadel are among the named targets. Investigators tracked 141.65 bitcoin across eighteen wallets between 7 January and 12 May — roughly $10.69 million.
We went to check what our feed held. This post is mostly about what we found, and it is not flattering.
We had it. It was not blocking anything.
Seventy-six phishing domains and the AiTM proxy addresses were already in our corpus. They arrived through a community feed at 06:33 UTC on the morning the research went public — genuinely fast, and not our detection.
Every single one carried confidence 70.
Correction, made within the hour of first publishing this. The original version of this post said a customer pulling our feed that morning got none of it. That is wrong, and the error was ours in both directions — we under-credited our own product while over-claiming a failure.
Our STIX feed takes a min_confidence parameter and it defaults to zero. Every one of these indicators was being served to anyone who pulled the feed, from the moment they landed at 06:33. A customer filtering at 70, or not filtering at all, had the whole campaign that morning.
What actually failed is narrower and still worth fixing: 80 is the threshold for the automatic enforcement artifacts — the edge shield, ips.csv, domains.csv. Those are the paths where we make the blocking decision on the customer's behalf. At 70, our automation declined to act on data we were already handing out.
So the honest statement is that the intelligence was distributed and the automation was not armed. Those are different failures with different fixes, and conflating them let us tell a more dramatic story than the facts supported.
We wrote this exact paragraph in June. In the Nissan correction we described holding a ShinyHunters command-and-control URL at blocking confidence while the bare domain sat at 70, and said plainly that a defender doing DNS-level blocking would not have been covered. We said the fix was a rule: a domain should inherit the highest confidence ever assigned to any path observed on it.
That rule addressed the case where we held the same indicator twice at different confidences. It does nothing for this case, where a whole campaign arrives from one feed at a uniform 70 and simply never crosses the line. The lesson generalised less than we thought it had.
The indicators are now re-ingested at confidence 90 with actor attribution, which is what puts them in front of the blocklist rather than behind it. Of 83 records, 73 verified on write and 9 came back queued behind the index write lock — those land asynchronously and are re-verified rather than re-ingested. One failed outright and is being chased. We are giving you the split rather than the round number because a feed that reports 83 of 83 every time is not reporting.
Our own search told us we had nothing
While checking coverage we ran all eighty-three published indicators through our search API. It reported zero of eighty-three present.
That is wrong. The enrichment path returns them correctly. Had we trusted the search result we would have published a confident, checkable, entirely false statement about our own feed — that we had none of this campaign — on the same day we in fact had most of it.
We are recording that because it is the more dangerous of the two defects. A sub-threshold confidence score is a tuning problem with a known fix. A search path that returns a clean zero for records that exist is a machine for manufacturing false gaps, and a gap report is exactly the kind of thing that feels authoritative when it is printed.
The fingerprint we were looking for was inverted
We track company-impersonating login domains as a staging signal. It is how we caught vercel-sso.com seven months before the Vercel disclosure, and the argument behind our staging-layer work is that you can see attacks before they land if you watch where they are assembled.
So we searched our corpus for the pattern against the named funds — point72-sso.com, twosigma-sso.com and the rest. Nothing. What came back for "point72" was a set of ClearFake C2 domains beginning point2-, matched on fuzzy similarity and completely unrelated. "Citadel" returned malicious npm packages with randomly generated names. "BlackFile" returned a domain called blackfire.
The reason the search failed is that we had the shape backwards. UNC6671 does not put the victim in the apex. They register a generic passkey-themed apex and put the victim in the subdomain: company.createssopasskey[.]com, company.addssopasskey[.]com.
That is worth understanding rather than just noting, because it changes what you block. A victim-named apex is single-use and you are always chasing the next registration. A generic apex with victim subdomains is reusable across every target the crew touches — which means blocking the seventy-six apexes covers funds they have not attacked yet. The inversion that made them harder to find by name makes them easier to block by pattern.
The apexes are relentlessly on-theme: myoktasso, passkeyenroll, activatepasskey, oktaportalsso, enablepasskey2fa, passkeyhelpdesk. If a domain combines "passkey," "okta," "sso" or "mfa" with an enrolment verb and was registered recently, that is the shape.
The vector, and why Levi's belongs in the same post
Levi Strauss disclosed on 7 August that an unauthorised third party reached corporate systems by social engineering three employees. More than 72,000 people are affected. No exploit, no CVE, no malware in the initial access.
Different actor, different sector, same door. UNC6671 phones a fund employee about passkey enrolment. ShinyHunters spent most of this year phoning helpdesks for MFA resets. Somebody phoned three people at a denim company.
The uncomfortable summary of 2026 initial access is that the phone call is winning. It costs almost nothing, it does not require a vulnerability, it is not detectable by any tool in the security stack, and it scales through call centres. Everything downstream of it — the AiTM proxy, the session cookie theft, the alert deletion, the bulk export — is competent but ordinary. The innovation is entirely social.
UNC6671's post-access tradecraft is the part worth copying into your detection engineering: they delete password-reset confirmations, MFA modification alerts, and company-wide security notifications from the compromised mailbox. The victim's own alerting is treated as a cleanup task.
What to do on Monday
Block the seventy-six apexes rather than hunting victim-named domains, because the apex is the reusable asset. They have been in the feed since 06:33 and are now at confidence 90, which additionally arms the automatic enforcement paths. If you pull the feed directly, set min_confidence deliberately rather than inheriting a default — it defaults to zero, which means you get everything, which is usually what you want for hunting and rarely what you want for auto-blocking.
One verification note for anyone checking our work: querying one of these values through an enrichment lookup may still return the older confidence-70 record, because our index holds multiple documents per value and returns one of them. The confidence-90 record exists alongside it. We mention it because we tripped over it ourselves an hour ago and briefly concluded our own write had failed.
In your identity provider, alert on an MFA registration event immediately preceded by an authentication failure or an abandoned push challenge. That sequence is the vishing call succeeding, and it is visible in Okta logs as system.multifactor.factor.setup following user.authentication.auth_via_mfa.
In Microsoft 365, treat FileAccessed with the same severity as FileDownloaded when the user agent contains a scripting library. Google's report names python-requests/2.28.1, WindowsPowerShell/5.1 and a spoofed Okta Android SDK string. Humans do not browse SharePoint with python-requests.
Then the non-technical control, which is the one that actually works: publish internally that your helpdesk will never call an employee's personal mobile to initiate an MFA or passkey change, and that any such call should be hung up on and reported. This costs an email. It defeats the entire initial access chain.
What we did not ingest, deliberately
Google published eleven addresses. We ingested seven.
The four we left out — on AT&T, Comcast, Starry and Optimum — are residential proxy pools the crew rents to make authentication look like it comes from a plausible home connection. They are real ISP customer addresses. Blocking them blocks somebody's actual house. They are useful for detection and dangerous as a blocklist entry, and pushing them into a feed that automatically enforces would make us the problem.
The accounting
Google's threat intelligence team did this research. We did none of it. Our contribution is putting the indicator set into a free feed at a confidence that actually enforces, and correcting our own coverage.
The receipts are uncomfortable ones: our automatic enforcement declined to act on a campaign we were already distributing, our search path reported we held none of it, and the first version of this post got the customer impact backwards. All three are now corrected.
We guarantee five percent of what we publish is wrong. Today the five percent was in this post, and it survived about forty minutes. The thing that caught it was somebody asking whether customers could set their own threshold — which they can, which meant the scary version of the story was never true.
Her name was Renee Nicole Good.
His name was Alex Jeffery Pretti.




Comments