跳转到帖子

国际威胁情报动态|XZ Utils 供应链后门复盘与 SSH 主机核查指南

精选回复

发布于

背景

2024 年 3 月 29 日,XZ Utils 5.6.0、5.6.1 上游发布包被确认植入供应链后门,对应 CVE-2024-3094。该事件的关键点并不是 xz 命令本身可被远程利用,而是恶意构建逻辑能够生成被篡改的 liblzma。在部分基于 glibc、x86_64,并采用特定 Debian/RPM 构建流程的 Linux 环境中,sshd 可能经由 libsystemd 间接加载该库,从而影响 SSH 认证路径。

后门在进入多数稳定版仓库前被发现,实际暴露面主要集中在当时使用滚动、测试或开发仓库的系统。不过,对授权渗透测试和企业应急排查而言,不能只根据“生产系统通常不会安装测试包”直接排除风险,还要核对软件来源、版本、构建信息和进程实际加载状态。

以下操作用于已获授权的资产核查和事件响应,不包含后门触发或利用步骤。生产环境执行降级、重启前,应先完成证据保全和业务影响评估。

问题定位:先区分版本命中与实际暴露

排查时建议把结论分为三层:

  • 软件层:是否安装 xz/liblzma 5.6.0 或 5.6.1,包来自哪个仓库,是否存在本地编译或手工覆盖。
  • 加载层:当前 sshd 是否直接或间接加载 liblzma,磁盘文件与进程映射是否一致。
  • 行为层:SSH 服务是否出现异常认证、未知子进程、可疑出站连接或权限边界被突破的迹象。

仅执行 xz --version 不够。xz 可执行文件、liblzma 动态库以及包管理器记录可能并不一致,容器、chroot、手工安装和未重启进程也会造成误判。

技术分析:后门如何进入 SSH 链路

公开分析显示,恶意内容主要存在于特定上游 release tarball,而不是简单地以明文后门代码出现在正常源码树中。构建期间,经过混淆的测试文件和脚本会参与生成被修改的 liblzma。

在部分发行版架构中,调用链大致为:sshd 加载 libsystemd,libsystemd 再依赖 liblzma。被修改的 liblzma 可对进程中的特定函数调用路径进行干预。公开逆向结果普遍将其风险指向 SSH 认证绕过及潜在远程代码执行,因此一旦触发,攻击者可能直接跨越普通账户边界,进入高权限 sshd 进程上下文。

在内网攻防链路中,这类入口的后续影响通常包括读取主机私钥和部署凭据、访问 SSH Agent 或自动化配置、窃取服务账号令牌,以及利用管理网连通性横向移动。即使没有发现明确登录日志,也不能排除风险,因为被篡改的是认证链路本身,常规 auth.log 未必完整反映异常行为。

操作步骤一:资产与软件包核查

下面的命令可在授权主机上收集基础信息。建议将输出重定向到只读取证目录,并额外记录主机时间、时区和命令执行人员。

set -u

printf '=== host ===\n'
date -u
uname -a
cat /etc/os-release 2>/dev/null

printf '=== xz runtime version ===\n'
command -v xz && xz --version

printf '=== Debian package records ===\n'
if command -v dpkg-query >/dev/null; then
  dpkg-query -W -f='${Package}\t${Version}\t${Architecture}\n' \
    xz-utils liblzma5 2>/dev/null
  apt-cache policy xz-utils liblzma5 2>/dev/null
  dpkg -V xz-utils liblzma5 2>/dev/null
fi

printf '=== RPM package records ===\n'
if command -v rpm >/dev/null; then
  rpm -q xz xz-libs --qf '%{NAME}\t%{EPOCHNUM}:%{VERSION}-%{RELEASE}\t%{ARCH}\t%{VENDOR}\n' 2>/dev/null
  rpm -V xz xz-libs 2>/dev/null
fi

