Log4Shell 是什么
CVE-2021-44228(业内称 Log4Shell)是 Apache Log4j 2 的远程代码执行问题:当日志内容里出现形如 ${jndi:...} 的表达式时,组件会去执行 JNDI 查询,且默认允许加载远程地址返回的对象,于是任何被记录进日志的用户输入都可能成为触发点。它的影响面之所以大,是因为日志记录几乎无处不在:请求头、参数、用户代理都可能被写入日志,且不需要认证。处置的关键是分清「升级」与「缓解」两种手段的适用版本,并确认所有运行实例都已生效。
基本信息
| CVE 编号 | CVE-2021-44228,同族还有 45046、45105、44832 |
|---|---|
| 影响版本 | Log4j 2.0-beta9 至 2.14.1 |
| 修复版本 | 2.15.0 起步修复主问题,2.16.0 默认关闭 JNDI 并移除消息查找,2.17.x 继续修复相关变体 |
| Java 7 与更早 | 需使用对应分支的修复版本(2.12.x 与 2.3.x 系列) |
| 临时缓解 | 2.10 至 2.14.1 可设 log4j2.formatMsgNoLookups=true,或移除 JndiLookup 类 |
| 检测线索 | 盘点 log4j-core 依赖 + 监控出站 LDAP/RMI 连接 + 排查日志中的 jndi 表达式 |
处置步骤
- 清点依赖:应用、基础镜像、第三方组件与大数据组件链里所有 log4j-core 版本
- 判断可利用性:确认触达路径(是否有未认证输入被写入日志)与出站网络是否被限制
- 先降暴露:出站访问限制与 WAF 规则可争取时间,但不能替代升级
- 执行升级:优先升到 2.17.x;受限时至少升到 2.16.0,并确认运行进程加载的版本
- 验证与记录:确认 JAR 版本、进程加载路径与出站行为,把证据挂回编号
- 回归业务:升级后确认日志输出、格式与下游采集链路正常
依赖清点示例
依赖清点示例
find / -name "log4j-core*.jar" 2>/dev/null
unzip -p log4j-core-*.jar META-INF/MANIFEST.MF | head
# Maven 项目:mvn dependency:tree | grep log4j
# 检查运行进程实际加载的 JAR,而不只是文件系统里是否存在
# 常见遗漏:基础镜像、离线包、第三方中间件自带依赖、历史备份目录配置层缓解(示例)
配置层缓解(示例)
JVM 参数:-Dlog4j2.formatMsgNoLookups=true
或移除类:zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class
# 注意:2.16.0 起相关查找默认关闭,无需再依赖上述参数
# 缓解手段只是临时措施,升级才是根治,两者不要互相替代手段对照
| 手段 | 适用情况 | 局限 |
|---|---|---|
| 升级版本 | 所有可升级场景 | 需要回归测试与发布窗口 |
| 移除危险类 | 无法立即升级且用 2.0 至 2.9 的场景 | 后续升级或回滚可能让问题复现 |
| 配置开关 | 2.10 至 2.14.1 的临时缓解 | 不覆盖同族其他变体 |
| 出站网络限制 | 争取时间的补充措施 | 不能阻止已在内网可达的目标 |
升级、删类、配置三种手段并存的环境容易出现漏改节点,处置后必须复测。重点确认运行进程实际加载的版本,而不是只看文件系统里有没有新 JAR。
排查日志里的 ${jndi: 表达式也有价值:它能提示历史探测痕迹,但日志内容本身可能被编码变形,不能仅凭关键字判断是否被利用,应结合出站连接记录。