01 Executive Summary
Between 2026-06-19 and 2026-06-23, the cowrAI honeypot fleet recorded four distinct source IPs
conducting HTTP/2 vulnerability scanning consistent with CVE-2026-23918, an Apache
mod_http2 flaw affecting stream state management. Each scanner sends bursts of
8–9 concurrent HTTP/2 connections, immediately issuing RST_STREAM frames with error code
STREAM_CLOSED (0x5) — a code distinct from the CANCEL (0x8) used
by the 2023-era Rapid Reset attacks. No payloads were delivered; this campaign is pure
reconnaissance / vulnerability enumeration.
RST_STREAM(CANCEL) (CVE-2023-44487) was
observed from three additional IPs (Tencent Cloud, DigitalOcean). These are distinct
from CVE-2026-23918 and documented in the IOC table for completeness.
02 Threat Actor Profile
Infrastructure Characteristics
| IP | ASN / Org | Country | Role | CVE Family |
|---|---|---|---|---|
| 185.65.135.182 | AS39351 31173 Services AB | SE | Blaster | CVE-2026-23918 |
| 103.81.231.93 | AS203020 HostRoyale Technologies | US | Blaster | CVE-2026-23918 |
| 146.70.201.108 | AS9009 M247 Europe SRL | JP | Blaster | CVE-2026-23918 |
| 154.47.29.11 | AS212238 Datacamp Limited | HR | Blaster | CVE-2026-23918 |
| 152.42.217.112 | AS14061 DigitalOcean | SG | Scanner | CVE-2023-44487 |
| 129.226.83.92 | AS132203 Tencent Cloud | SG | Scanner | CVE-2023-44487 |
| 43.128.73.4 | AS132203 Tencent Cloud | SG | Scanner | CVE-2023-44487 |
All CVE-2026-23918 nodes use abuse-tolerant hosting (31173 Services AB, HostRoyale, M247, Datacamp/Datapacket) — a pattern consistent with rented scan infrastructure that prioritises network diversity over persistent IP identity. The CVE-2023-44487 nodes use mainstream cloud (DigitalOcean, Tencent) suggesting compromised instances or a separate operator with different opsec posture.
03 Infrastructure Diagram
04 Technical Analysis
CVE-2026-23918 vs CVE-2023-44487 — Error Code Distinction
The 2023 HTTP/2 Rapid Reset attack (CVE-2023-44487) established a pattern: open a stream
(HEADERS frame), then immediately cancel it (RST_STREAM with error code CANCEL = 0x8)
before the server processes the request. Apache patched this path with rate-limiting on
CANCEL RSTs in mod_http2.
CVE-2026-23918 uses STREAM_CLOSED (0x5) instead. Per RFC 9113, STREAM_CLOSED
indicates "the stream is no longer open." Sending this as a client RST — before the server
has responded — places mod_http2 into an ambiguous state: the stream object was allocated
on receipt of HEADERS, but the client is now telling the server the stream is already closed
from the client's perspective. This bypasses the CANCEL rate-limit codepath and targets a
distinct branch of the stream state machine, likely triggering resource exhaustion or a
use-after-free in stream cleanup.
| Property | CVE-2023-44487 (Rapid Reset) | CVE-2026-23918 (STREAM_CLOSED) |
|---|---|---|
| RST error code | 0x8 CANCEL | 0x5 STREAM_CLOSED |
| Patched rate-limit bypass | No — rate-limited | Yes — different code path |
| Attack vector | Resource exhaustion (CPU) | State confusion + potential UAF |
| Concurrent sessions | Many | 8–9 per wave (lower profile) |
| First seen in fleet | — | 2026-06-19 |
Browser UA Rotation (Anti-Fingerprint)
All CVE-2026-23918 sessions present realistic browser fingerprints with matching
User-Agent and sec-ch-ua headers across three UA profiles,
rotated per session:
| Profile | User-Agent | sec-ch-ua |
|---|---|---|
| Mac Chrome 120 | Mozilla/5.0 (Macintosh…) Chrome/120.0.0.0 | "Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120" |
| Mac Chrome 131 | Mozilla/5.0 (Macintosh…) Chrome/131.0.0.0 | "Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24" |
| Mac Safari 18 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) Version/18.0 Safari/605.1.15 | (absent — Safari does not send sec-ch-ua) |
All profiles use macOS 10_15_7 (Catalina) as the platform string — a fixed anchor across all three UAs, which may be a scanner artefact and an IOC in itself.
Scan Wave Pattern
Each scanner operates in waves: 8–9 connections open concurrently, all originating from a single source port per session. Within each wave, 1–2 "hero" connections send dozens of HEADERS+RST pairs while the remaining connections hold open (1 HEADERS, 1 RST each) — likely testing server-side concurrency limits alongside the RST error path.
Wave timing (154.47.29.11 example — 118 seconds total): 22:05:26 Wave start (probe session) 22:05:42 8 concurrent sessions open simultaneously 22:05:48 9 additional sessions (second burst) 22:05:58 8 additional sessions (third burst) 22:06:36 8 additional sessions (fourth burst) 22:07:09 9 additional sessions (fifth burst) 22:07:24 All sessions closed
05 MITRE ATT&CK Mapping
| ID | Technique | Evidence |
|---|---|---|
| T1595.001 | Active Scanning: Scanning IP Blocks | Multiple scanner IPs hitting different honeypot nodes across the fleet |
| T1595.002 | Active Scanning: Vulnerability Scanning | RST_STREAM(STREAM_CLOSED) pattern targets specific mod_http2 code path |
| T1036 | Masquerading | Rotating legitimate browser UA profiles (Mac Chrome 120/131, Safari 18) with matching sec-ch-ua |
| T1583.003 | Acquire Infrastructure: Virtual Private Server | All nodes on abuse-tolerant VPS providers (Datacamp, M247, HostRoyale, 31173) |
| T1499.003 | Endpoint DoS: Application Exhaustion Flood | High-volume HEADERS+RST bursts targeting mod_http2 stream resource allocation |
06 Campaign Timeline
07 Captured HTTP/2 Frames & Headers
Raw headers captured by apachelure from session 827c9e39955d (154.47.29.11).
Note: :method, :path, :authority pseudo-headers
were not captured in this version of apachelure (fix deployed separately).
--- HTTP/2 Frame Sequence (representative session 827c9e39955d) --- [22:05:42.567] apache.h2_preface ← client magic received [22:05:42.567] apache.h2_frame ← SETTINGS frame [22:05:42.568] cowrie.command.input sec-ch-ua: "Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120" [22:05:42.568] cowrie.command.input user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 Version/18.0 Safari/605.1.15 [22:05:42.569] apache.h2_rst_stream STREAM_CLOSED (0x5) [22:05:43.568] cowrie.command.input sec-ch-ua: "Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120" [22:05:43.569] apache.h2_rst_stream STREAM_CLOSED (0x5) ⋮ (10× RST_STREAM, all STREAM_CLOSED, 13× HEADERS total) [22:05:57.572] apache.h2_session_end ← session closed --- All RST_STREAM errors observed across campaign --- apache:h2_rst_error:STREAM_CLOSED 391 (100% of CVE-2026-23918 RSTs)
08 Indicators of Compromise
CVE-2026-23918 Scanner IPs
| IP | ASN | Country | Sessions | RSTs | First Seen |
|---|---|---|---|---|---|
| 185.65.135.182 | AS39351 31173 Services AB | SE | 54 | 87 | 2026-06-19 |
| 103.81.231.93 | AS203020 HostRoyale Technologies | US | 52 | 89 | 2026-06-20 |
| 146.70.201.108 | AS9009 M247 Europe SRL | JP | 84 | 140 | 2026-06-21 |
| 154.47.29.11 | AS212238 Datacamp Limited | HR | 46 | 75 | 2026-06-23 |
Related CVE-2023-44487 IPs (CANCEL RST — separate campaign)
Behavioral Signatures
| Indicator | Value |
|---|---|
| RST_STREAM error code | 0x5 (STREAM_CLOSED) — all RSTs |
| Concurrent sessions per wave | 8–9 |
| Session duration | ~15 seconds per wave |
| UA platform anchor | macOS 10_15_7 (Catalina) — fixed across all profiles |
| Target port | 443 (TLS only) |
| Protocol | HTTP/2 (h2) — no h2c observed |
| ASNs of interest | AS39351, AS203020, AS9009, AS212238 |
09 Detection Signatures
Suricata — CVE-2026-23918 STREAM_CLOSED Rapid Reset
alert tcp any any -> $HTTP_SERVERS 443 ( msg:"CVE-2026-23918 Apache mod_http2 STREAM_CLOSED Rapid Reset Scan"; flow:established,to_server; content:"|50 52 49 20 2a 20 48 54 54 50 2f 32 2e 30 0d 0a 0d 0a 53 4d 0d 0a 0d 0a|"; comment:"HTTP/2 client magic (PRI * HTTP/2.0)"; threshold:type both, track by_src, count 5, seconds 10; detection_filter:track by_src, count 3, seconds 5; metadata:cve CVE-2026-23918, confidence high; classtype:attempted-dos; sid:9002691801; rev:1; ) # Tighter: STREAM_CLOSED RST (binary RST_STREAM frame with error 0x00000005) alert tcp any any -> $HTTP_SERVERS 443 ( msg:"CVE-2026-23918 RST_STREAM STREAM_CLOSED error in HTTP/2"; flow:established,to_server; content:"|00 00 04 03 00|"; comment:"RST_STREAM frame header (len=4, type=0x3, flags=0x0)"; content:"|00 00 00 05|"; within:4; comment:"error code STREAM_CLOSED = 0x5"; threshold:type both, track by_src, count 8, seconds 30; metadata:cve CVE-2026-23918, confidence high; classtype:attempted-dos; sid:9002691802; rev:1; )
Apache httpd — Rate-limit RST_STREAM(STREAM_CLOSED)
# In httpd.conf or mod_http2 config: H2MaxSessionStreams 20 H2MaxWorkerIdleSeconds 30 H2StreamMaxMemSize 65536 # Monitor: grep "h2_rst_error:STREAM_CLOSED" in cowrie events # or Apache error.log for "RST_STREAM" with status 0x5
Nginx / HAProxy upstream — Mitigation
# Nginx: limit concurrent HTTP/2 streams
http2_max_concurrent_streams 20;
limit_req_zone $binary_remote_addr zone=h2_limit:10m rate=30r/m;
# HAProxy: bind with h2 rate limits
bind :443 ssl crt /etc/ssl/cert.pem alpn h2,http/1.1 \
maxconn 100
10 Collection Methodology
Data collected by the cowrAI honeypot fleet — 36 distributed SSH/Telnet and protocol-lure sensors running on KVM VPS nodes across Cloudzy (Bern/Frankfurt), Vultr, DigitalOcean, Netcup, TeamBlue, and Hetzner. HTTP/2 traffic was captured by apachelure, a custom lure daemon presenting a realistic Apache HTTPS endpoint on port 443 (anchor-tier: deployed to all 36 nodes).
apachelure emits cowrie.command.input events for each captured HTTP header
(service field: apache:h2_header:<name>) and structured events for
HTTP/2 frame-level telemetry (apache.h2_preface, apache.h2_frame,
apache.h2_rst_stream, apache.h2_session_end). All events are
ingested into a PostgreSQL time-series database via the cowrAI ingest pipeline and
cross-referenced against Analytics Engine for fleet-wide aggregation.
:method, :path,
:authority) were not captured in the version of apachelure active during this
campaign. A fix to capture these fields is being deployed fleet-wide as of 2026-06-24.
Future sessions will include full request path telemetry.