printf '=== discovered libraries ===\n'
ldconfig -p 2>/dev/null | grep -E 'liblzma|libsystemd'
find /usr /lib /lib64 -xdev -type f \
  -name 'liblzma.so*' -print 2>/dev/null

如果版本命中 5.6.0 或 5.6.1,应继续确认发行版公告和包的完整版本号。部分厂商可能通过发行号回移补丁,因此不能只比较上游版本字符串;相反,来源不明的 5.4.x 也不能因为版本较低就直接视为可信。

dpkg -V 或 rpm -V 出现差异时,需要判断是合法配置变更、更新残留,还是磁盘文件已偏离软件包清单。对 liblzma 这类库文件出现摘要、大小或符号链接异常,应提升事件等级。

操作步骤二:确认 sshd 的依赖和进程映射

printf '=== sshd file dependencies ===\n'
SSHD_BIN=$(command -v sshd 2>/dev/null || printf '/usr/sbin/sshd')
printf 'sshd=%s\n' "$SSHD_BIN"
ldd "$SSHD_BIN" 2>/dev/null | grep -E 'liblzma|libsystemd' || true
readelf -d "$SSHD_BIN" 2>/dev/null | grep NEEDED || true

printf '=== running sshd mappings ===\n'
for pid in $(pgrep -x sshd 2>/dev/null); do
  printf '%s\n' "--- PID $pid ---"
  grep -E 'liblzma|libsystemd' "/proc/$pid/maps" 2>/dev/null || true
done

printf '=== hashes of mapped liblzma files ===\n'
for pid in $(pgrep -x sshd 2>/dev/null); do
  awk '/liblzma/{print $6}' "/proc/$pid/maps" 2>/dev/null
done | sort -u | while read -r file; do
  test -f "$file" && sha256sum "$file"
done

检查结果需要结合发行版设计解释。sshd 未直接显示 liblzma,不代表不存在间接依赖;应同时查看 libsystemd 和运行进程的 /proc/PID/maps。反过来,加载 liblzma 也不等于已经中招,仍需核对库文件来自哪个包、包是否由可信仓库签名以及摘要是否匹配厂商清单。

若磁盘上的库已更新,但 sshd 进程映射仍指向旧 inode 或已删除文件,说明旧代码可能仍驻留内存。此时不能只看当前文件哈希,应保留进程映射信息,并在完成取证后重启服务或整机。

操作步骤三:日志与行为侧排查

常规 SSH 日志仍有价值,重点关注事件窗口内的异常来源、认证方式变化、短会话、高权限账户登录以及登录后立即启动的未知进程。

printf '=== SSH service logs ===\n'
journalctl --utc --since '2024-03-01' \
  -u ssh -u sshd --no-pager 2>/dev/null | tail -n 500

printf '=== authentication records ===\n'
grep -Eh 'Accepted|Failed|Invalid user|session opened|session closed' \
  /var/log/auth.log* /var/log/secure* 2>/dev/null | tail -n 500

printf '=== recent privileged logins ===\n'
last -Fai 2>/dev/null | head -n 100
lastlog 2>/dev/null | head -n 100

printf '=== sshd children and network state ===\n'
ps -eo pid,ppid,user,lstart,args --forest | grep -E '[s]shd|[s]sh '
ss -tpna 2>/dev/null | grep -E 'sshd|:22 ' || true

printf '=== audit records, if auditd is enabled ===\n'
command -v ausearch >/dev/null && \
  ausearch -x sshd -ts recent -i 2>/dev/null | tail -n 300

日志检索时间应按组织首次引入相关软件包的时间确定,而不是机械地从漏洞公开日期开始。若软件仓库、CI 镜像或开发机曾同步测试版包,还应检查以下位置:

  • 代理、防火墙和流量传感器中的 22/TCP 来源与出站连接。
  • 堡垒机命令审计、身份平台登录记录和 MFA 事件。
  • 软件仓库同步日志、镜像构建记录、SBOM 和制品哈希。
  • authorized_keys、sudoers、systemd unit、cron、shell profile 的变更历史。
  • 云环境中的实例角色调用、密钥访问及安全组变更。

