A Staging C2 That Introduces Itself: Unauthenticated /health on a Custom Flask Panel at 67.215.232.25
A Staging C2 That Introduces Itself: Unauthenticated /health on a Custom Flask Panel at 67.215.232.25
TL;DR
On April 9, 2026, we followed a lead from @1ZRR4H into a custom Python/Flask command-and-control server at 67.215.232.25 — a HostPapa/ColoCrossing VPS in Los Angeles. The panel listens on two ports (8080 for the operator interface, 5000 for what appears to be the agent listener) and exposes an unauthenticated /health endpoint that politely self-reports the C2's operational state: active agent count, pending command count, completed command count, and status.
At the time of investigation the box is idle — active_servers: 0, pending_commands: 0, completed_commands: 0 — which is the kind of thing only a C2 would feel compelled to tell you. It's fresh infrastructure with zero prior threat intelligence coverage across VirusTotal, OTX, URLhaus, ThreatFox, and AbuseIPDB, and the earliest Shodan surface dates only to March 4, 2026, which makes it a prime candidate for pre-deployment monitoring rather than post-mortem reporting.
What this report adds to the public record:
- A first-look snapshot of
67.215.232.25while it's still in staging: SSH fingerprint, the exact/healthJSON schema, the auth rejection semantics on the protected endpoints, and the two-port architecture - A detection-ready fingerprint for this panel style: HTTP responses from non-standard ports containing all of
active_servers,pending_commands,completed_commands,status,healthyon the same JSON body - An SSH host-key pivot point unique to this IP for defenders who want to correlate
Hat tip to @1ZRR4H for the lead. If you've already published reporting on this panel style, this IP, or the SSH host key below, please reply or DM — we'll update and credit.
The Target
| Field | Value |
|---|---|
| IP | 67.215.232.25 |
| ASN | AS36352 (HostPapa / AS-COLOCROSSING) |
| Location | Los Angeles, CA, US |
| OS | Ubuntu Linux |
| Reverse DNS | None |
| Allocated | 2025-01-30 (HostPapa /24 block via ARIN) |
| First Shodan observation | 2026-03-04 (SSH) / 2026-03-28 (port 8080) / 2026-04-02 (port 5000) |
| Prior threat intel presence | None |
The /24 block was allocated about 14 months ago; the box itself was provisioned around early March 2026, and the second Flask listener on port 5000 was added only a week before our investigation on April 2. Everything about the deployment timeline says staging.
Open Ports
| Port | Service | Version | Role |
|---|---|---|---|
| 22 | SSH | OpenSSH 9.6p1 Ubuntu 3ubuntu13.15 | Operator access |
| 25 | SMTP | — | Firewall-filtered |
| 5000 | HTTP | Werkzeug/3.1.6 Python/3.12.3 | Suspected agent listener (all paths → 404) |
| 8080 | HTTP | Werkzeug/3.1.6 Python/3.12.3 | Operator panel with /health and /api/* |
Two Flask instances on the same box is itself a pattern worth noting — one public-facing on a management port, one on a secondary port that answers nothing on any common path we tested. That's consistent with an operator/agent separation where the agent port expects specific, non-guessable routes (UUIDs, signed tokens in the path, or specific headers before it'll route anything).
Port 8080 — The Management Panel
| Method | Endpoint | Response | Auth? |
|---|---|---|---|
GET | /health | 200 with JSON | No |
POST | /api/report | 401 {"error":"Authentication failed"} | Yes |
POST | /api/heartbeat | 401 {"error":"Authentication failed"} | Yes |
GET | /api/report | 405 Method Not Allowed | — |
GET | /api/heartbeat | 405 Method Not Allowed | — |
The /health response (captured 2026-04-09T02:12:45Z)
{
"active_servers": 0,
"completed_commands": 0,
"pending_commands": 0,
"status": "healthy",
"timestamp": "2026-04-09T02:12:45.515454"
}
Field by field, this hands defenders the panel's entire tasking model:
active_servers— currently-connected implantspending_commands— tasks queued for implants to pullcompleted_commands— tasks implants have executed and reported backstatus— panel operational statetimestamp— server-side UTC
The natural interpretation of that schema is: operators queue commands via the panel → agents poll /api/heartbeat to pull pending tasks → agents post results back to /api/report. The fact that the POST-only endpoints return 401 on empty bodies and 405 on GETs means the panel is routing correctly and enforcing auth — the operator just forgot to include /health in the auth-required set.
Auth mechanism (what it isn't)
We probed the obvious auth shapes on /api/report to see what the panel expects:
- Bearer tokens → rejected
- HTTP Basic → rejected
X-API-Keyheader → rejected- Body-embedded
server_id/api_key/token/auth_key→ rejected
All return {"error":"Authentication failed"}. That leaves a custom scheme — most likely a shared secret embedded in a non-standard JSON field, HMAC over the body, or timing/nonce checks. The panel requires Content-Type: application/json (it returns 415 Unsupported Media Type on form-encoded bodies), which is consistent with a hand-rolled JSON-only API.
Port 5000 — The Quiet One
Port 5000 runs the same Werkzeug/Flask stack but returns 404 on every path we tried — root, /api, /v1, /v2, /beacon, /agent, /gate, /task, /callback, and about a hundred more common C2 routes. Behavior consistent with:
- A listener expecting specific, non-guessable endpoint paths (UUID-routed agents, signed paths, etc.)
- A listener that requires specific HTTP headers before routing (e.g.,
X-Implant-Idor a custom auth header) - A backup / secondary channel that isn't fully wired yet
Given the agent tasking model implied by the /health schema, (1) is the most likely reading: the agent probably beacons to a path like /<agent-uuid>/beacon and any other path returns 404 as cover.
This Isn't an Off-the-Shelf Framework
We walked this panel through the usual suspects and it matched none of them:
- Cobalt Strike — no BEACON patterns, no malleable C2 profile, no team server ports
- Sliver — no gRPC / mTLS, no implant registration endpoints
- Havoc — no Demon agent patterns
- Mythic — no GraphQL API, no Apollo routes
- Metasploit — no Meterpreter handler signatures, no stage patterns
The Flask + Werkzeug + minimal JSON API stack, the "report/heartbeat" naming, and the lack of any standard framework fingerprint all point to a custom panel — either bespoke to this operator or an early-stage framework that hasn't been publicly released.
Attribution
None — yet. The panel has zero OPSEC tells that I could find:
- No leaked emails, domains, or associated accounts
- No identifying strings in the
/healthbody beyond timestamp format - No TLS cert (HTTP only across the board)
- No associated hostnames, domains, or certs in crt.sh or VT passive DNS
- Infrastructure too new and too clean for confident attribution
Use of HostPapa / ColoCrossing (AS36352) is consistent with low-cost VPS procurement — common across everything from script kiddies to bulletproof hosting resellers. Not a discriminator.
Detection & Hunting
Network
- Block
67.215.232.25at the perimeter on all ports. - Alert on HTTP responses containing all five fields
active_servers,pending_commands,completed_commands,status,healthyin a single JSON body — that exact combination is a tight fingerprint for this panel style. A singlegrepover web-scanner archives will surface sister boxes if this framework is deployed elsewhere. - Alert on HTTP traffic to non-standard ports (
5000,8080) containing JSON payloads withapi_key,heartbeat, orreportfields in the body. - Flag raw-IP HTTP POSTs to
/api/heartbeator/api/report— direct IP comms with no associated hostname is the norm for this deployment pattern.
SSH pivot
The server's SSH host key is unique to this IP in Shodan's index:
Type: ecdsa-sha2-nistp256
Fingerprint: b9:db:77:d7:f0:2f:98:f3:27:9a:09:e5:dc:0e:63:7f
Public key: AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBDN8gOvi3wu8Z2DMxeldHv3uQj2/JQoFqk7eraXDvzd8+n6NAqpL0dMvDfVwyInizh7g/cLlJMR8HMPev7xvCs8=
If this key turns up on a second IP, that's sister infrastructure.
Monitoring
- Periodic Shodan polling on this IP — when
active_serversclimbs above0the panel has gone operational and defenders should expect beaconing traffic. - Watch the
67.215.232.0/24subnet for sibling deployments using the same Werkzeug banner. - Watch VirusTotal / OTX passively — when samples pointing at this C2 finally surface, they'll reveal the client-side binary format and unlock the auth scheme.
MITRE ATT&CK
| Tactic | Technique | ID |
|---|---|---|
| Resource Development | Acquire Infrastructure: VPS | T1583.003 |
| Resource Development | Develop Capabilities: Malware | T1587.001 |
| Command and Control | Application Layer Protocol: Web Protocols | T1071.001 |
| Command and Control | Non-Standard Port | T1571 |
| Command and Control | Ingress Tool Transfer | T1105 |
IOCs
67.215.232.25 Custom Python/Flask C2 (HostPapa LA)
67.215.232.25:8080 Operator panel (Werkzeug/3.1.6)
67.215.232.25:8080/health Unauthenticated status endpoint
67.215.232.25:8080/api/report Suspected result posting (auth req)
67.215.232.25:8080/api/heartbeat Suspected agent beacon (auth req)
67.215.232.25:5000 Suspected agent listener
b9:db:77:d7:f0:2f:98:f3:27:9a:09:e5:dc:0e:63:7f SSH ecdsa fingerprint
Detection signature (JSON field combination):
active_servers + pending_commands + completed_commands + status + healthy
in a single HTTP response body on a non-standard port
Disclosure
- HostPapa abuse:
net-abuse-global@hostpapa.com(+1-905-315-3455)
The box is still idle as of this writing. We're not publishing the panel side — this post is defender-first. If you have reason to believe you have an implant beaconing to 67.215.232.25 on port 5000 or 8080, the SSH host key and the /health schema are your tightest pivots.
GHOST — Breakglass Intelligence "One indicator. Total infrastructure."