安全事故与漏洞
Log4Shell(CVE-2021-44228)——让全世界一夜之间为『不知道自己是否在用』的漏洞而战栗的一天
2021 年 12 月,Java 的日志输出库 Log4j 中发现了最高等级(CVSS 10.0)的远程代码执行漏洞。其恐怖的本质在于『即使你没有直接使用,也会经由另一个库被卷入其中』的传递性依赖。本文用图解、时间线,以及 SBOM、依赖的机器化监控、迅速打补丁这些至今依然有效的教训,配合图与表为你梳理。
回顾过去的重大事件,不去复现攻击,而是聚焦于『对当下你的运维真正有用的教训』。
发生了什么——『被动的处理』成了攻击通道
Log4j 是承担日志输出这一极其常见处理的库,在 Java 世界里几乎无处不在。问题在于,这个库会把日志所含字符串中的特定写法解释为『引用外部进行解析』的功能,结果导致执行由外部指定的代码。
也就是说,攻击者只需在『会被记入日志的位置』(用户名、HTTP 头等)放入经过构造的字符串,就有可能在服务器端导致代码执行。日志输出这一『被动的处理』竟然成了攻击通道,其冲击是巨大的。
为什么回答不出『我们没事吧?』
许多应用没有印象自己直接引入过 Log4j。是框架或 SDK 在内部使用了它——这正是传递性依赖(transitive dependency)。依赖的依赖,再往下还有依赖。如果手里没有自己的『物料清单』,连是否受影响都无从判断。
最可怕的是『无法掌握』
在『不知道是否在用』的状态下,连处置的优先级都无从排定。是否掌握自己的物料清单(SBOM),决定了那一夜的成败。
时间线
2021-12-09〜10
漏洞被广泛知晓,全世界一齐奔走确认『我们是否受影响』。紧随其后
紧急打补丁与临时缓解措施陆续展开。攻击尝试也急剧增多。此后
修补此前修复不足的后续 CVE 接连公布。『修过一次』并没有就此结束。
至今依然有效的教训
拥有 SBOM(物料清单)
把自己的应用在内部使用了什么可视化出来。用 npm ls / 锁文件 / SBOM 生成工具掌握『实际在运行的依赖』。只看『直接引入的东西』是不够的。
用机器监控依赖
在 CVE 公布的那一刻,自动判定是否受影响(Dependabot / osv-scanner)。能连同传递性依赖一起检查,正是机器监控的强项。靠人工巡查必然会有遗漏。
加快打补丁的运维
为了在紧急时刻能跑通『立刻升级、验证、上线』,平时就要练好更新的『肌肉』。也请参阅 依赖跟进的机制。
追踪后续 CVE
Log4Shell 之后,对修复的再修复出现了多次。不要在『修过一次』就收手,要一直追到后续报道。
接下来阅读
FAQ
QLog4Shell『新』在哪里、为何如此可怕?
它在全球范围内让人直面了传递性依赖(transitive dependency)的恐怖:『即使你没有印象自己直接引入过,它也在另一个库内部被使用着,并且存在漏洞』。如果不掌握自己的 SBOM(物料清单),连是否受影响都无从判断。
Q为什么日志输出会成为攻击通道?
因为 Log4j 把日志字符串中的特定写法当作『引用外部进行解析』的功能来解释。攻击者只需在会被记入日志的位置(用户名、HTTP 头等)放入经过构造的字符串即可,本应是被动的日志输出由此变成了执行通道。
Q怎样才能不重蹈覆辙?
三点:①用机器监控依赖(Dependabot/osv-scanner),自动检测对应的 CVE;②生成 SBOM,把『自己在用什么』可视化;③建立迅速打补丁的运维机制。追踪后续 CVE(对修复的再修复)同样重要。