From a single URL to a pan-European fake-voting PhaaS cluster.
How Bounce-CTI, an autonomous CTI pivoting agent, took two URLs received over WhatsApp and unmasked the Cloudflare-fronted operation behind them — and where it deliberately stopped short.
Six things this run shows.
- 01
Starting from one URL — a French-language "School votingFR" fake-voting page received over WhatsApp — Bounce-CTI fingerprinted the host, recognised it was Cloudflare-fronted, recovered the true origin server, and pulled the origin TLS certificate that bound several sibling domains together. From that single seed it mapped a 7-domain cluster.
- 02
The origin (
217.145.226[.]186, AS205775, bulletproof hosting) was already known to a previous investigation. The agent recognised it as repeat actor infrastructure rather than starting from zero. - 03
The strongest cluster evidence is the shared origin-certificate SAN and the shared origin IP — not the shared JARM. The JARM is a generic Cloudflare-edge fingerprint, and the agent explicitly down-weighted it to corroboration only. A tool that headlined "all domains share JARM X" would have been wrong.
- 04
The cluster was absent from every community and abuse feed queried (OTX, ThreatFox, Pulsedive, AlienVault, URLhaus). This makes the data set an early-warning view, with two confirmed cluster members still sitting at VirusTotal 0/94.
- 05
On request, the agent expanded the cluster to two dozen domains across four TLDs and three languages (French, German, Italian) — a recurring, multilingual pan-European operation, not a one-off French burst.
- 06
Confidence is reported as a gradient. The agent flagged what it could not prove, refused a false pivot, and stopped on yield instead of padding the graph.
What you're looking at.
Bounce-CTI is a research prototype: an autonomous threat-intelligence pivoting agent. You give it one observable — a URL, domain, IP, or file hash — and it decides for itself which open sources to query next, builds an infrastructure graph live in the browser, and writes a structured analyst report at the end. Three design choices shape everything below.
- reasons
It reasons about pivots, it doesn't brute-force them. The agent chooses the next source based on what it has already found, and it defuses shared/benign infrastructure (CDN ranges, parking, sinkholes, DynDNS) before pivoting on it — so the graph never explodes into noise.
- bounded
It is bounded and auditable. Each investigation caps itself at a limited pivot depth and API budget. You can watch every decision stream past as it happens.
- passive
It is defensive by construction. Everything here is passive OSINT and threat-hunting enrichment. The agent never interacts with the infrastructure it describes; it has no shell and no filesystem access, only read-only intelligence tools.
The walk-through below follows three real runs: a single-seed investigation, a second seed merged into the same graph, and a conversational "find the rest of this campaign" expansion.
From one URL to a cluster.
The seed
The investigation starts with a single observable — a link that arrived, unprompted, in a WhatsApp message:
A French-language "School votingFR" page — the classic fake-contest / fake-voting lure ("vote for my entry"). The link is pushed peer-to-peer through WhatsApp and Messenger, riding the trust of a known contact, which is also why it lands in front of victims long before it lands in any abuse feed. The second seed in Act 2 reached a different person through the same channel — two independent WhatsApp deliveries of the same kit, a week apart.
francevoice29[.]click). The pretext — “vote for my friends' daughter, the prize is a free dance class” — is the classic fake-voting lure, riding the trust of a known contact. Only the message body is shown; no sender details were captured.The WhatsApp delivery is a first-hand observation of the distribution vector — the messages were received directly. It is recorded as analyst-supplied context, not as something the graph proves; the infrastructure findings below stand on their own technical evidence. Keeping the two separate is the same discipline the agent applies throughout: strong markers and corroborating context are never conflated.
Triage and defusing
The agent's first move is to observe: resolve DNS, pull RDAP, query URLScan and VirusTotal. It immediately establishes that the domain is Cloudflare-fronted — its A records sit in Cloudflare ranges (104.21.21[.]216, 172.67.200[.]153), its nameservers are Cloudflare, and it carries the standard Cloudflare TLS fingerprint. This is the moment most automated OSINT tooling drowns. Pivoting on a Cloudflare IP returns millions of unrelated sites. Bounce-CTI instead defuses those nodes — tags them as CDN edge and refuses to pivot on them — and pivots on the registration and certificate surface instead.
cdn) before the agent pivots — the single most important step in keeping infrastructure graphs signal-dense.The reasoning is visible
Because the agent streams its decisions, you don't just get a verdict — you see why. In its own words, mid-run:
Cloudflare-fronted (A records in 104.21/172.67), registered 2026-04-11, Dynadot registrar. This triggers the origin-unmask step.
— Bounce-CTI agent log, run 1
Unmasking the origin
A Cloudflare-fronted phishing page hides its real home. To find it, the agent runs a passive datascan (Onyphe) keyed on the host and certificate — and recovers the origin:
The node fills in fast, and the picture is unambiguous:
- ASN
AS205775 — NEON CORE NETWORK LLC (RIPE org TrafficTransitSolution LLC, geolocated RU; abuse
info[at]traffictransitsolution[.]us) — bulletproof-style hosting. - panel
Running nginx/1.18.0 (Ubuntu) with a Python/3.10 aiohttp panel on
tcp/5001— the PhaaS control panel itself, exposed. - ports
Open ports
22/80/443/5001, OpenSSH 8.9p1, and a handful of version-banner-inferred CVEs (regreSSHionCVE-2024-6387, HTTP/2 Rapid ResetCVE-2023-44487,CVE-2021-23017). The agent recorded these as banner-derived context, not confirmed-exploitable findings — correct restraint.
tcp/5001, recovered without ever touching the server.The certificate that tied it together
The decisive evidence is the origin's TLS certificate:
- serial
06:97:88:8e:72:55:f2:31:11:cb:10:98:d1:ad:01:50:5d:f1 - cn
CN
voteingmap[.]click, SHA-256548b4f01…78497 - SAN
SAN-bound to multiple cluster domains:
francedancingvotingfr[.]click,konkurzfrance[.]click,voteingmap[.]click
A single certificate on the origin server cryptographically links three of the sibling domains. Combined with a second domain (panek2n[.]shop) co-hosted on the same origin with its own certificate, this is strong, discriminating attribution — the kind that holds up.
Every domain in the cluster shares JARM 27d40d40d00040d1…3d525c. A naive tool would headline that as proof. Bounce-CTI flagged it as a generic Cloudflare-edge fingerprint that matches thousands of unrelated hosts, and treated it as corroboration only. A JARM membership sweep returned 324K characters of non-discriminating results and was discarded. The cluster is held together by the origin certificate and the shared origin IP — the JARM just rhymes with it.
This distinction — strong markers vs. generic ones — is the whole game in infrastructure CTI. Reporting a CDN fingerprint as a cluster signature is how false clusters get built.
A known address
When the agent enriched the origin, its cross-investigation memory flagged something: 217.145.226[.]186 — and the exact certificate SHA-256 548b4f01… — had appeared in prior investigations, already tagged phaas / actor-origin. This isn't a fresh discovery; it's repeat infrastructure from a returning operator.
The cluster, Act 1
From one URL, the agent settled a 7-domain cluster:
| Domain | Role | First seen | VT (at scan) |
|---|---|---|---|
| konkurzfrance[.]click | Seed (FR "School votingFR") | 2026-04-11 | malicious |
| voteingmap[.]click | Origin cert CN | 2026-04-10 | 11 |
| francedancingvotingfr[.]click | Origin cert SAN | 2026-04-11 | 0 |
| panek2n[.]shop | Co-hosted on origin (fake-shop variant) | 2026-05-14 | 0 |
| danncervotting[.]click | Same kit /home/votenam | 2026-04-18 | 5 |
| dancorevoting[.]click | Same kit /home/votenam | 2026-04-15 | 6 |
| reeechka[.]club | Oldest member; Italian variant | 2026-02-22 | 11 |
Two members — francedancingvotingfr[.]click and panek2n[.]shop — were at VirusTotal 0/94 yet provably in-cluster. Those are exactly the domains defenders want to block before detection catches up.
A second seed, one graph.
A real investigation rarely has one starting point. A second link — delivered over WhatsApp to a different person, a week after the first — surfaces:
Two independent WhatsApp deliveries of the same kit, reaching two different targets, is itself a signal: this is an active distribution campaign, not a dormant page. Dropped into the same investigation, the new link doesn't start a separate report — it merges into the existing graph. The agent enriches it (VirusTotal malicious 8/94: BitDefender, Fortinet, G-Data flag phishing; Sophos flags malware; alphaMountain categorises the domain Malicious) and the graph automatically draws the bridges to the existing cluster:
- jarm
It presents the same Cloudflare JARM (corroborative).
- registrar
It is registered through Spaceship, Inc. — the same registrar used by existing cluster member
dancorevoting[.]click— inside the same April-2026 registration window. - kit
It serves the identical kit at the same
/home/vote*path.
Its true origin could not be recovered on free/passive sources (only the Cloudflare front was visible; a confirmed shared-origin link would need a paid datascan). So the tool placed it in the cluster on registrar + kit + corroborating JARM — and explicitly declined to assert a shared-origin-IP edge it couldn't prove.
"Find the rest of this campaign."
Bounce-CTI is also conversational. With the cluster mapped, a single instruction:
Find as much domains / URLs as possible, belonging to the same campaign.
— analyst prompt, chat panel
The agent ran a kit-fingerprint sweep (URLScan kit-path /home/voteng + page-title search) and returned 16 additional campaign domains, all serving the byte-identical "School votingFR" kit:
Chips marked VT✓ were independently VirusTotal-confirmed.
Three findings make this the most important act:
-
It's multilingual and pan-European.
Alongside the French "School votingFR", the sweep surfaced a German variant ("School votingGR",
koncnckcurs[.]cfd) and an Italian variant (italyvoice215[.]click). The mixed-language domain naming (konkurz/concours/konkcurs— competition across Slavic, French, and garbled forms) points to a PhaaS operator serving several language markets, not a France-only actor. -
The confidence is graded, not flattened.
Two of the sixteen —
balletvotee38[.]click(VT 12) andkonkcurserr[.]cfd(VT 8, VirusTotal-taggeddga) — were independently VirusTotal-confirmed as exact cluster members carrying the cluster JARM and the same Dynadot/Global Domain Group registrar. The remaining fourteen rest on byte-identical kit + path evidence — high confidence on kit identity, with origin co-residency left explicitly unconfirmed (passive DNS on the bulletproof origin was empty; confirming it would need a paid JARM datascan). -
It told us the map is incomplete.
The page-title sweep exceeded the tool's result limit — so the agent reported plainly that more members almost certainly remain and a paged follow-up would extend coverage. It didn't pretend the campaign was fully enumerated.
What the agent didn't do.
For a senior analyst, restraint is as telling as discovery. Across these runs Bounce-CTI:
- refused
Refused a false pivot. Two live domains shared an inline-script hash (
2050f127…). The agent noticed both pages were actually returning Cloudflare 522 error pages and concluded the shared hash was the CDN error-page script, not a kit signature. It recorded the node at low confidence, tagged itcloudflare_522_artifact, and wrote "do not treat as a cluster pivot." - flagged
Flagged a contradiction it couldn't resolve. Geolocation came back DE from AbuseIPDB but RU from Onyphe's geolocus. Rather than pick one, it recorded both and noted geo was unreliable for this host.
- discarded
Discarded its own typo artifact. An auto-generated stub (
reeechka[.]click, a near-miss of the realreeechka[.]club) was caught and taggedignoreinstead of being passed off as a finding. - stopped
Stopped on yield. With the core cluster mapped, it noted that every remaining queued pivot would only return already-defused CDN or already-graphed values — and stopped, rather than inflating the graph to look busy.
These are the behaviours that separate a usable intelligence tool from a confident-sounding one.
Defensive takeaways.
- early
This is an early-warning data set. The cluster was absent from OTX, ThreatFox, Pulsedive, AlienVault, and URLhaus at the time of investigation — attribution rests on the graph evidence (origin cert SAN, shared origin, identical kit), not on third-party verdicts.
- vector
The distribution vector is messaging, not email. Both seeds were delivered over WhatsApp, peer-to-peer — which sidesteps email gateways entirely. Defenders relying only on mail-flow controls won't see this class of lure.
- block
Block the silent members first.
francedancingvotingfr[.]clickandpanek2n[.]shopwere at VT 0/94 but provably in-cluster. Pre-emptive blocking is the whole value here. - kit
Hunt the kit, not just the domains. The durable fingerprint is the
/home/vote*"School voting(FR/GR)" kit template — it surfaces new domains the operator hasn't burned yet. - abuse
Abuse routing. Registrar abuse: Dynadot / Global Domain Group (
abuse[at]dynadot[.]com) and Spaceship (abuse[at]spaceship[.]com); Cloudflare for the fronting; RIPEinfo[at]traffictransitsolution[.]usfor the origin. - rotation
Expect rotation. Registrations span 2026-04-02 → 2026-05-24; the operator mints fresh domains continuously. A recurring sweep keeps the picture current.
Technique mapping.
| Technique | ID | Tactic |
|---|---|---|
| Phishing | T1566 | Initial Access |
| Acquire Infrastructure: Domains | T1583.001 | Resource Development |
| Acquire Infrastructure: Virtual Private Server | T1583.003 | Resource Development |
| Proxy: Domain Fronting | T1090.004 | Command and Control |
How this was produced — and where it stops.
Every result above came from free, passive, open sources — DNS, RDAP, crt.sh, VirusTotal, URLScan, Onyphe, AbuseIPDB, CriminalIP, OTX, ThreatFox, Pulsedive, Wayback. No active scanning, no interaction with the infrastructure, no paid feeds.
That last point is also the main limitation, and the agent was candid about it: the origin co-residency of the expanded domain set could not be confirmed because passive DNS on a bulletproof, Cloudflare-fronted host is empty on free sources. A paid Shodan/Onyphe JARM datascan would close that gap. The campaign enumeration is also deliberately incomplete — the agent capped itself and reported where more results remain.
Findings are graph-native and map cleanly to STIX 2.1, so a cluster like this can be exported as a bundle for ingestion into OpenCTI, MISP, or TheHive rather than living only as a picture.
IOCs.
⚠ All indicators are defanged. Re-fang at your own risk, in an isolated environment only.
Seed URLs · 2
Cluster domains — core · cert / origin / kit-confirmed · 8
Cluster domains — expanded · kit-identical; two VT+JARM-confirmed · 16
koncnckcurs[.]cfd → DE variant · italyvoice215[.]click → IT variant
Origin
Certificates
Per-domain Let's Encrypt serials
TLS fingerprint · corroborative only — generic Cloudflare edge
Defused · benign / CDN — do not pivot
Host fingerprint
This case study was produced end-to-end by Bounce-CTI, an autonomous CTI pivoting agent, from free and passive open sources. Bounce-CTI is a research prototype. Live demo available on request.