供应链攻击检测与应急响应
供应链攻击通过篡改软件的构建、分发、更新环节来植入恶意代码,是最隐蔽的攻击方式之一
关联:06-文件系统取证 | 30-YARA规则
供应链攻击概述
攻击类型分类
| 类型 |
描述 |
经典案例 |
| 软件包投毒 |
在官方/第三方包仓库中植入恶意包 |
event-stream (npm), ua-parser-js |
| 依赖混淆 |
利用同名内部包在公共仓库注册 |
Dependency Confusion (Alex Birsan) |
| 源码篡改 |
直接篡改开源项目代码 |
SolarWinds, codecov |
| 构建环境篡改 |
篡改 CI/CD 管道 |
CircleCI 事件 |
| 镜像投毒 |
篡改 Docker 镜像或系统镜像源 |
Docker Hub 恶意镜像 |
| 二进制篡改 |
替换分发的编译产物 |
CCleaner, ASUS LiveUpdate |
Linux 环境中的主要风险
系统包管理器(apt/yum/dnf)的源被替换或包被篡改
Python pip / Node.js npm / Ruby gem 等语言包管理器
Docker 镜像(基础镜像被篡改)
自编译软件的源码被篡改
CI/CD 流水线中的依赖被注入
系统包完整性校验
Debian/Ubuntu (dpkg/apt)
debsums 校验
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| apt-get install debsums
debsums -c 2>/dev/null
debsums openssh-server debsums coreutils
for pkg in coreutils procps net-tools iproute2 openssh-server; do echo "=== $pkg ===" debsums $pkg 2>/dev/null done
|
dpkg 验证
1 2 3 4 5 6 7 8 9 10 11 12
| dpkg -L openssh-server
apt-key list
cat /etc/apt/sources.list ls -la /etc/apt/sources.list.d/
grep -r "^deb " /etc/apt/sources.list /etc/apt/sources.list.d/ | grep -v "ubuntu.com\|debian.org"
|
RHEL/CentOS (rpm/yum)
rpm -Va 校验
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| rpm -Va
rpm -Va | grep "^S\.5"
rpm -V openssh-server rpm -V coreutils rpm -V procps-ng
|
yum 源检查
1 2 3 4 5 6 7 8 9 10 11
| cat /etc/yum.repos.d/*.repo
yum repolist
rpm -qa gpg-pubkey*
rpm -K /path/to/package.rpm
|
关键二进制文件校验
排查思路
如果攻击者替换了系统命令(如 ls, ps, netstat),那么用这些命令排查就会得到假结果
这就是为什么要先校验工具本身的完整性
手动校验方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
dpkg -V coreutils
rpm -V coreutils
sha256sum /usr/bin/ls sha256sum /usr/bin/ps sha256sum /usr/bin/ss sha256sum /usr/bin/netstat sha256sum /usr/sbin/sshd sha256sum /usr/bin/find sha256sum /usr/bin/lsof
stat /usr/bin/ps stat /usr/bin/ls
file /usr/bin/ps file /usr/bin/ls
|
使用静态编译工具
当怀疑系统工具被替换时,使用静态编译的可信工具
1 2 3 4 5 6 7 8 9
|
busybox ls /tmp/ busybox ps aux busybox netstat -antlp
python3 -c "import os; print(os.listdir('/tmp/'))" python3 -c "import subprocess; print(subprocess.check_output(['cat', '/etc/passwd']).decode())"
|
语言包管理器检测
Python pip
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| pip3 list --format=columns
pip3 show <package_name>
pip3 hash <package_file>.whl
pip3 list | sort
pip3 show -f <package_name>
find / -name "site-packages" -type d 2>/dev/null
|
Node.js npm
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| npm list -g --depth=0
npm ls
npm audit
cat node_modules/<pkg>/package.json | grep -A5 '"scripts"'
find / -name ".npmrc" 2>/dev/null -exec cat {} \;
|
Ruby gem / Go modules
1 2 3 4 5 6
| gem list gem environment
go list -m all
|
Docker 镜像安全检测
镜像检查
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| docker images
docker history <image_name>
docker inspect <image_name> | jq '.[0].Config.Cmd' docker inspect <image_name> | jq '.[0].Config.Entrypoint' docker inspect <image_name> | jq '.[0].Config.Env'
docker export <container_id> > container_fs.tar
docker inspect <image_name> | jq '.[0].RepoDigests'
|
容器运行时检查
1 2 3 4 5 6 7 8 9 10 11
| docker ps -a
docker inspect <container_id> | jq '.[0].Mounts' docker inspect <container_id> | jq '.[0].HostConfig.Privileged' docker inspect <container_id> | jq '.[0].HostConfig.CapAdd'
docker inspect <container_id> | jq '.[0].HostConfig.PidMode' docker inspect <container_id> | jq '.[0].HostConfig.NetworkMode'
|
CI/CD 管道检查
检查构建环境
审查 CI/CD 配置文件:.github/workflows/, .gitlab-ci.yml, Jenkinsfile
检查是否引用了不受信任的 Action/Plugin
检查环境变量中的 secrets 是否泄露
检查构建产物的 hash 是否与预期一致
常见风险
使用 @main 或 @latest 引用(而非固定版本/hash)
在构建过程中执行外部脚本(curl | bash 模式)
构建 Agent 被攻陷
Secrets 在日志中泄露
实战案例
案例:发现被篡改的 sshd
场景:安全审计发现 sshd 文件的 hash 与官方不匹配
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
debsums openssh-server
rpm -V openssh-server
file /usr/sbin/sshd stat /usr/sbin/sshd strings /usr/sbin/sshd | grep -iE "password|log|send|connect"
apt-get download openssh-server dpkg -x openssh-server_*.deb /tmp/orig-ssh/ diff <(md5sum /usr/sbin/sshd) <(md5sum /tmp/orig-ssh/usr/sbin/sshd)
apt-get install --reinstall openssh-server
|
排查清单
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| echo "=== 系统包完整性 ===" if command -v debsums &>/dev/null; then debsums -c 2>/dev/null | head 20 elif command -v rpm &>/dev/null; then rpm -Va 2>/dev/null | grep "^S\.5" | head 20 fi
echo "=== 关键二进制校验 ===" for bin in /usr/bin/ps /usr/bin/ls /usr/bin/ss /usr/sbin/sshd /usr/bin/find; do echo -n "$bin: " file "$bin" | grep -q "ELF" && echo "OK (ELF)" || echo "SUSPICIOUS (not ELF!)" done
echo "=== APT/YUM 源检查 ===" grep -r "^deb " /etc/apt/sources.list /etc/apt/sources.list.d/ 2>/dev/null cat /etc/yum.repos.d/*.repo 2>/dev/null | grep "^baseurl"
echo "=== /etc/ld.so.preload ===" cat /etc/ld.so.preload 2>/dev/null
echo "=== Docker 镜像 ===" docker images --format "{{.Repository}}:{{.Tag}} {{.Size}}" 2>/dev/null
|
实战练习
练习场景
系统中的某个关键二进制文件被替换
使用本页学到的方法发现并恢复
排查步骤
使用 debsums/rpm -Va 发现被修改的文件
使用 file/strings 分析被修改的文件
对比原始版本
恢复并加固