ted Backdoor: DPRK Weaves an Implant Into Victims' Own HAProxy Builds

·

What happened: Rapid7 Labs disclosed a previously undocumented Linux toolkit — named ted after debug strings left in its binaries — that was compiled directly into the HAProxy load balancers of two South Korean organisations in the automotive and media sectors. Rather than exploiting a HAProxy flaw, the operators recompiled the reverse proxy itself so it doubles as a silent adversary-in-the-middle and command-and-control channel.

Who and why it matters: Rapid7 attributes the activity with medium confidence to North Korea-linked (DPRK) clusters overlapping APT37, Lazarus and Kimsuky tradecraft. Because the trojanised proxy answers C2 requests inline and erases them from HAProxy's own connection counters, neither backend logs nor load-balancer statistics record the operator's traffic — a genuinely novel evasion pattern for edge Linux infrastructure.

Act on this: This is not a patch-and-move-on advisory. The implant reports the same version string as a clean build, so version checks and package auditing will not flag it. Defenders need file-integrity verification against known-good hashes, egress and DNS review for the six img.* C2 domains, and hunts for the specific dropped artefacts and log-scrubbing behaviour detailed below.

◈ Table of Contents

01 Threat Actor Profile 02 Disclosure Timeline 03 Access & Deployment 04 Technical Deep Dive: the Trojanized Proxy 05 Trojanized Binary Family & Persistence 06 curlRAT Companion Implant 07 Anti-Forensics & Log Tampering 08 Indicators of Compromise 09 Detection & Hunt Queries 10 MITRE ATT&CK Mapping 11 Mitigation & Hardening 12 Sources & References
🎯

01 · Threat Actor Profile

DPRK · medium confidence

Rapid7 Labs stops short of a single-group callout. The toolkit's tradecraft — Linux server persistence, patient traffic manipulation, and targeting of South Korean industry — overlaps the broader North Korean (DPRK) ecosystem, and Rapid7 assesses the activity with medium confidence as DPRK-aligned, drawing lines to the APT37, Lazarus and Kimsuky clusters.

AttributeDetail
Implant nameted (from debug strings); HAProxy instance labelled "ted backdoor"
Companion RATcurlRAT
AttributionNorth Korea-linked (DPRK) — medium confidence
Overlapping clustersAPT37 · Lazarus · Kimsuky
Discovered / reported byRapid7 Labs — report published September 4, 2026
Confirmed victims2 organisations, South Korea
Sectors targetedAutomotive · Media
PlatformLinux (edge load balancers / internet-facing infrastructure)
ObjectiveSelective web-traffic interception / page tampering + covert access

The strategic logic fits DPRK cyber-espionage priorities: a compromised media outlet's load balancer is a censorship-grade position for shaping what selected readers see, and an automotive supplier is a long-standing DPRK intellectual-property target. Placing the implant on the reverse proxy — not an endpoint — puts the operator on the exact device that already terminates and inspects everyone's web sessions.

Medium-confidence attribution means the DPRK link is an assessment, not proof. Treat the TTPs and IOCs as the actionable core; do not over-index on a specific group name in reporting to leadership.

🕒

02 · Disclosure Timeline

2024 → 2026
T
Known dated events
Chronology
  • 1Nov 8, 2024 — HAProxy 2.8.12 is released. The implant is built to read this exact release's internal structures, with memory offsets hard-coded to 2.8.12.
  • 2Jul 2, 2025 — Several of the campaign's C2 domain indicators first surface in open threat-intel sources (maltrail / ThreatFox), suggesting infrastructure staging well before disclosure.
  • 3Aug 27, 2026 — HAProxy 2.8.28 ships upstream, underscoring how far behind the pinned 2.8.12 build sits on the victims' proxies.
  • 4Sep 4, 2026 — Rapid7 Labs publishes its analysis of ted and curlRAT, tying the toolkit to two South Korean victims and DPRK-aligned activity. As of that date, all six C2 domains resolve to NXDOMAIN.

The 2.8.12 pin plus mid-2025 infrastructure staging implies dwell time measured in many months. Scope any confirmed compromise as long-dwell, not a smash-and-grab.

🚪

03 · Access & Deployment

Post-compromise implant

The single most important framing point: ted is not a HAProxy vulnerability. There is no CVE to patch here. The implant is a post-exploitation payload — installing it presupposes the operator already has code execution on the host and the ability to replace the running binary. The value is in what the operator does after access: they rebuild the proxy so persistence and C2 live inside a trusted, expected process.