需要注意,未发现 Accepted 登录记录不能作为排除依据。更可靠的做法是把主机日志、网络流量和身份系统记录按 UTC 时间线合并,寻找 sshd 进程派生异常命令、登录来源与资产用途不匹配、认证失败后突然出现高权限会话等关联信号。

权限边界与内网影响判断

确认主机曾运行可疑 liblzma 后,不应只处理单台 SSH 服务。应建立以该主机为起点的凭据和信任关系清单:

  • 主机上是否保存运维私钥、Git 部署密钥、云访问令牌或配置中心凭据。
  • root 或服务账号能否免密访问其他服务器。
  • 该主机是否位于管理 VLAN,能否连接数据库、虚拟化平台或域控。
  • CI/CD 账号是否允许修改制品、部署任务或软件仓库。
  • 是否存在共享 SSH Host CA、用户 CA 或通配证书。

如果答案涉及高权限或广泛横向访问,应按照“主机身份已失陷”处理,而不是仅替换 liblzma。尤其不要在疑似失陷主机上生成新密钥或直接登录其他服务器,否则可能再次暴露凭据。

风险处置与修复建议

  • 先隔离:限制主机出入站访问,保留管理取证通道,避免直接关机导致内存和进程信息丢失。
  • 再取证:保存包数据库、库文件哈希、/proc/PID/maps、SSH 日志、网络连接和时间线。证据文件应写入外部可信存储并计算摘要。
  • 使用厂商仓库修复:确认候选包已由发行版公告标记为安全,再执行升级、降级或 distro-sync。不要从论坛附件或未知镜像下载所谓修复包。
  • 清除驻留代码:修复磁盘文件后重启 sshd;若主机曾运行命中版本且暴露于不可信网络,优先从可信镜像重建整机。
  • 轮换凭据:在干净终端上撤销并更新主机私钥、运维密钥、部署令牌、云凭据和相关证书。先封堵访问路径,再进行轮换。
  • 扩大狩猎:依据 SSH 信任关系、管理网访问和 CI/CD 权限检查相邻资产,而不是只扫描相同版本号。

修复前可先查看候选版本,避免在仓库尚未同步安全包时盲目重装:

# Debian/Ubuntu 系列:先确认 Candidate 来源与发行版安全公告一致
apt-cache policy xz-utils liblzma5

