Ted Backdoor & curlRAT: Trojanized HAProxy Load-Balancer Toolkit

Linux edge-device implant compiled into HAProxy 2.8.12, paired with trojanized crond/sshd/agetty/atd/polkitd and a curl-based RAT. Reported by Rapid7 Labs, 2026-09-04. Medium-confidence DPRK attribution (APT37 / Lazarus / Kimsuky tooling overlap).
Threat
Ted backdoor + curlRAT
Severity
NATION-STATE
Type
Linux edge implant / backdoor
Access
Load-balancer + system-daemon compromise
Version
v0.1 · 2026-09-13
Author
HuntPack
Confidence
Medium (attribution) / High (technical findings)
01

Executive Summary

Rapid7 Labs documented a previously undocumented Linux toolkit at two South Korean organizations (automotive, media) in which a custom backdoor, internally referred to as "ted" from debug strings left in the binary, is compiled directly into the victims' own HAProxy 2.8.12 source tree as a native filter-API plugin. It is not a separate process bolted onto HAProxy; it rides HAProxy's own memory pools, event scheduler, and process-management infrastructure, so ordinary load-balancing continues to work while the implant intercepts decrypted HTTP traffic underneath it.

The attacker's objective is threefold: (1) a self-erasing command-and-control channel triggered by a request for a specific fake image path, with commands relayed through a named pipe and the triggering request scrubbed from HAProxy's own connection counters and logs before it ever reaches the backend; (2) a watering-hole capability that selectively rewrites or swaps page content for visitors matched by IP, User-Agent, referer, or a credential smuggled in the Accept-Language header; and (3) long-term persistence and credential theft via trojanized replacements of crond, sshd, agetty, atd, and polkitd, including an SSH keylogger and a companion beacon, curlRAT.

The single highest-value defensive angle is that this implant's entire design goal is making the load balancer's own logs and counters lie. Any hunt or control that depends solely on HAProxy's own logging, access logs, or connection statistics will not see it. Effective detection has to come from independent telemetry: EDR-visible process and file-write events on the underlying Linux host, binary integrity/hash verification, and out-of-band network egress monitoring, none of which the implant is documented to tamper with.

Defender priority: treat every internet-facing HAProxy (or any edge component doing SSL termination and traffic routing) with the same binary-integrity and EDR coverage as an application server. A load balancer that is only monitored through its own logs cannot be trusted to report its own compromise.
02

Source Review & Web Hunter Notes

TierSourceKey FindingCarry Forward
1Rapid7 Labs (primary research)Original technical report: ted backdoor architecture, curlRAT, SSH keylogger, timestomping, log/history scrubbing, stager behavior, attribution reasoningYes
2The Hacker NewsJournalistic synthesis of the Rapid7 report; consolidated IOC list (domains, hashes, file paths) and confirmed all six C2 domains were NXDOMAIN as of publicationYes
2Security AffairsExtended verbatim quotes from the Rapid7 report; confirms C2 trigger endpoint, Accept-Language operator credential, Accept-Ranges header deletion, connection-counter scrubbingYes
3GBHackersIndependent summary; corroborates hash 72e70936…, adds two additional hashes (94630b96…, a8bfab4d…) and the "Ricochet Chollima" APT37 aliasPartial (see hash confidence note below)
3hendryadrian.com (Rapid7 report mirror)Confirms timestomping detail, log-scrubbing keyword list, and file artifact paths; introduces one hash (5db1b6d5…) not seen elsewherePartial (see hash confidence note below)

Web Hunter Decisions

Hash confidence tiering. Five distinct SHA-256 values surfaced across the five sources above. Three are corroborated by two or more independently-fetched snapshots (72e70936…, 4bb923eb…, 94630b96…) and are shipped as high-confidence. Two appear in only a single snapshot each (a8bfab4d… in GBHackers only, 5db1b6d5… in the hendryadrian mirror only) and are shipped as single-source/lower-confidence rather than silently dropped or silently trusted: both are still traceable to a saved snapshot, not invented, so they ship with an honest confidence label instead.

No hostile or injected content encountered. All five fetched sources returned ordinary journalistic/technical reporting. None contained instructions directed at the research agent, no prompt-injection attempts, and no request to fetch additional URLs, change output paths, or skip pipeline steps. All five are retained as legitimate citations.

Unconfirmed detail flagged, not shipped as fact. The task brief's claim that curlRAT "aborts on non-virtualized hosts" is confirmed verbatim in the Rapid7 source (it refuses to run unless it detects virtualization signatures, consistent with confirming deployment onto the intended cloud/VM-hosted production infrastructure rather than a bare-metal analysis box). This is stated accurately in Section 6 below rather than assumed to mean conventional sandbox-evasion (which is normally the inverse check).

03

Hunt Brief & Attack Chain

Hunt Hypotheses

  1. H1 (high conf). A host runs a HAProxy, crond, sshd, agetty, atd, or polkitd binary whose SHA-256 matches a known ted/curlRAT sample.
  2. H2 (high conf, FP medium). The HAProxy process itself spawns a shell or network utility as a child process, which a load balancer has no legitimate reason to do outside of a configured external-check script.
  3. H3 (medium conf). A named pipe matching the pattern /tmp/t[ID]_w.pipe is created by a process whose parent is haproxy, consistent with the documented ted_make_pipe_name / ted_create_multi_pipe_file command-relay mechanism.
  4. H4 (high conf, perishable). A host resolves one of the six documented C2 domains. All six were NXDOMAIN as of 2026-09-04, so this is a retrospective/historical-log hunt, not a live-detection control.
  5. H5 (medium conf, FP medium). A cron/at/getty/polkit daemon image makes an outbound network connection directly, which none of these programs do as part of normal operation.
  6. H6 (medium conf). A process executes from one of the documented non-standard artifact paths (/var/lib/snapd/g580, /tmp/jasper-log), consistent with the stager's root-verification / OS-fingerprinting step before dropping the toolkit.
  7. H7 (high conf). A file write occurs at one of the four documented artifact paths (cache file, SSH-keylogger output, stager drop paths).
  8. H8 (high conf, requires log ingestion). HAProxy's own access log records a request for the specific fake image path used to trigger C2 mode. Because the implant is documented to scrub this from HAProxy's live counters and connection logs, this only works against out-of-band-shipped logs (e.g. a syslog/Filebeat forwarder that ships the line before ted can erase it, or an upstream WAF/CDN log that never passed through the compromised HAProxy at all).

