flawopen.com/Incidents/log4shell-jndi-injection-december-2021
●
Apache Software Foundation · CVE-2021-44228 · December 2021 · CVSS 10.0 · 严重
安全研究 · FlawOpen
Log4Shell(CVE-2021-44228):成因与修复
CVE-2021-44228允许日志数据触发Log4j 2查找并通过JNDI加载类。请更新Log4j并盘点所有内嵌副本。[1], [2], [4]
💡 通俗易懂的原理解析 (ELI5)
一间办公室里有个文员,他唯一的工作就是记下访客说的话。有人发现,只要访客说出某句特定的话,文员就会停笔,按那句话里提到的地址过去,从陌生人手里接过一个密封的信封,并照着里面的指示去做。可文员的本职只是做记录而已。[1]
核心概念与专有名词
消息查找- Log4j 2 的一项功能,会在写日志时把消息中的 ${...} 表达式替换成相应的值。在 2.15.0 之前,这不仅作用于配置的格式,也作用于消息里的数据。[1]
JNDI- Java 命名和目录接口,用于在 LDAP 等目录服务中查找对象的 API。向远程服务器发起的 JNDI 查找可能返回一个供 JVM 加载的类。[1]
表达式注入(CWE-917)- 不可信数据到达表达式求值器,作为数据传入的文本被当作指令执行。[1]
传递依赖- 应用只是因为另一个库依赖它才引入的库。许多受 Log4Shell 影响的情况,都来自无人登记的 Log4j 副本。[4]
框架映射
- 本指南所述弱点的 CWE 参考: CWE-20 CWE-502 CWE-917
- D3-OTF 出站流量过滤 — 本指南中的出站网络限制会限制服务或主机可访问的目标。
- CISA KEV — 收录日期 2021-12-10 — CVE-2021-44228
事件演进时间线
2021-11-24
阿里云安全团队的陈兆军私下向 Apache 报告了该漏洞。[1]
2021-12-17
CISA 发布第 22-02 号紧急指令,要求美国联邦机构排查并缓解 Log4j 问题。[3]
2021-12-28
Log4j 2.17.1 修复 CVE-2021-44832,这是 2.15.0 之后三个后续 CVE(另两个为 CVE-2021-45046 和 CVE-2021-45105)中的最后一个。[1]
攻击执行流程分解
源代码对比:漏洞与安全实现
示意性的 Maven 配置。导入 log4j-bom 后,所有 Log4j 模块(包括其他库带进来的副本)都会解析为同一个当前版本。enforcer 规则则会在仍能访问到任何低于 2.17.1 的 log4j-core(包括传递依赖)时让构建失败,这样新的依赖就无法悄悄把有漏洞的代码带回来。升级才是真正的修复;在应用服务器上阻断出站 LDAP 和 RMI,则是纵深防御,即使补丁滞后也能切断利用链。
存在漏洞的实现
<!-- pom.xml: a direct dependency pinned to a vulnerable release -->
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.14.1</version>
</dependency>
</dependencies>
<!-- Nothing stops another library from pulling in an older log4j-core transitively. -->
加固后的安全修复
<!-- pom.xml: one version for every Log4j module, and a build that fails on old ones -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-bom</artifactId>
<version>2.24.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.5.0</version>
<executions>
<execution>
<id>ban-vulnerable-log4j</id>
<goals><goal>enforce</goal></goals>
<configuration>
<rules>
<bannedDependencies>
<searchTransitive>true</searchTransitive>
<excludes>
<exclude>org.apache.logging.log4j:log4j-core:[2.0-beta9,2.17.1)</exclude>
</excludes>
</bannedDependencies>
</rules>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
工程与系统安全加固清单
- ✓把 log4j-core 升级到 2.17.1 或更高版本(Java 7 用 2.12.4,Java 6 用 2.3.2),并让依赖树中任何位置解析出旧版本的构建失败。[1]
- ✓每次构建都生成 SBOM 并与制品一起保存,这样日后出现安全公告时,几分钟内就能对应到受影响的服务。[4], [3]
- ✓扫描已部署的制品,而不只是源码仓库:在很多产品中,经过 shade 或打包的 JAR 让依赖清单里看不到 Log4j。[4]
- ✓对应用服务器默认拒绝出站流量;漏洞利用需要向任意主机发起出站 LDAP、RMI 和 DNS 连接。[4], [3]
- ✓结构性缺陷修复后,要预期还会出现后续 CVE,在厂商修复稳定之前不要关闭事件。[1]