A coordinated credential-harvesting campaign built from someone else’s home internet connections.

Observed: 2026-05-26 → 2026-06-02 (7 days)

First published: 2026-06-24

Signal: 5,469 connection attempts from 88 unique IPs across four sensor regions

Core finding: identical HASSH fingerprint, identical Python SSH library, zero auth successes — pure credential-list construction at scale

Defensive value: HASSH signature, behavioral detection rule, ISP prefix aggregates


What we observed

Over seven days, our sensors logged 5,469 connection attempts from 88 unique source IPs against honeypot sensors deployed across four regions. Every single attempt used the same SSH client fingerprint. Every single attempt failed to authenticate. No post-auth activity was ever recorded.

This is not a brute-force attack. It is credential validation: an operator testing whether a harvested list of username-password pairs opens SSH on internet-exposed servers, producing a filtered list of working credentials for later use.

The 88 source IPs share one property: they are all residential broadband addresses on two Vietnamese ISPs, Viettel and VNPT. They are not rented VPS nodes, not datacenter infrastructure, not Tor exits. They are home internet connections — routers, DSL modems, FTTH CPE — that have been compromised and recruited into a scanning fleet.


Technical fingerprint

SSH client library

Every connection carried the banner SSH-2.0-AsyncSSH_2.1.0.

AsyncSSH is a Python library for asynchronous SSH operations. It is not a compiled scanner. An attacker who builds a credential-validation tool on top of AsyncSSH is writing Python, not C or Go. This matters for attribution and for detection: a Python-based scanner running on compromised residential hardware implies a specific operator profile — one comfortable with Python scripting and able to maintain persistent access to a fleet of home devices.

HASSH fingerprint

All 88 IPs produced the same HASSH value:

fda360b1b4f4d345...

HASSH is a network fingerprint derived from the key exchange algorithms, encryption ciphers, MAC algorithms, and compression methods advertised by an SSH client. A matching HASSH across 88 nodes confirms they are running the same tool version on the same configuration — not independent actors who happen to use AsyncSSH, but a single coordinated fleet.

This fingerprint was consistent across all four sensor regions and across the full seven-day window with no rotation. The operator did not attempt to vary the fingerprint to evade detection.

No successful logins

Across 5,469 attempts and 88 source IPs: zero successful authentications.

The honeypots accept a range of common credential pairs. The fact that none of the attempted credentials succeeded tells us either that the wordlist used by this operator does not overlap with the credentials accepted by our sensors, or that our sensors are not the primary target and the operator is testing a more specific list against a specific set of services. Either way, the operator was not exploiting anything — they were probing.


Infrastructure

Fleet composition

The 88 IPs fall inside five ISP broadband allocations belonging to two Vietnamese operators, Viettel Group (AS7552) and VNPT (AS45899):

AllocationOperatorTypeHosts
27.79.0.0/16Viettel GroupFTTH/DSL broadband27
116.110.0.0/16Viettel Groupbroadband / mobile26
171.231.0.0/16Viettel Groupmobile 4G (CGNAT)14
171.243.0.0/16Viettel Groupmobile 4G (CGNAT)9
116.99.0.0/16VNPTFTTH/DSL broadband12
Total88

These are end-user broadband and mobile allocations, not datacenter or hosting space: the APNIC records for the covering blocks describe them as consumer broadband and mobile services.

The mobile addresses (171.231.*, 171.243.*) are 4G LTE ranges served via carrier-grade NAT. Attribution to a specific device behind these addresses is not possible without ISP cooperation; the IPs represent NAT gateway exit points, not individual devices.

Cross-region coordination

The same core set of IPs — particularly those from Viettel’s 27.79.0.0/16 range — appeared across all four sensor regions within the same seven-day window:

Sensor regionUnique IPsEvents
Region A (primary)824,387
Region B17362
Region C16318
Region D15402

Seven hosts appeared in three or more of the sensor regions — six in Viettel 27.79.0.0/16 and one in VNPT 116.99.0.0/16. These are the most active nodes in the fleet, and their cross-regional presence confirms centralized task distribution — a controller is assigning targets to nodes, not each node operating independently.


Assessment

The behavioral profile is consistent with the reconnaissance phase of a credential-stuffing operation:

  1. A set of credentials has been harvested from a previous breach, phishing campaign, or purchase.
  2. The operator needs to know which credentials are still valid against live SSH servers.
  3. The validation tool is deployed on compromised residential devices to reduce detection risk and rate-limiting exposure.
  4. Valid credentials are collected for later use — lateral movement, persistence, resale, or integration into a larger botnet.