01
Root-gated staging
Delivery

Rapid7 describes a stager that is deliberately conservative about where it fires. It deploys only where HAProxy or cron is already present and verifies root before dropping anything. That targeting discipline both reduces noisy failures and keeps the toolkit off honeypots and mismatched hosts.

Deployment preconditions
  • AExisting code execution on the Linux host (initial access vector not disclosed).
  • BRoot privileges — the stager aborts if it cannot confirm them.
  • CA running HAProxy or cron service to graft persistence onto.
  • DAbility to swap the live binary for the recompiled, backdoored build.

Because deployment requires prior root, a ted detection is also proof of an earlier, unremediated intrusion. Do not close the case at binary removal — hunt for the initial access path.

🔬

04 · Technical Deep Dive: the Trojanized Proxy

Inline C2 + AitM

This is the part that makes ted worth studying. The operators fold a full C2 handler and content-rewriting engine into HAProxy's own request-handling path, so the malicious logic runs at exactly the point where every client session is already being proxied. The recompiled binary behaves as a normal load balancer for ordinary traffic and only switches into implant mode for requests that satisfy a precise set of secret conditions.

Figure — a covert request that clears all four gates is served by the implant and scrubbed from the proxy's own statistics.
01
The magic-path C2 trigger
Activation

A request for a specific image path flips the proxy into C2 mode. To ordinary monitoring this looks like a request for a static asset — exactly the kind of traffic a web front-end sees constantly — which is why the trigger hides in plain sight. Nothing about the request reaches the real backend.

This is classic traffic signalling: the implant listens for a covert pattern inside otherwise-legitimate HTTP rather than opening a new listener or beaconing outbound. No extra port, no obvious anomaly in the netstat table.

02
Four-gate access control
Authentication

Before the implant will act on a triggering request, it enforces four independent checks. Together they ensure only the operator — from expected infrastructure, using the right client fingerprint — can drive the backdoor, and that a curious scanner stumbling onto the image path gets nothing.

#CheckWhat must match
1User-AgentA valid, expected User-Agent header value.
2URL + RefererMatching URL and Referer patterns.
3Client addressWhitelist membership by source address — exact match or /24 CIDR.
4Accept-Language keyAn operator key in the Accept-Language header — this overrides the address filter, letting the operator reach the backdoor from off-whitelist networks.

The Accept-Language override is the hunt-friendly quirk: a legitimate visitor never carries an operator key there. Anomalous Accept-Language values paired with static-image requests are a high-signal pivot.

03
Command channel via named pipe
Execution

When a request clears all four gates, the implant writes the command body to a named pipe under /tmp and returns the resulting output back to the operator on a raw socket, wrapped in a standard HTTP/1.0 200 OK header so the exchange reads as an ordinary successful web response.

Operator capabilities over the channel
  • 1Beacon / check-in.
  • 2Upload and download files.
  • 3Run arbitrary shell commands.
  • 4Replace the implant's own configuration on the fly.
04
Response rewriting & statistics scrubbing
Evasion + AitM

The implant does two evasive things at response time. First, for C2 exchanges it rewrites the content type and content length, forces the response status to 200, and deletes the Accept-Ranges header to stop clients from making byte-range requests that would break the smuggled payload. Second — and this is the standout trick — it decrements HAProxy's live connection counters, removing the operator's requests from the proxy's own statistics.

Because the counters are adjusted and the request never touches the backend, the covert session leaves no trace in either the load balancer's stats page or the backend application logs. Alongside C2, the same inline position lets the operator selectively alter the pages that chosen visitors receive — the adversary-in-the-middle capability that gives the campaign its strategic value against a media target.

Do not rely on HAProxy's stats socket or connection counters as ground truth on a suspect host — the implant is designed specifically to falsify them. Correlate against upstream network flow records instead.

🧩

05 · Trojanized Binary Family & Persistence

5 system binaries

ted is not a single file. Rapid7 found the same implant code reused across several core system binaries, so the operator keeps redundant, mutually-covering footholds even if one is discovered and replaced. Each trojanised binary keeps doing its legitimate job while carrying the backdoor.

Trojanized binaryLegitimate roleMalicious addition
haproxyReverse proxy / load balancerInline C2 handler + AitM page rewriting (Phase 04)
crondCron schedulerPersistence host; legitimate crond overwritten
sshdSSH daemonCaptures plaintext passwords, encrypts them to a fixed path
agettyTTY / login handlerCarries the shared implant code
atdat-job schedulerCarries the shared implant code
polkitdPolicyKit authorization daemonCarries the shared implant code
01
Persistence via crond overwrite & timestamp cloning
Persistence