Attack Chain

StepTelemetryHunt Angle
1. Initial access (assessed, not directly confirmed by Rapid7's public writeup)Web/mail server access logs, WAF logsOut of scope for this pack; see Gap note in Section 15
2. Root-verifying stager profiles host, drops toolkit, verifies rootProcess execution from non-standard pathsH6 / Q6
3. HAProxy binary replaced with ted-compiled build; crond/sshd/agetty/atd/polkitd replacedProcess execution, file writes, known-bad hashH1 / Q1, H7 / Q7
4. Indicator removal: crond timestomped to /usr/bin/ssh's creation time; auth.log/audit.log/bash_history keyword-scrubbedFile metadata, log integrityNative hunts, Section 7 (no reliable CQL equivalent)
5. Operator sends trigger request for the fake image path; ted enters C2 mode via named pipeHAProxy access log (out-of-band), named pipe creationH8 / Q8, H3 / Q3
6. Operator executes commands, harvests cookies/credentials, selectively rewrites pages for chosen visitorsNot independently visible to endpoint EDR (in-process HAProxy filter logic)GAP: see Section 15
7. curlRAT beacons out (12h default / 30s fast-poll) from trojanized daemons; SSH keylogger captures plaintext passwordsNetwork connections from daemon images, DNS requestsH5 / Q5, H4 / Q4
04

Consolidated IOC Table

TypeValueConfidenceActionContextExpiry
sha25672e70936f0dbe459142a1d867617c35f8d0cce5d18c6a49e1090a2a5adc8e558highdetectted backdoor sample; corroborated by 3 independent snapshots2027-03-13
sha2564bb923eb040aa13ca8fd409c31ee4729c60ddff32e350efe1c5a4a9168a065f5highdetectted backdoor sample; corroborated by 2 independent snapshots, matches task-brief intel2027-03-13
sha25694630b96f628c96a6bff7904b40ffc9ad67c86f8a4ff6080c3b524831c93f402highdetectted backdoor sample; corroborated by 2 independent snapshots (Rapid7 direct + GBHackers)2027-03-13
sha256a8bfab4de81a1acb04aacdf757346946b0f5e30f0c9f402004016d0e425119c7lowhuntsingle-source (GBHackers only); ship as hunt-only, not auto-block, until corroborated2026-12-13
sha2565db1b6d52faf60b4f32d6fd0c7c938e4d05d29a14c32ded4a9668357c08b6a91lowhuntsingle-source (hendryadrian mirror only); ship as hunt-only, not auto-block, until corroborated2026-12-13
domainimg.monderhouse.spacemediumhuntted C2; NXDOMAIN as of 2026-09-04, retrospective log value only2026-12-13
domainimg.smartnords.sitemediumhuntted C2; NXDOMAIN as of 2026-09-04, retrospective log value only2026-12-13
domainimg.darklights.storemediumhuntted C2; NXDOMAIN as of 2026-09-04, retrospective log value only2026-12-13
domainimg.responsive.pstatic.autosmediumhuntted C2; NXDOMAIN as of 2026-09-04, retrospective log value only2026-12-13
domainimg.socialteams.storemediumhuntted C2; NXDOMAIN as of 2026-09-04, retrospective log value only2026-12-13
domainimg.worksongo.storemediumhuntted C2; NXDOMAIN as of 2026-09-04, retrospective log value only2026-12-13
filename~/cache/haproxy-1000.cachehighhuntted configuration cache file2026-12-13
filename/var/lib/sshd/c8c68e629bba773a10ac80012d10bf19highhuntSSH keylogger encrypted credential output2026-12-13
filename/var/lib/snapd/g580highhuntstager / toolkit drop artifact2026-12-13
filename/tmp/jasper-loghighhunttoolkit artifact / HAProxy cache reference2026-12-13
url/favorite_list_2x_m500_ico.jpghighhuntC2 activation trigger endpoint; requires HAProxy access-log ingestion to see, since ted scrubs it from live counters/logs2026-12-13
pattern/tmp/t[ID]_w.pipe (e.g. /tmp/t4471_w.pipe)mediumhuntnamed-pipe command-relay naming convention (ted_make_pipe_name / ted_create_multi_pipe_file); [ID] varies per connection, not an exact-match indicator2026-12-13
behavioralhaproxy, crond, sshd, agetty, atd, polkitd binaries replaced/trojanizedhighhuntpersistence mechanism across six system binaries2026-12-13

The named-pipe pattern is not shipped in the machine-readable IOC appendix (Section 10) as an exact-match value because [ID] varies per HAProxy connection; it is hunted via a wildcard query (Q3) instead of an import-ready atomic indicator.

05

Affected Surface & Telemetry Matrix

SurfaceRequired TelemetryPriorityGap Risk
Internet-facing HAProxy / load-balancer hostsFalcon Linux sensor (process, file, network) + HAProxy access/error logs ingested to NGSIEMCriticalHigh: the implant erases its own traces from HAProxy's own logs and connection counters, so log-only monitoring is blind to the C2 channel itself
System daemons (crond, sshd, agetty, atd, polkitd)Falcon Linux sensor process + file-write telemetryCriticalMedium: detection depends on known-bad hash or a file-integrity baseline; a newly recompiled sample defeats hash-only detection
DNS resolution / egressDNS request telemetry, egress firewall/proxy logsHighMedium: the known C2 domains are NXDOMAIN as of 2026-09-04; live value is retrohunt only, not real-time blocking
SSH authenticationFalcon Linux sensor UserLogon/UserLogoff, auth.log via NGSIEMHighHigh: the trojanized sshd captures credentials at the application layer, below where normal auth-success/failure logging would show anything unusual
Root filesystem / binary integrityFile-integrity monitoring (AIDE) or package-manager verification baselineHighMedium: most Linux estates do not run FIM by default; without a pre-established baseline, integrity checks have nothing to compare against
06

ATT&CK Mapping

TacticTechnique IDTechnique NameObserved Behavior
Initial AccessT1190Exploit Public-Facing ApplicationRapid7 assesses (not independently confirmed in the public writeup) likely initial entry via an externally accessible Groupware or mail portal; treated here as an operational assumption, not a confirmed fact
Persistence / Defense EvasionT1554Compromise Client Software BinaryHAProxy, crond, sshd, agetty, atd, and polkitd binaries replaced with trojanized builds that retain original functionality
Defense EvasionT1070.006Indicator Removal: TimestompTrojanized crond binary given the same creation timestamp as /usr/bin/ssh
Defense EvasionT1070.002Indicator Removal: Clear Linux or Mac System LogsKeywords tmp, wget, cron, crond stripped from /var/log/messages, audit/audit.log, cmd.log, secure, syslog, auth.log
Defense EvasionT1070.003Indicator Removal: Clear Command HistorySame keyword set stripped from /root/.bash_history
Defense EvasionT1027Obfuscated Files or InformationTed configuration protected with chained XOR plus a monoalphabetic substitution cipher; C2 traffic uses feedback XOR with Base64 encoding
Credential AccessT1556Modify Authentication ProcessTrojanized sshd captures plaintext passwords at authentication time, encrypts them with a custom substitution cipher, and writes them to a fixed path
Command and ControlT1071.001Application Layer Protocol: Web ProtocolsC2 responses disguised as standard HTTP/1.0 200 OK traffic; curlRAT beacons every 12 hours by default, or every 30 seconds in operator-enabled fast-poll mode
Command and ControlT1205Traffic SignalingA request for a specific non-existent image path (/favorite_list_2x_m500_ico.jpg) silently switches the HAProxy filter into C2 mode
CollectionT1557Adversary-in-the-MiddleTed hooks HAProxy's HTTP parsing to inspect decrypted traffic before it reaches backend services, harvesting cookies, headers, and selectively injecting or swapping page content for chosen visitors
DiscoveryT1082System Information DiscoveryStager profiles hostname, OS distribution, and version before installing the toolkit, and verifies root privileges first
Defense EvasionT1497.001Virtualization/Sandbox Evasion: System CheckscurlRAT checks for virtualization signatures and refuses to run if it does not find them, consistent with confirming deployment onto the intended cloud/VM-hosted production host rather than a bare-metal analysis environment (the inverse of the more common sandbox-evasion direction)
07

Native Audit-Log Hunts

These checks have no reliable CQL equivalent (file birth-time comparison and log-content-gap detection are not standard EDR event fields) and are run directly on the host or via auditd.

1. Timestomp check: crond birth time vs. /usr/bin/ssh

stat --format='%W %n' /usr/sbin/crond /usr/bin/ssh 2>/dev/null
# Note: %W (birth/creation time) returns 0 on filesystems/tools that do not expose
# it. Where that happens, use a forensic tool that reads the statx btime field, or
# debugfs -R 'stat <inode>' /dev/<device> on ext4. Flag any host where crond's
# birth time exactly equals ssh's birth time to the second.

2. Log / history tamper detection via auditctl

auditctl -w /root/.bash_history -p wa -k ted_history_tamper
auditctl -w /var/log/auth.log -p wa -k ted_log_tamper
auditctl -w /var/log/audit/audit.log -p wa -k ted_log_tamper
# Alert on any write to these paths from a process other than the expected
# logging daemon (rsyslogd, auditd itself, or the shell's own history-append).

3. Root-verifying stager / OS-fingerprint sequence

Look for a short-lived process reading /etc/os-release, hostname, and CPU/hypervisor identification (/proc/cpuinfo, dmidecode, systemd-detect-virt) in quick succession, immediately followed by a new file write to /var/lib/snapd/g580 or /tmp/jasper-log. See Q6/Q7 in Section 8 for the EDR-side correlation of the resulting artifacts.

4. Live named-pipe enumeration

find /tmp -type p -name 't*_w.pipe' -newer /var/log/wtmp
# Any FIFO matching this naming convention under /tmp is worth immediate
# investigation regardless of age; the -newer filter is a triage convenience,
# not a requirement.
08

CrowdStrike LogScale CQL Hunt Queries

Pick your tenant's cloud first: every "Open in Falcon" button below uses this selection.
Q1 · Known-Bad Hash Execution: Trojanized System Daemon
CONF HIGHFP LOWCOST LOW

Looks for: execution of haproxy, crond, sshd, agetty, atd, or polkitd whose SHA-256 matches a documented ted/curlRAT sample. FP: effectively none: an exact hash match on these binary names is not expected to occur benignly.

// HUNT: Known-bad hash execution -- trojanized system daemon
// MITRE: T1554
// CONF: high  FP: low  COST: low
// REQUIRES: Falcon Linux sensor process telemetry (ProcessRollup2 / SyntheticProcessRollup2)
// FALSE POSITIVES: none expected -- these are exact hash matches on named samples
// LOOKBACK: 30d -- set the window with the Falcon time picker
#event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/
| FileName=/^(haproxy|crond|sshd|agetty|atd|polkitd)$/i
| in(SHA256HashData, values=["72e70936f0dbe459142a1d867617c35f8d0cce5d18c6a49e1090a2a5adc8e558","4bb923eb040aa13ca8fd409c31ee4729c60ddff32e350efe1c5a4a9168a065f5","94630b96f628c96a6bff7904b40ffc9ad67c86f8a4ff6080c3b524831c93f402","a8bfab4de81a1acb04aacdf757346946b0f5e30f0c9f402004016d0e425119c7","5db1b6d52faf60b4f32d6fd0c7c938e4d05d29a14c32ded4a9668357c08b6a91"])
| table([@timestamp, aid, ComputerName, FileName, ImageFileName, SHA256HashData, UserName, CommandLine])
Q2 · HAProxy Spawning Shell or Network Utility
CONF HIGHFP MEDIUMCOST LOW

Looks for: a shell or common network/scripting tool spawned directly by haproxy, which a load balancer has no routine reason to do. FP: environments with a configured HAProxy external-check command, or a health-check wrapper script that legitimately shells out, will trigger this.

// HUNT: HAProxy process spawning shell or network utility
// MITRE: T1557, T1071.001
// CONF: high  FP: medium  COST: low
// REQUIRES: Falcon Linux sensor process telemetry with parent/child lineage
// FALSE POSITIVES: configured HAProxy external-check commands or health-check wrapper scripts that shell out legitimately
// TUNING: exclude known-good external-check CommandLine patterns (e.g. your specific health-check script path) by name before promoting this to a blocking Custom IOA
// LOOKBACK: 14d -- set the window with the Falcon time picker
#event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/
| ParentBaseFileName=/^haproxy$/i
| FileName=/^(sh|bash|dash|curl|wget|nc|ncat|socat|python3?|perl|busybox)$/i
| table([@timestamp, aid, ComputerName, ParentBaseFileName, FileName, ImageFileName, CommandLine, UserName])
Q3 · Named-Pipe Command-Relay Pattern (ted C2 channel)
CONF MEDIUMFP LOWCOST LOW

Looks for: a named pipe matching ted's documented /tmp/t[ID]_w.pipe naming convention, opened by a process whose parent is haproxy. FP: low; this naming pattern is not a standard Linux or HAProxy convention. ⚠ Event coverage unverified: validate FIFO/pipe visibility in your tenant Falcon's capture of raw mkfifo() calls on Linux is not independently confirmed against the vendor data dictionary for this pack; treat this as a starting point and confirm against a live tenant before relying on it alone.

// HUNT: Named pipe command-relay pattern consistent with ted backdoor
// MITRE: T1071.001, T1205
// CONF: medium  FP: low  COST: low
// REQUIRES: Falcon Linux file-open telemetry (FileOpenInfo) -- Field/event unverified, validate in tenant
// FALSE POSITIVES: none expected from this naming pattern under normal HAProxy operation
// LOOKBACK: 14d -- set the window with the Falcon time picker
#event_simpleName=/FileOpenInfo/
| ParentBaseFileName=/^haproxy$/i
| TargetFileName = "*/tmp/t*_w.pipe"
| table([@timestamp, aid, ComputerName, ParentBaseFileName, TargetFileName, UserName])
Q4 · DNS Resolution to Known ted/curlRAT C2 Domains (retrohunt)
CONF HIGHFP LOWCOST LOW

Looks for: any historical DNS request to the six documented C2 domains. FP: none expected: these are campaign-specific subdomains. Coverage note: all six domains were confirmed NXDOMAIN as of 2026-09-04, so this query has retrospective/historical value only and will not catch a live, ongoing beacon against current infrastructure.

// HUNT: DNS resolution to known ted/curlRAT C2 domains (retrohunt)
// MITRE: T1071.001
// CONF: high  FP: low  COST: low
// REQUIRES: Falcon Linux sensor DNS telemetry (DnsRequest)
// FALSE POSITIVES: none expected; these are campaign-specific subdomains
// LOOKBACK: 90d -- set the window with the Falcon time picker; domains are NXDOMAIN as of 2026-09-04, so this is historical-log value only
#event_simpleName=/DnsRequest/
| DomainName=/^img\.(monderhouse\.space|smartnords\.site|darklights\.store|responsive\.pstatic\.autos|socialteams\.store|worksongo\.store)$/i
| table([@timestamp, aid, ComputerName, DomainName, ContextBaseFileName, UserName])
Q5 · Outbound Network Connection Initiated by a Cron/AT/Getty/Polkit Daemon Image
CONF MEDIUMFP MEDIUMCOST LOW

Looks for: the daemon image itself (not a child it forked) making a direct outbound connection, consistent with curlRAT's beacon riding inside a trojanized crond/atd/agetty/polkitd. FP: some environments configure cron-triggered mail notification (sendmail) or polkit-adjacent directory/LDAP lookups that could appear similar.

// HUNT: Outbound connection initiated directly by cron/at/getty/polkit daemon image
// MITRE: T1071.001, T1554
// CONF: medium  FP: medium  COST: low
// REQUIRES: Falcon Linux sensor network telemetry (NetworkConnectIP4 / NetworkConnectIP6)
// FALSE POSITIVES: cron-triggered mail notifications (sendmail) or polkitd directory/LDAP lookups in some environments
// TUNING: exclude RemoteAddressIP4 values that resolve to your internal mail relay or directory/LDAP servers before treating a hit as C2
// LOOKBACK: 14d -- set the window with the Falcon time picker
#event_simpleName=/NetworkConnectIP4|NetworkConnectIP6/
| ContextBaseFileName=/^(crond|atd|agetty|polkitd)$/i
| table([@timestamp, aid, ComputerName, ContextBaseFileName, RemoteAddressIP4, RemotePort, UserName])
Q6 · Process Execution From Documented Stager Artifact Paths
CONF MEDIUMFP LOWCOST LOW

Looks for: any process executing from the two documented non-standard drop paths. FP: low: these are not standard executable locations for any legitimate package.

// HUNT: Process execution from documented ted/curlRAT stager artifact paths
// MITRE: T1082, T1497.001, T1554
// CONF: medium  FP: low  COST: low
// REQUIRES: Falcon Linux sensor process telemetry (ProcessRollup2 / SyntheticProcessRollup2)
// FALSE POSITIVES: none expected; these paths are not standard executable locations
// LOOKBACK: 30d -- set the window with the Falcon time picker
#event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/
| (ImageFileName = "*/var/lib/snapd/g580" or ImageFileName = "*/tmp/jasper-log")
| table([@timestamp, aid, ComputerName, ImageFileName, CommandLine, UserName])
Q7 · File Write at Documented ted/curlRAT Artifact Paths
CONF HIGHFP LOWCOST LOW

Looks for: creation of any of the four documented artifact files (config cache, SSH-keylogger output, stager drops). FP: none expected; these are highly specific, non-standard paths.

// HUNT: File write at documented ted/curlRAT artifact paths
// MITRE: T1554, T1556
// CONF: high  FP: low  COST: low
// REQUIRES: Falcon Linux sensor file-write telemetry (NewExecutableWritten / ELFFileWritten / FileOpenInfo)
// FALSE POSITIVES: none expected; these are highly specific non-standard paths
// LOOKBACK: 30d -- set the window with the Falcon time picker
#event_simpleName=/NewExecutableWritten|ELFFileWritten|FileOpenInfo/
| (TargetFileName = "*/cache/haproxy-1000.cache" or TargetFileName = "*/var/lib/sshd/c8c68e629bba773a10ac80012d10bf19" or TargetFileName = "*/var/lib/snapd/g580" or TargetFileName = "*/tmp/jasper-log")
| table([@timestamp, aid, ComputerName, TargetFileName, ContextBaseFileName, UserName])
Q8 · HAProxy Access Log Request for the ted C2 Trigger Endpoint (log source, not endpoint sensor)
CONF HIGHFP LOWCOST MEDIUM

Looks for: a request for the specific fake image path that switches ted into C2 mode. FP: none expected: this is not a real asset path on any legitimate site. Coverage note: this only works against logs shipped out-of-band (e.g. a forwarder that ships the access-log line before ted can scrub it, or an upstream WAF/CDN that never passed through the compromised HAProxy). If the only log source is the compromised HAProxy's own live output, this query will typically return nothing, by design of the implant. Field names below are illustrative for a generic parsed-access-log schema; adjust to match your actual ingested field names.

// HUNT: HAProxy access log request for ted C2 trigger endpoint
// MITRE: T1205, T1071.001
// CONF: high  FP: low  COST: medium
// REQUIRES: HAProxy access logs ingested into Falcon Next-Gen SIEM via a log connector (NOT Falcon endpoint sensor telemetry) -- Field unverified, validate in tenant against your parser's actual field names
// FALSE POSITIVES: none expected; this is not a real asset path
// LOOKBACK: 90d -- set the window with the Falcon time picker
#repo = "haproxy_access_logs"
| url = "*/favorite_list_2x_m500_ico.jpg*"
| table([@timestamp, client_ip, http_user_agent, http_referer, url, status])
09

CrowdStrike Custom IOA Recommendations

IOA CandidateSource QueryPatternExclusionsDeployment Path
Known-bad hash execution: system daemonQ1FileName matches system-daemon basenames AND SHA256HashData in known-bad setNone knownPromote directly to a Custom IOA in prevention mode; low FP, high specificity
Process execution from stager artifact pathsQ6ImageFileName under /var/lib/snapd/g580 or /tmp/jasper-logNone knownPromote to detect-mode Custom IOA; monitor for 2 weeks before considering prevent-mode
File write at artifact pathsQ7New executable/file write matching the four documented pathsNone knownPromote to detect-mode Custom IOA
HAProxy spawning shell/network toolQ2ParentBaseFileName=haproxy AND FileName in shell/net-tool setConfigured external-check / health-check wrapper scripts: allowlist by CommandLine before promotingKeep as investigate-only hunt query until the environment's legitimate external-check commands are enumerated and excluded
Daemon-initiated outbound connectionQ5ContextBaseFileName in cron/at/getty/polkit set making a network connectionInternal mail relay / directory-LDAP destinationsInvestigate-only; FP profile needs a baseline period per environment before any promotion
10

Machine-Readable IOC Appendix

Falcon IOC Management CSVbulk import
type,value,action,severity,expiration,description,tags
sha256,72e70936f0dbe459142a1d867617c35f8d0cce5d18c6a49e1090a2a5adc8e558,detect,critical,2027-03-13,ted backdoor sample,campaign:Ted-HAProxy
sha256,4bb923eb040aa13ca8fd409c31ee4729c60ddff32e350efe1c5a4a9168a065f5,detect,critical,2027-03-13,ted backdoor sample,campaign:Ted-HAProxy
sha256,94630b96f628c96a6bff7904b40ffc9ad67c86f8a4ff6080c3b524831c93f402,detect,critical,2027-03-13,ted backdoor sample,campaign:Ted-HAProxy
sha256,a8bfab4de81a1acb04aacdf757346946b0f5e30f0c9f402004016d0e425119c7,hunt,high,2026-12-13,ted backdoor sample -- single-source (GBHackers),campaign:Ted-HAProxy
sha256,5db1b6d52faf60b4f32d6fd0c7c938e4d05d29a14c32ded4a9668357c08b6a91,hunt,high,2026-12-13,ted backdoor sample -- single-source (hendryadrian mirror),campaign:Ted-HAProxy
domain,img.monderhouse.space,hunt,medium,2026-12-13,ted C2 -- NXDOMAIN as of 2026-09-04,campaign:Ted-HAProxy
domain,img.smartnords.site,hunt,medium,2026-12-13,ted C2 -- NXDOMAIN as of 2026-09-04,campaign:Ted-HAProxy
domain,img.darklights.store,hunt,medium,2026-12-13,ted C2 -- NXDOMAIN as of 2026-09-04,campaign:Ted-HAProxy
domain,img.responsive.pstatic.autos,hunt,medium,2026-12-13,ted C2 -- NXDOMAIN as of 2026-09-04,campaign:Ted-HAProxy
domain,img.socialteams.store,hunt,medium,2026-12-13,ted C2 -- NXDOMAIN as of 2026-09-04,campaign:Ted-HAProxy
domain,img.worksongo.store,hunt,medium,2026-12-13,ted C2 -- NXDOMAIN as of 2026-09-04,campaign:Ted-HAProxy
filename,~/cache/haproxy-1000.cache,hunt,high,2026-12-13,ted configuration cache file,campaign:Ted-HAProxy
filename,/var/lib/sshd/c8c68e629bba773a10ac80012d10bf19,hunt,high,2026-12-13,SSH keylogger encrypted output,campaign:Ted-HAProxy
filename,/var/lib/snapd/g580,hunt,high,2026-12-13,stager drop artifact,campaign:Ted-HAProxy
filename,/tmp/jasper-log,hunt,high,2026-12-13,toolkit artifact,campaign:Ted-HAProxy
url,/favorite_list_2x_m500_ico.jpg,hunt,high,2026-12-13,C2 activation trigger endpoint,campaign:Ted-HAProxy
Behavioral Signatureshunt heuristics
# Not atomic indicators -- behavioral patterns to hunt, see Section 8 for full CQL
haproxy parent process spawning: sh, bash, dash, curl, wget, nc, ncat, socat, python, perl, busybox
named pipe pattern under /tmp: t[ID]_w.pipe  (e.g. /tmp/t4471_w.pipe)
cron/at/getty/polkit daemon image initiating outbound network connection directly
process executing from: /var/lib/snapd/g580, /tmp/jasper-log
crond binary creation timestamp exactly matching /usr/bin/ssh creation timestamp
Named Malware / Toolingattribution context
ted backdoor      -- custom HAProxy filter-API plugin, compiled into HAProxy 2.8.12
curlRAT           -- companion RAT embedded in trojanized crond/atd/agetty/polkitd
SSH keylogger     -- trojanized sshd, plaintext password capture, substitution-cipher encrypted
Attribution: medium confidence, DPRK state-sponsored
  Clusters cited: APT37 (aka Ricochet Chollima), Lazarus Group, Kimsuky
  Basis: South Korean targeting, XOR/substitution cipher usage, APT37-linked infra,
  watering-hole delivery pattern; Rapid7 explicitly states further evidence is
  needed for a stronger linkage (ngx_* routine naming overlap with a Funnull/nginx
  backdoor is noted but not treated as significant code-level overlap)
Binary Integrity / Egress Audit Checklisthost verification
# Run on every host running HAProxy or any of: crond, sshd, agetty, atd, polkitd
debsums -c haproxy openssh-server cron util-linux polkitd   # Debian/Ubuntu
rpm -V haproxy openssh-server cronie util-linux polkit       # RHEL/CentOS/Rocky
sha256sum /usr/sbin/haproxy /usr/sbin/crond /usr/sbin/sshd /sbin/agetty /usr/sbin/atd /usr/lib/polkit-1/polkitd
stat --format='%W %n' /usr/sbin/crond /usr/bin/ssh
find /tmp -type p -name 't*_w.pipe'
11

Detection Validation Gates

GateRequirementStatus Guidance
Telemetry readyFalcon Linux sensor deployed and reporting ProcessRollup2, file-write, network, and DNS events on every HAProxy and system-daemon host in scopeConfirm sensor coverage before trusting a zero-hit result on Q1/Q2/Q6/Q7
Benign baselineRun Q2 and Q5 for at least 14 days in investigate-only mode to characterize normal external-check and cron-notification behavior in this environmentDo not promote to prevention mode until the exclusion list in Section 9 is populated from real baseline data
Positive testConfirm Q1 fires against a deliberately-labeled test file carrying one of the known-bad hashes in a lab/sandbox host (never on production)Validates the query actually executes and the hash comparison syntax is correct in your tenant
Promotion criteriaZero false positives over the baseline period for Q1, Q6, Q7 before enabling prevention mode; Q2 and Q5 remain investigate-only until an environment-specific exclusion list existsSee Section 9 for per-query promotion guidance

See Section 15 for the full Detection Coverage Map, including attack-chain steps this pack does not cover.

12

Hardening: Tiered

Immediate (this week)

1. Verify binary integrity of HAProxy and the five system daemons against package-manager checksums (M1022 Restrict File and Directory Permissions, M1047 Audit). Authority: CIS Distribution Independent Linux Benchmark, "Filesystem Integrity Checking" control family; DISA Red Hat Enterprise Linux STIG, file-integrity verification requirements. Run debsums -c / rpm -V across the fleet (see Section 10 audit checklist). Read-only check, no deployment risk.

2. Capture a SHA-256 baseline of the live haproxy/crond/sshd/agetty/atd/polkitd binaries on every host, stored off-host, so any future silent replacement is detectable (M1047 Audit). Authority: CIS Controls v8, Control 4 (Secure Configuration of Enterprise Assets and Software).

3. Rotate every credential that has ever authenticated over SSH to a HAProxy or edge host in scope, given the documented plaintext-password-capture capability (M1026 Privileged Account Management, M1032 Multi-factor Authentication). Authority: NIST SP 800-63B, credential-compromise response guidance. Treat this as containment, not a config change: see Section 14.

Near term (1–4 weeks)

1. Enforce SSH key-only authentication and disable password auth on all HAProxy/edge hosts (M1043 Credential Access Protection analog for Linux: PasswordAuthentication no). Authority: CIS Distribution Independent Linux Benchmark, "Ensure SSH PasswordAuthentication is disabled"; DISA Red Hat Enterprise Linux STIG, SSH daemon authentication requirements; OpenSSH sshd_config vendor documentation. This directly closes the credential-capture path documented in this campaign, since a trojanized sshd cannot harvest a plaintext password that is never sent.

2. Deploy file-integrity monitoring (AIDE) against the six critical binaries and their containing directories, alerting on any change outside a change-managed maintenance window (M1047 Audit). Authority: CIS Distribution Independent Linux Benchmark, "Ensure AIDE is installed" and "Ensure filesystem integrity is regularly checked".

3. Forward logs off-host in near-real-time (syslog/Filebeat to a central, append-only sink) so on-host log and history scrubbing cannot erase the record before it is captured (M1029 Remote Data Storage, M1047 Audit). Authority: NIST SP 800-92, Guide to Computer Security Log Management; CIS Distribution Independent Linux Benchmark, "Ensure rsyslog is configured to send logs to a remote log host".

4. Enforce egress filtering on edge/load-balancer hosts, default-deny outbound except to explicitly allowlisted backend/management/DNS destinations (M1037 Filter Network Traffic). Authority: NIST SP 800-41 Rev. 1, Guidelines on Firewalls and Firewall Policy; CIS Controls v8, Control 13 (Network Monitoring and Defense). This directly breaks curlRAT's beacon and any DNS lookup to C2 infrastructure.

Strategic (1–3 months)

1. Move to an immutable/read-only-root or golden-image redeploy model for edge load balancers (e.g. a containerized HAProxy pulled from a signed internal registry on every deploy, rather than a long-lived host with an in-place binary) (M1022, M1046 Boot Integrity analog). Authority: CIS Controls v8, Control 4 (Secure Configuration of Enterprise Assets and Software); CIS Docker Benchmark, image-provenance controls where HAProxy is containerized.

2. Network-segment edge/DMZ load balancers from general server egress and from direct SSH management-plane exposure, requiring a bastion/jump host for administrative access (M1030 Network Segmentation, M1035 Limit Access to Resource Over Network). Authority: CIS Controls v8, Control 12 (Network Infrastructure Management); NIST SP 800-207, Zero Trust Architecture, management-plane isolation guidance.

3. Establish a build-provenance program for any internally compiled HAProxy (reproducible builds, binary provenance attestation) so a compile-time trojanization of the kind documented here is independently verifiable against a known-good build artifact (M1045 Code Signing, M1051 Update Software). Authority: NIST SP 800-218, Secure Software Development Framework (SSDF), practices PS.2 and PS.3; SLSA build-provenance levels.

13

Deployable Playbooks

Playbook A: Binary Integrity Verification & Baseline (Immediate)

# Step 1: verify installed package integrity
# Debian/Ubuntu:
debsums -c haproxy openssh-server cron util-linux polkitd 2>&1 | tee /var/log/ted-hunt-debsums.log
# RHEL/CentOS/Rocky:
rpm -V haproxy openssh-server cronie util-linux polkit | tee /var/log/ted-hunt-rpmverify.log

# Step 2: capture current binary hashes for the ongoing baseline
sha256sum /usr/sbin/haproxy /usr/sbin/crond /usr/sbin/sshd /sbin/agetty /usr/sbin/atd /usr/lib/polkit-1/polkitd > /var/log/ted-hunt-binary-hashes.txt

Prerequisites: debsums or rpm package installed; read access to the package database and the listed binary paths (paths vary by distro: adjust to your layout before running at scale). Reboot required: none. Rollback: none required: this is a read-only verification and reporting step.

Playbook B: Egress Filtering for Edge/Load-Balancer Hosts (Immediate/Near term)

nft add table inet ted_hunt_egress
nft add chain inet ted_hunt_egress output { type filter hook output priority 0 \; policy drop \; }
nft add rule inet ted_hunt_egress output ct state established,related accept
nft add rule inet ted_hunt_egress output ip daddr { REPLACE_WITH_BACKEND_CIDR, REPLACE_WITH_MGMT_CIDR } accept
nft add rule inet ted_hunt_egress output udp dport 53 ip daddr REPLACE_WITH_INTERNAL_DNS accept

Prerequisites: nftables installed; a validated list of legitimate backend/management/DNS destinations for this specific host populated into the REPLACE_WITH_ placeholders before deploying: wrong values will break production load balancing. Reboot required: no; rules apply immediately. Persist across reboot with nft list ruleset > /etc/nftables.conf and enable the nftables service. Rollback: nft delete table inet ted_hunt_egress removes the entire policy immediately.

Playbook C: SSH Hardening: Disable Password Authentication (Near term)

# /etc/ssh/sshd_config.d/99-ted-hunt-hardening.conf
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin prohibit-password

# Apply:
sshd -t && systemctl reload sshd

Prerequisites: key-based access already provisioned and tested for every admin and service account that needs to reach this host, before disabling password auth: otherwise you will lock yourself out. Reboot required: no; an sshd reload is sufficient. Rollback: remove /etc/ssh/sshd_config.d/99-ted-hunt-hardening.conf and run systemctl reload sshd.

Playbook D: File Integrity Monitoring via AIDE (Near term)

apt-get install -y aide   # or: yum install -y aide
aideinit
mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db
echo "0 */6 * * * root /usr/bin/aide --check | /usr/bin/mail -s 'AIDE report' REPLACE_WITH_SOC_MAILBOX" > /etc/cron.d/ted-hunt-aide

Prerequisites: the baseline must be captured from a host already verified clean via Playbook A before trusting the AIDE database as a source of truth. Reboot required: no. Rollback: rm /etc/cron.d/ted-hunt-aide stops scheduled checks immediately; removing the aide package itself is optional and non-disruptive.

14

Containment Runbook

PhaseActionsOwnerEvidence to Preserve
1. IsolateNetwork-isolate the affected load balancer(s) via Falcon host containment or an out-of-band edge firewall rule (block all traffic except forensic/management access). Pull the host out of DNS/VIP rotation in favor of a known-clean standby.IR lead + Network teamMemory image of the HAProxy process (e.g. LiME), current iptables/nftables rules, running process list, open files (lsof): captured before any shutdown
2. EradicateRebuild the host from a trusted golden image or verified-clean package repository rather than attempting in-place remediation: the implant is compiled into the binary and process memory, so in-place cleaning cannot be trusted. Rotate every credential that ever authenticated over SSH to the host. Reset any session/auth cookies the load balancer could have harvested for downstream applications.IR lead + System ownersCopy of the trojanized binaries and any recovered artifact files (Section 4) before wipe, for further analysis
3. RecoverRedeploy HAProxy from the verified-clean build pipeline (Playbook A / Strategic tier). Re-enable in DNS/VIP rotation only after the FIM baseline (Playbook D) is clean and egress filtering (Playbook B) is enforced. Add the host to enhanced monitoring for 30 days post-recovery.System owners + SOCPost-recovery binary hashes and AIDE baseline, filed alongside the pre-incident baseline for comparison
15

Detection Coverage Map

TechniqueBehaviorCQLIOACoverage
T1554Trojanized haproxy/crond/sshd/agetty/atd/polkitd binariesQ1, Q6, Q7Q1, Q6, Q7 candidatesGood for known samples; a newly recompiled build defeats hash-only detection
T1557In-process HAProxy filter interception, header/content manipulation, cookie harvestingNoneNoneGAP: not visible to endpoint EDR telemetry; requires network capture, memory forensics, or HAProxy-external traffic comparison
T1070.006 (timestomp)crond timestomped to /usr/bin/ssh's creation timeNative hunt only (Section 7)NonePartial: detectable only via direct host inspection, no streaming EDR event for file birth-time comparison
T1070.002 / T1070.003 (log & history scrubbing)Keyword stripping from auth.log/audit.log/bash_historyNative hunt only (Section 7)NonePartial: requires off-host log forwarding or auditctl watch rules; on-host-only logging is exactly what the implant defeats
T1556Trojanized sshd captures plaintext passwordsQ1 (hash-based), Q7 (keylog artifact path)Q1, Q7 candidatesPartial: a new sshd sample with a different hash and a different output path would evade both queries
T1071.001 / T1205C2 channel disguised as HTTP/1.0, hidden trigger endpoint, curlRAT beaconQ4, Q5, Q8None promotedPartial: Q4's domains are dead (NXDOMAIN), Q8 requires log ingestion that bypasses the implant's own scrubbing; live beacon interval alone (12h/30s) is not independently queryable without a network baseline
T1497.001curlRAT virtualization check / conditional executionNoneNoneGAP: not visible to process/network telemetry; would require behavioral or memory analysis of the RAT binary itself
T1082Stager profiles hostname/OS/root before installQ6 (post-hoc artifact only)Q6 candidatePartial: the profiling activity itself is not distinctly queryable; only its resulting artifact drop is
T1190 (initial access)Assessed Groupware/mail portal exploitationNoneNoneGAP: out of scope for this pack; not independently confirmed in public reporting and no specific CVE or exploit chain was documented to hunt against

Validation gates for the queries above are detailed in Section 11. In short: confirm sensor coverage before trusting a clean result, baseline Q2/Q5 for at least 14 days before any prevention-mode promotion, and re-run the audit checklist in Section 10 fleet-wide as the first action on any new host brought into scope.

16

Hunt Summary Ticket

TITLE:      Ted Backdoor / curlRAT -- Trojanized HAProxy & Linux System Daemon Hunt
SEVERITY:   High (nation-state, medium-confidence DPRK attribution; techniques are
            portable to any HAProxy 2.8.x deployment, not limited to the two
            confirmed South Korean victims)
SCOPE:      Linux hosts running HAProxy (confirmed on 2.8.12) and any host sharing
            the crond/sshd/agetty/atd/polkitd persistence toolkit
HYPOTHESIS: The adversary trojanizes a load balancer's HAProxy binary at compile
            time and replaces core Linux system daemons to gain covert,
            self-erasing C2 and credential capture that never appears in
            application or connection logs.
QUERIES:    Q1-Q8 (Section 8)
DO FIRST:   Run Playbook A (binary integrity verification) against every
            HAProxy/edge host in the estate; run Q1, Q6, and Q7 fleet-wide for
            atomic-IOC and artifact-path hits before anything else.
FINDINGS:   REPLACE_WITH_HUNT_FINDINGS -- populate after hunt execution
GAPS:       No EDR visibility into in-process HAProxy filter/C2 logic (T1557) or
            curlRAT's virtualization check (T1497.001); C2 domains are NXDOMAIN as
            of 2026-09-04 so Q4 is retrospective only; initial-access vector is
            assessed, not confirmed.
ACTIONS:    Escalate any Q1/Q6/Q7 hit as a confirmed compromise; isolate per
            Containment Runbook Phase 1 immediately -- do not attempt in-place
            remediation, the implant is compiled into the binary itself.
OWNER:      REPLACE_WITH_HUNT_OWNER
VERSION:    v0.1 - 2026-09-13
17

Changelog

v0.12026-09-13Initial release. Built from Rapid7 Labs' primary technical report plus four corroborating/independent sources. 8 CQL hunt queries, 8 hunt hypotheses, tiered hardening, 4 deployable playbooks, and a 3-phase containment runbook.
18

References

TierSourceUsed ForAccess Date
1Rapid7 Labs: DPRK APTs: Ted backdoor and curlRAT target South Korean media and automotive sectorsPrimary technical report: architecture, IOCs, timestomping, log scrubbing, attribution2026-09-13
2The Hacker News: New Ted Backdoor Hides Inside Victims' Own HAProxy BuildsIOC consolidation, NXDOMAIN confirmation2026-09-13
2Security Affairs: North Korea-linked Hackers Hide a Backdoor Inside HAProxyExtended verbatim quotes, C2 trigger endpoint confirmation2026-09-13
3GBHackers: DPRK-Linked Hackers Backdoor HAProxy ServersAdditional hash corroboration, APT37/Ricochet Chollima attribution detail2026-09-13
3hendryadrian.com: DPRK APTs: Ted backdoor and curlRAT (Rapid7 report mirror)Timestomping/log-scrub verbatim confirmation, additional hash2026-09-13

Full fetched-text snapshots of all five sources are saved alongside this pack in Ted-HAProxy-Backdoor-Hunt-sources/ for provenance verification.