从 SSH 慢半秒到 XZ 后门:如何排查 Linux 供应链异常

2026-07-20 39 预计阅读时间: 1 分钟
来源: oschina.net AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:8 分钟

2024 年 3 月 29 日,微软工程师 Andres Freund 在测试机上发现 SSH 登录比平时慢了约 0.5 秒。这个微小的性能偏差最终指向 XZ Utils 中经过长期策划的后门。事件最值得工程团队记住的,不只是某个压缩库出了问题,而是一次供应链攻击可能先表现为延迟、CPU 占用或调用链变化,而不是清晰的安全告警。

半秒延迟为什么值得追

单次 SSH 登录多出 0.5 秒,通常很容易被归因于网络抖动、DNS、认证服务或机器负载。真正有价值的是把模糊的“变慢了”转化为可重复测量的问题:延迟发生在哪一台机器、哪个进程阶段、升级前后是否一致,以及是否伴随异常 CPU 消耗。

可以这样实践:先对目标主机做多次 SSH 计时,避免根据一次结果下结论。把 HOST 改成测试主机;命令使用非交互模式,不会进入远程 Shell。

#!/usr/bin/env bash
set -euo pipefail

HOST="${1:-localhost}"
RUNS="${RUNS:-10}"

for i in $(seq 1 "$RUNS"); do
  /usr/bin/time -f "run=$i elapsed=%e cpu=%P" \
    ssh -o BatchMode=yes \
        -o ConnectTimeout=5 \
        -o ControlMaster=no \
        "$HOST" true
done

运行方式:

chmod +x measure-ssh.sh
./measure-ssh.sh user@server.example.com

这段脚本不能判断机器是否感染后门。它只能建立基线,并帮助确认延迟是否稳定存在。测试时还要固定网络路径、认证方式和 SSH 配置,否则结果没有可比性。

从应用症状追到动态库

XZ Utils 看起来只是底层压缩工具,但这类基础组件会通过软件包、动态链接和构建流程进入大量 Linux 系统。供应链攻击的危险之处正在于此:业务团队可能从未直接调用某个工具,它仍可能出现在关键进程的依赖路径上。

发现性能偏差后,可以按“进程、系统调用、动态库、软件包来源”的顺序缩小范围。以下命令适合实验机或隔离环境;生产环境运行 strace 会增加开销,应先评估影响。

# 查看本机实际调用的 xz,以及版本输出
command -v xz
xz --version

# 查看 sshd 链接的动态库;不同发行版的 sshd 路径可能不同
SSHD="$(command -v sshd || true)"
if [ -n "$SSHD" ]; then
  ldd "$SSHD"
fi

# Debian/Ubuntu:校验已安装软件包文件
if command -v dpkg >/dev/null 2>&1; then
  dpkg -V xz-utils || true
  apt-cache policy xz-utils
fi

# Fedora/RHEL 系:校验软件包并查看来源
if command -v rpm >/dev/null 2>&1; then
  rpm -V xz || true
  rpm -qi xz
fi

这里要区分三个问题:版本号是否处于发行版公告的影响范围、安装文件是否与包管理器记录一致、软件包本身是否来自可信仓库。dpkg -Vrpm -V 没有报错,只能说明文件与本机软件包元数据相符,不能单独证明上游制品安全。

若要定位 SSH 登录期间的系统调用耗时,可以在授权的测试环境中运行:

sudo strace -ff -tt -T \
  -o /tmp/sshd.trace \
  "$(command -v sshd)" -D -e -p 2222

然后从另一个终端连接测试端口:

ssh -p 2222 localhost true
rg '<[0-9]+\.[0-9]+>' /tmp/sshd.trace* | head -n 50

该示例假设测试机允许启动独立的 sshd,并且配置能够监听 2222 端口。不要直接替换正在提供服务的 SSH 守护进程。

供应链防线不能只盯 CVE

这个事件表明,发现异常的入口可能是性能工程,而确认风险则需要安全、发行版软件包和构建系统的信息共同闭环。只扫描公开漏洞编号往往不够,因为精心设计的攻击可能在被正式识别之前已经进入发布流程。

团队可以把以下控制放进日常工程流程:

  • 记录基础镜像和系统软件包的精确版本,避免构建时无约束地获取“最新版”。
  • 使用发行版签名仓库,并在 CI 中保存锁文件、软件物料清单和镜像摘要。
  • 对 SSH、TLS 终止、身份认证等关键路径建立延迟与 CPU 基线。
  • 将动态库集合和软件包来源纳入主机变更审计。
  • 收到安全公告后优先采用发行版提供的升级或回退方案,不自行猜测一个版本是否安全。
  • 在隔离环境复现异常,保留日志、软件包缓存和磁盘镜像,避免重装导致证据消失。

可以这样为容器镜像生成一份最小软件清单,具体工具可替换为团队现有的 SBOM 方案:

IMAGE="debian:stable-slim"
docker pull "$IMAGE"
docker image inspect "$IMAGE" --format '{{json .RepoDigests}}'
docker run --rm "$IMAGE" sh -c \
  'dpkg-query -W -f="${Package}\t${Version}\n" | sort' \
  > packages.tsv
sha256sum packages.tsv

这份清单不能阻止攻击,但能回答事故处理中最费时间的问题之一:某个时间点部署的镜像究竟包含了什么。

把“感觉不对”变成可验证信号

XZ 事件的起点不是一条完美告警,而是工程师没有忽略半秒钟的偏差。组织不能依赖某个人持续保持这种敏锐度,更可靠的做法是把关键路径基线、软件包溯源、制品校验和异常复现固化进工具链。

落地时应优先选择少量高价值目标:互联网入口、远程管理、认证服务和构建节点。基线过多会制造噪声,自动升级完全放任又会扩大供应链暴露面。合适的平衡点是保留可追溯版本、分阶段发布安全更新,并让性能异常能够自动关联最近的软件包和镜像变更。


相关推荐