The implant overwrites the legitimate crond binary and then clones the creation timestamp of /usr/bin/ssh onto it. That timestomping makes the replaced binary look as old as an original system component, defeating the simple "what changed recently?" triage that responders reach for first.

Timestomping copies mtime/ctime but the filesystem's inode change time and package-manager metadata can still betray it. Compare rpm -Va / dpkg --verify output and the on-disk hash against distro packages — not the file date.

02
Credential theft via trojanized sshd
Credential Access

The backdoored sshd intercepts authentication and encrypts captured plaintext passwords to a fixed file path, giving the operator a rolling harvest of valid credentials for lateral movement and re-entry — a hallmark of long-dwell server implants.

Rapid7's reporting associates the artefact path /var/lib/sshd/c8c68e629bba773a10ac80012d10bf19 with this component. Its presence on a host is a strong compromise signal in its own right.

📡

06 · curlRAT Companion Implant

Secondary access
01
Beacon cadence & sandbox awareness
C2

Rapid7 tracks a second implant it calls curlRAT alongside ted. It beacons every 12 hours by default, dropping to a 30-second interval when the operator sets a flag — patient by default, responsive on demand. Critically, curlRAT aborts unless the host shows a virtualization marker file, an inversion of the usual anti-VM check.

BehaviourValue
Default beaconEvery 12 hours
Operator "fast" modeEvery 30 seconds (flag-set)
Execution guardRuns only if a virtualization marker file is present; otherwise aborts

The require-virtualization guard suggests the operators expect their targets to run on virtualised infrastructure and want to avoid firing on unexpected bare-metal or analysis hosts. A tightly-timed 12-hour outbound cadence from a server is itself worth a hunt.

🧹

07 · Anti-Forensics & Log Tampering

Indicator removal

Beyond hiding its C2 in the proxy counters, ted actively scrubs the host's forensic record. It strips a fixed set of keywords from the root user's bash history and from six system logs, quietly deleting the lines most likely to reveal how it was installed and operated.

01
Keyword-based log & history scrubbing
Defense Evasion

The implant removes lines containing the keywords tmp, wget, cron and crond from the root bash history and from six system logs — including auth.log and audit/audit.log. Those keywords map directly to the toolkit's own staging and persistence activity, so the scrub is surgical rather than a blunt log wipe that would itself be suspicious.

A selectively-thinned auth.log or missing audit.log entries around known SSH sessions is a tell. If host logs look "too clean," treat forwarded/central logs as the authoritative copy — the implant cannot reach those after the fact.

Forensic tells this behaviour leaves
  • Gaps in auth.log / audit.log inconsistent with known logins
  • Root bash history missing expected tmp / wget / cron lines
  • Divergence between on-host logs and central SIEM copies
  • crond binary date matching /usr/bin/ssh rather than its package
🧬

08 · Indicators of Compromise

Rapid7 Labs

Defanged for safety. All six C2 domains resolved to NXDOMAIN as of September 4, 2026 — treat them as historical/retrohunt indicators, not live blocks, though revival is trivial for the operator.

TypeIndicator
Domainimg.monderhouse[.]space
Domainimg.smartnords[.]site
Domainimg.darklights[.]store
Domainimg.responsive.pstatic[.]autos
Domainimg.socialteams[.]store
Domainimg.worksongo[.]store
SHA-25672e70936f0dbe459142a1d867617c35f8d0cce5d18c6a49e1090a2a5adc8e558
SHA-2564bb923eb040aa13ca8fd409c31ee4729c60ddff32e350efe1c5a4a9168a065f5
File path~/cache/haproxy-1000.cache
File path/var/lib/sshd/c8c68e629bba773a10ac80012d10bf19
File path/var/lib/snapd/g580
File path/tmp/jasper-log
Host artefactHAProxy instance labelled "ted backdoor"; trojanized crond, agetty, atd, sshd, polkitd

The pstatic lookalike domain (img.responsive.pstatic[.]autos) mimics a well-known South Korean CDN naming convention — consistent with a campaign that wants its C2 domains to blend into a Korean victim's normal image-serving traffic.

🔗
Rapid7 Labs — original ted / curlRAT analysis
Primary source for full IOC set, screenshots and binary detail (link out — not re-hosted)
🔎