The choice of AsyncSSH (a Python library) over commodity Go-based scanners (the dominant choice for well-resourced actors) suggests either a smaller-scale operator with Python tooling preferences, or deliberate selection of a less-detected library. AsyncSSH’s legitimate use cases mean it is less likely to appear in threat intelligence feeds than purpose-built scanners.

The residential broadband infrastructure adds a layer of operational security: blocklists for residential CIDRs are rarely deployed in production environments because blocking large ISP ranges produces unacceptable false-positive rates. An operator who can maintain persistence on dozens of home routers or CPE devices gets a fleet that is harder to block than a datacenter cluster.

We do not attribute this campaign to a specific threat actor. The operator responsible for distributing the scanning script to these 88 devices is not identified by this data. The ISPs involved (Viettel, VNPT) are the owners of the compromised end-user devices, not the campaign operator.


Detection

No single signal is sufficient here. HASSH identifies a client build and configuration, not an actor: every install of the same AsyncSSH version on the same configuration yields the same value, legitimate ones included. Combine signals.

Composite rule

  1. Client bannerSSH-2.0-AsyncSSH_2.1.0
  2. HASSHfda360b1b4f4d345...
  3. Authentication outcome — repeated failures, no success anywhere in the session
  4. Destination dispersion — many distinct destination hosts rather than one target
  5. Timing cadence — regular machine-paced intervals rather than human bursts

Signals 1 and 2 narrow the field. Signals 3, 4 and 5 are what separate a scanning fleet from a legitimate AsyncSSH automation that happens to share a build.

Behavioral fallback

Where HASSH is unavailable: AsyncSSH 2.1.0 banner with no successful authentication in the session, correlated across more than one destination. This survives a client upgrade; the HASSH value will not.

The prefixes are descriptive, not a blocklist

The /20 prefixes under IOCs record where the fleet sat during the observation window. They are consumer broadband and CGNAT mobile allocations: each covers roughly 4,096 addresses, assignment is dynamic, and the overwhelming majority of subscribers inside them had nothing to do with this campaign. A prefix filter would penalise thousands of uninvolved customers to reach a few dozen compromised devices — and would stop matching the fleet as soon as leases rotate. Use the prefixes to understand the shape of the campaign, not to build filtering rules.


IOCs

Fleet distribution over the 2026-05-26 → 2026-06-02 window, aggregated to /20. Per-host addresses are not published — see Data handling below.

/20 prefixOperatorHosts
27.79.0.0/20Viettel Group19
27.79.32.0/20Viettel Group8
116.99.160.0/20VNPT12
116.110.0.0/20Viettel Group7
116.110.16.0/20Viettel Group1
116.110.144.0/20Viettel Group9
116.110.208.0/20Viettel Group9
171.231.176.0/20Viettel Group10
171.231.192.0/20Viettel Group4
171.243.144.0/20Viettel Group9
Total88

The 88 hosts spread across 54 distinct /24 subnets inside those ten /20s — consistent with dynamically assigned consumer addresses rather than a contiguous allocation under single control.

HASSH: fda360b1b4f4d345...
SSH client banner: SSH-2.0-AsyncSSH_2.1.0


Data handling

What is published. Aggregated indicators only: ISP allocations, /20 prefixes with host counts, the HASSH value, the client banner, and the behavioral signature. This is what a defender needs to write a detection rule.

What is not published. The per-host address list. These are residential subscriber connections. The device owners are victims of the compromise described here, not participants in it, and a per-host list paired with a dated observation window is information their network operator can resolve to named subscribers. Prefix aggregation keeps the report operationally useful without carrying that cost. We do not publish hashed addresses either — the IPv4 space is small enough that a hashed address is trivially reversible, so a hash would be a per-host list wearing a disguise.

Available on request. The per-host list is available on request to national CERTs, to the network operators responsible for the allocations above, and to verified incident responders and researchers working a confirmed case, at research@ohiiho.com. We respond to requests; we do not push this data to anyone.

Correction and removal. Requests to correct or remove any indicator in this report go to research@ohiiho.com. We act on a request from the affected network operator without requiring it to be justified.

Retention. The underlying telemetry is kept internally, under restricted access, for as long as it serves research reproducibility and our contractual obligations — an indicator that cannot be re-derived from source data cannot be defended — and is deleted once that purpose ends. We do not claim a fixed statutory period: we document the purpose and the deletion.


Sensor data: HIIH distributed SSH sensor network, 4 regions. Observation window: 2026-05-26 → 2026-06-02. Methodology: passive capture, no active probing.