# RPM 系列:检查仓库提供版本和软件包签名
rpm -qi xz xz-libs 2>/dev/null
dnf --showduplicates list xz xz-libs 2>/dev/null
rpm -K /var/cache/dnf/*/packages/xz-libs-*.rpm 2>/dev/null

# 修复完成后重新确认进程实际加载的库
systemctl restart sshd 2>/dev/null || systemctl restart ssh
for pid in $(pgrep -x sshd); do
  grep liblzma /proc/$pid/maps 2>/dev/null
done

生产环境执行 systemctl restart 前,应确认现有管理会话、带外控制台和 SSH 配置有效,防止修复过程中失联。对于高风险命中主机,服务重启只解决内存中旧库的问题,不能证明攻击者未建立其他持久化。

长期防护建议

  • 生产软件源与 testing、unstable、rawhide 等仓库严格隔离,禁止临时混源后不恢复。
  • 在资产平台记录包来源、签名、完整版本和镜像摘要,避免只采集 xz --version。
  • 对基础库升级建立灰度流程,监控 sshd、sudo、systemd 等高权限进程的依赖变化。
  • 为软件仓库和构建系统保留可检索日志,确保能回答“哪些镜像在什么时间引入了哪个包”。
  • 限制 SSH 管理面来源,启用堡垒机、短期证书和分级管理网络,减少单点失陷后的横向范围。
  • 将主机日志发送到远端不可篡改存储,并结合网络侧元数据进行检测。

总结

CVE-2024-3094 的现实价值在于提醒防守方:供应链事件不能只靠版本扫描闭环。有效核查需要同时验证软件包来源、动态依赖、运行进程映射、认证日志和内网信任关系。若主机曾实际加载可疑库,应按高权限入口失陷评估,完成隔离、取证、可信重建和凭据轮换,而不是仅执行一次软件降级。

服务器与云环境安全示意图
服务器、云资产与权限边界梳理示意
安全事件影响分析示意图
安全动态、影响面和处置建议示意

这次核查不要只看 xz --version。CVE-2024-3094 主要涉及上游发布的 5.6.0/5.6.1 tarball,是否真正可利用还取决于发行版构建方式、架构,以及 sshd 进程是否间接加载了对应的 liblzma。发行版回补后的同版本包也可能是安全的,最终应以包来源、构建版本和厂商公告为准。

建议先做三层确认:

# 基础信息
uname -a
uname -m
xz --version

# Debian/Ubuntu
dpkg-query -W xz-utils liblzma5 openssh-server libsystemd0 2>/dev/null
apt-cache policy xz-utils liblzma5

# RPM 系
rpm -q xz xz-libs openssh-server systemd
rpm -qi xz-libs

其次检查运行中的 SSH 进程,而不只是磁盘上的二进制:

pid=$(systemctl show sshd.service -p MainPID --value 2>/dev/null)
[ -z "$pid" ] || [ "$pid" = 0 ] && pid=$(pgrep -o sshd)

grep -E 'liblzma|libsystemd' /proc/"$pid"/maps 2>/dev/null
readlink -f /proc/"$pid"/exe
ldd /usr/sbin/sshd | grep -E 'lzma|systemd'

ldd 没看到 liblzma 不能单独判定安全,因为部分环境是经其他库间接加载;以 /proc/$pid/maps 中实际映射的库文件为准。找到路径后再校验包归属和完整性:

# Debian/Ubuntu
dpkg -S /usr/lib/x86_64-linux-gnu/liblzma.so.5
dpkg -V xz-utils liblzma5

# RPM 系
rpm -qf /usr/lib64/liblzma.so.5
rpm -V xz xz-libs

如果命中风险版本,优先使用发行版仓库提供的已修复包或降级包,不建议临时从第三方下载单个 liblzma.so 替换。更新后需要重启 sshd,更稳妥的是整机重启,否则旧库可能仍驻留在进程内存中:

# RPM 系示例,具体版本以发行版公告为准
dnf downgrade xz xz-libs
systemctl restart sshd

# 确认重启后已不再映射旧文件
pid=$(pgrep -o sshd)
grep liblzma /proc/"$pid"/maps

日志侧可围绕受影响包安装时间建立窗口,重点核查异常来源地址、非预期成功登录、密钥和账户变更:

journalctl -u sshd --since '2024-03-20' --no-pager
journalctl -u ssh  --since '2024-03-20' --no-pager
grep -hE 'Accepted|Failed|Invalid user' /var/log/auth.log* /var/log/secure* 2>/dev/null
last -ai
find /root /home -path '*/.ssh/authorized_keys' -type f -printf '%TY-%Tm-%Td %TT %p\n' 2>/dev/null
getent passwd | awk -F: '$3 == 0 {print}'

需要注意,普通 SSH 日志中没有异常并不能排除风险,这类后门位于认证链路较前的位置。若主机曾实际加载可疑库,建议同时保留包文件、进程映射、认证日志、网络流量和磁盘镜像;在有控制台或带外管理的前提下先限制 SSH 暴露面,再进行降级和凭据轮换。单纯以“登录延迟变高”作为 IOC 误报会比较多,不适合直接批量下结论。

最近浏览 0

  • 没有会员查看此页面。