09 · Detection & Hunt Queries

KQL · SPL

Because the recompiled HAProxy reports a clean version string and the implant scrubs local logs, detection leans on file-integrity evidence, dropped-artefact paths, and DNS/egress to the C2 domains — captured off-host wherever possible. Queries below assume Microsoft Sentinel / Defender for Endpoint on Linux (KQL) and Splunk with a Linux TA (SPL). Validate field names against your own schema before operationalising.

DETECTS ▸ Creation or presence of ted's known dropped artefact paths across Linux hosts.
KQL — Sentinel / Defender for Endpoint (Linux)
// ted dropped-artefact file paths DeviceFileEvents | where Timestamp > ago(90d) | where FolderPath has_any ( "/var/lib/sshd/c8c68e629bba773a10ac80012d10bf19", "/var/lib/snapd/g580", "/tmp/jasper-log") or FileName == "haproxy-1000.cache" | project Timestamp, DeviceName, ActionType, FolderPath, FileName, InitiatingProcessFileName | order by Timestamp desc
SPL — Splunk (Linux auditd / filesystem)
`# ted dropped-artefact file paths` index=linux (sourcetype=auditd OR sourcetype=linux_secure OR source=*audit*) (path="/var/lib/sshd/c8c68e629bba773a10ac80012d10bf19" OR path="/var/lib/snapd/g580" OR path="/tmp/jasper-log" OR name="haproxy-1000.cache") | stats count min(_time) as first_seen max(_time) as last_seen by host, path | convert ctime(first_seen) ctime(last_seen)
DETECTS ▸ DNS resolution or web egress to the six known ted C2 domains (historical / retrohunt).
KQL — Sentinel (DNS / network events)
// ted C2 domains — retrohunt across DNS + network let c2 = dynamic([ "img.monderhouse.space","img.smartnords.site", "img.darklights.store","img.responsive.pstatic.autos", "img.socialteams.store","img.worksongo.store"]); union DnsEvents, DeviceNetworkEvents | where TimeGenerated > ago(180d) | where Name in~ (c2) or RemoteUrl has_any (c2) | project TimeGenerated, Computer, DeviceName, Name, RemoteUrl, InitiatingProcessFileName
SPL — Splunk (DNS / proxy)
`# ted C2 domains — DNS + proxy egress` index=network (sourcetype=dns OR sourcetype=proxy OR sourcetype=stream:dns) (query="img.monderhouse.space" OR query="img.smartnords.site" OR query="img.darklights.store" OR query="img.responsive.pstatic.autos" OR query="img.socialteams.store" OR query="img.worksongo.store" OR dest_host="*worksongo.store" OR dest_host="*socialteams.store") | stats count values(host) as hosts min(_time) as first by query | convert ctime(first)
DETECTS ▸ Integrity drift on the exact system binaries ted trojanizes — the primary, version-string-proof signal.
KQL — Sentinel (package verification via custom log)
// Ingest `rpm -Va` / `dpkg --verify` output; alert on ted's target binaries PackageVerify_CL | where TimeGenerated > ago(7d) | where FilePath_s has_any ( "/usr/sbin/haproxy","/usr/sbin/crond","/usr/sbin/sshd", "/sbin/agetty","/usr/sbin/atd","/usr/lib/polkit-1/polkitd") | where VerifyFlags_s has_any ("5","md5 mismatch","missing") // 5 = MD5/hash changed | project TimeGenerated, Computer, FilePath_s, VerifyFlags_s
SPL — Splunk (package verification)
`# Integrity drift on ted-targeted binaries (rpm -Va / dpkg --verify feed)` index=linux sourcetype=package_verify (file="/usr/sbin/haproxy" OR file="/usr/sbin/crond" OR file="/usr/sbin/sshd" OR file="/sbin/agetty" OR file="/usr/sbin/atd" OR file="*polkitd") (verify_flags="*5*" OR status="changed" OR status="missing") | table _time host file verify_flags status
DETECTS ▸ Anomalous static-image requests carrying operator-key patterns in Accept-Language — the four-gate C2 quirk.
KQL — Sentinel (HAProxy / web access logs)
// Image-path requests with rare Accept-Language + referer mismatch HAProxyAccess_CL | where TimeGenerated > ago(30d) | where UrlPath_s matches regex @"\.(png|jpe?g|gif|webp)$" | where isnotempty(AcceptLanguage_s) | summarize hits=count() by AcceptLanguage_s, UserAgent_s, SrcIp_s | where hits < 5 // rare header combos on image requests = pivot | order by hits asc
SPL — Splunk (web access logs)
`# Rare Accept-Language on static-image requests` index=web (sourcetype=haproxy OR sourcetype=access_combined) uri_path="*.png" OR uri_path="*.jpg" OR uri_path="*.gif" OR uri_path="*.webp" | stats count by http_accept_language, http_user_agent, src_ip | where count < 5 | sort + count

