"ted backdoor" and curlRAT, a DPRK-nexus actor recompiles a victim's own HAProxy source tree to hide C2 inside the load balancer's self-reported connection statistics
Rapid7 finds a DPRK-nexus implant that falsifies HAProxy's own traffic counters so its command-and-control never appears in the load balancer's own logs
Analysis
Rapid7 Labs documents a previously undocumented Linux espionage toolkit deployed against two South Korean automotive- and media-sector organizations, active since at least early 2025. Rather than exploiting a HAProxy vulnerability, the operators obtained code execution on the host by some other route and recompiled the victim's own HAProxy 2.8.12 source tree to embed a custom filter plugin (internally named ted_plugin, left in debug strings as "ted backdoor") that hooks HAProxy's native HTTP parser, memory-pool allocator and event scheduler (Rapid7 Labs, 2026-09-03). Because it is compiled into the load balancer's own binary rather than exploiting a flaw in it, the technique defeats vulnerability scanning and version-string checks outright: a recompiled binary still reports the same version string as a clean build (The Hacker News, 2026-09-04).
The filter's defining trick is anti-forensic self-falsification. After every command-and-control exchange, it reaches into HAProxy's own internal counters (using hardcoded struct offsets specific to build 2.8.12) and decrements the per-backend connection counts (beconn/feconn), the global active-connection count (actconn), and cumulative traffic fields (cum_conn, cum_req, bytes_in, bytes_out), so the C2 traffic that passed through the load balancer never appears in its own self-reported statistics or logs (Rapid7 Labs, 2026-09-03). A request to one hardcoded static-asset-style path switches the filter into C2 mode (beacon, file upload/download, shell command execution, configuration update) while outside that mode it can passively capture session cookies and selected HTTP headers, or, when several conditions match (a specific User-Agent pattern, a payload-path selector byte, a URL/referer regex, and either IP allow/deny-list membership or an operator key smuggled in the Accept-Language header that overrides IP filtering), substitute or append attacker content into the HTTP response body via HAProxy's own body-editing callbacks while rewriting Content-Type/Content-Length and stripping Accept-Ranges so the size change goes unnoticed by the client.
A companion RAT, curlRAT (named for its libcurl-based networking, distinct from the unrelated CurlBack RAT attributed to the Pakistan-linked SideCopy group), is compiled into trojanized replacements of crond, agetty, atd and polkitd (Rapid7 Labs, 2026-09-03). It polls a hardcoded C2 over HTTPS (with an HTTP fallback) every 12 hours by default, or every 30 seconds in an operator-set fast-poll mode, decoding tasking through a Base64-plus-rolling-XOR pipeline, and offers command execution, file transfer, an interactive PTY/reverse shell that escalates to full root privilege before handoff, and a watchdog thread that first checks for the presence of a specific virtualization-driver file before activating, sleeping and aborting if the host does not look virtualized, an anti-analysis check against sandboxed detonation; before reporting HAProxy's running/stopped/restarted state back to the operator every hour (Rapid7 Labs, 2026-09-03). If its primary C2 host fails configuration validation, curlRAT falls back to a second hardcoded server, and it derives a per-victim tracking identifier from a hash of host-specific values (hostname, IP address, hardware UUID and a cron-version string) letting the operator distinguish individual infected hosts across a botnet-style deployment rather than relying on a random or sequential ID (Rapid7 Labs, 2026-09-03). A stager component deploys only when HAProxy or cron are already present, verifies root, overwrites the legitimate crond binary in place, timestomps the replacement to match another system binary's own creation time, and scrubs the keywords tmp/wget/cron/crond from root's bash history and six system logs including auth.log and audit/audit.log, staged through a file named to resemble a JSP engine artifact (Rapid7 Labs, 2026-09-03). A separately trojanized sshd intercepts plaintext credentials into an encrypted log file for later retrieval (Rapid7 Labs, 2026-09-03).
Rapid7 could not establish the initial-access vector with certainty, but notes both victims ran an exposed groupware login portal and mail server on the same edge host; a plausible entry point Rapid7 says is consistent with documented Kimsuky tradecraft against Korean groupware vendors (Rapid7 Labs, 2026-09-03). The watering-hole delivery model otherwise overlaps Kaspersky's Operation SyncHole (November 2024–February 2025), which Kaspersky attributed to Lazarus; Rapid7 explicitly notes APT37 and Lazarus are organizationally distinct DPRK clusters operating under different agencies, so the toolkit's attribution rests on three only partially reconciled threads (APT37 via C2 infrastructure, Lazarus via the delivery model, Kimsuky via the initial-access hypothesis) rather than a single confirmed cluster (Rapid7 Labs, 2026-09-03).
Triage: a legitimate in-house HAProxy Lua or filter module can also hook the HTTP parser and modify response bodies, so that alone is not the signal. The discriminating feature this mechanism supports is that no operationally normal filter module needs to actively decrement or zero HAProxy's own connection or traffic counters, any module observed doing so, rather than only reading them, warrants immediate investigation.
Cited evidence
The toolkit is attributed with medium confidence to DPRK APTs, given that the attacks Rapid7 observed were targeting South Korean media and automotive sectors, likely aiming at long-term espionage, the usage of simple xor-based encryption, custom substitution cipher, and the list of C2s hardcoded is associated to APT37 by ThreatFox and maltrail.
First, it reaches into HAProxy's internal counters to decrement active connection stats, referencing fields from the proxy struct via hardcoded 2.8.12 offsets to clear any trace left: the per-backend beconn/feconn and the global actconn, then 64-bit fields within be_counters (cum_conn, cum_req, bytes_in, bytes_out) guarded against underflow, and 32-bit peak metrics (sps_max, conn_max, cps_max) decremented only when exactly 1.
It is not a HAProxy vulnerability, and installing it requires code execution on the host and the ability to replace the running binary.
Sources2
AI-generated · no human review · this permalink is the shareable record for the finding · verify operationally critical claims against the linked primary source.