The Accept-Language hunt is heuristic and will produce noise on genuinely diverse audiences. Use it to pivot onto suspicious source IPs, then confirm with binary integrity and artefact-path evidence — never alert on it alone.

🗺

10 · MITRE ATT&CK Mapping

Enterprise
TacticTechniqueIDHow ted uses it
PersistenceCompromise Host Software BinaryT1554Recompiled haproxy, crond, sshd, agetty, atd, polkitd (assessed from behaviour)
Command & ControlTraffic SignalingT1205Magic image-path request triggers C2 mode inline (assessed from behaviour)
Defense EvasionMasqueradingT1036C2 disguised as ordinary HTTP image traffic; forced 200 responses
Defense EvasionIndicator RemovalT1070Scrubs bash history + six logs; decrements HAProxy connection counters; timestomps crond
Credential AccessModify Authentication ProcessT1556Trojanized sshd captures and encrypts plaintext passwords
DiscoverySystem Owner/User DiscoveryT1033Cited in Rapid7 analysis
DiscoveryProcess DiscoveryT1057Cited in Rapid7 analysis

T1036, T1070, T1556, T1033 and T1057 are drawn from Rapid7's analysis; T1554 and T1205 are CyberHawk assessments mapped directly to the trojanized-binary and magic-request behaviours described in the report.

🛡

11 · Mitigation & Hardening

Response actions
🔏

Verify, don't trust versions

Hash internet-facing haproxy, sshd, crond, agetty, atd and polkitd against distro packages (rpm -Va, dpkg --verify) or a known-good gold image. Version strings lie here.

🧾

Forward logs off-host

Ship auth.log and auditd to a central SIEM in real time. The implant scrubs local copies but cannot reach forwarded records after the fact.

🌐

Egress + DNS control

Alert on the six img.* C2 domains and constrain outbound from edge appliances. A load balancer beaconing outbound is abnormal.

📡

Trust upstream flow, not the proxy

The implant falsifies HAProxy's counters. Use netflow / span-port records upstream of the proxy as your source of truth for its traffic.

🔁

Rebuild, don't clean

A host with root-level trojanized system binaries should be re-provisioned from trusted media, not surgically cleaned. Rotate all credentials that touched it.

🕳

Hunt the initial access

ted deployment requires prior root. Its presence proves an earlier intrusion — trace how the operator first landed and close that door.

Response is complete when
  • All six trojanized binary types are confirmed replaced with verified-clean packages or the host is rebuilt
  • Dropped artefacts (sshd hash file, snapd/g580, jasper-log, haproxy-1000.cache) are removed and IR-imaged first
  • Credentials exposed to the host — SSH keys, service accounts, passwords — are rotated
  • C2 domains are blocked/monitored and retrohunted across 180 days of DNS + web logs
  • Initial access vector is identified and remediated; central logs confirm no further beaconing
📚

12 · Sources & References

Primary + corroborating
Rapid7 Labs — ted backdoor & curlRAT analysis (primary research, published Sep 4, 2026) The Hacker News — "New Ted Backdoor Hides Inside Victims' Own HAProxy Builds to Intercept Web Traffic" HAProxy — official project (version reference: 2.8.12 / current 2.8.28) MITRE ATT&CK — technique reference (T1554, T1205, T1036, T1070, T1556, T1033, T1057)

◈ Check your edge before it checks you

Run the ted domains and file hashes through the CyberHawk IOC Scanner, then pressure-test your Linux edge with the detection queries above. For more DPRK and supply-chain implant breakdowns, follow the CyberHawk Threat Intel feed and the CyberHawk Blog.

◈ Stay Connected

Follow CyberHawk Threat Intel for threat intelligence, deployment guides and hands-on SOC tooling content.

🌐 Website ▶️ YouTube ▶️ YouTube (2) 𝕏 Twitter / X ♪ TikTok ✈️ Telegram
🔍 IOC Scanner 🛠️ Live Tools 📚 Courses 🚨 Threat Intel 📝 Blog 📋 SOPs

"They can't exploit you if you are the Exploit."