深入剖析最新Log4j2漏洞调用流程【CVE-2021-44228、CNVD-2021-95914】

深入剖析Log4j2调用流程

申明:本文只做学习交流使用,严禁任何组织和个人通过转发、转载等方式进行传播,因此导致的法律后果与本文作者无关。

小菜鸡昨晚正在积极进补雷神大大的课程的时候:
在这里插入图片描述
老板的消息划破了寂静的夜空,也打断了我学习的脚步:
在这里插入图片描述
按照我的尿性,这种时候我肯定偷偷装死没跑了。
不过这个漏洞还是引起了我的兴趣,毕竟热度就那么多,蹭一蹭就没有了,我肯定也要蹭一蹭了。于是在昨晚瞎整了一晚上没结果后,今天上班的时候划水就把这整个利用过程给跑通了…
果然上班划水才是生产力啊。
首先,我们使用maven进行项目管理,搭建漏洞环境:
在pom.xml中引入下面的两个依赖:

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

漏洞存在的版本就懒得说了,反正不是最新版就对了,手动狗头!!
然后写个小页面:

package com.armandhe.log4j2;


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

public class Log4j2Test {
    private static final Logger logger =  LogManager.getLogger();
    public static void main(String[] args) {
        logger.error("payload手动打码");
    }
}

然后打断点直接开始调试:
在这里插入图片描述
跳进去,懂的都懂:
在这里插入图片描述
到了这儿后据说是一个非常重要的步骤,调用logIfEnabled方法判断是否启用日志记录,这里的日志记录分为不同的等级,可以在log4j2的配置文件log4j2.properties中进行配置日志记录的级别。
我们继续跟进该方法:
在这里插入图片描述
虽然不知道logMessage函数干什么的,不过肯定不是我们需要的,继续跟进:
在这里插入图片描述
logMessageSafely函数,翻译一下就是日志信息安全性,猜一下可能是进行安全性判断的吧?因为是从零开始的期间我还跟进了newMessage函数,发现是将我们的message封装成了一个对象,对我们的目标没有大的影响, 跟进:
在这里插入图片描述
就想这样,将message封装进了一个ReusableSimpleMessage对象,继续回到logMessageSafely函数跟进:
在这里插入图片描述
跟进logMessageTrackRecursion函数,不懂就问recursion什么意思?所以我抽空去有道查了一下:
在这里插入图片描述
函数名翻译过来就是日志信息跟踪递归,什么意思?俺也不知道,继续跟进:

在这里插入图片描述
哦豁,原来就在下面,跟进函数tryLogMessage,老规矩还是翻译一下,捕获日志信息,还是不知道什么意思,但是又有什么关系呢,继续跟进:
在这里插入图片描述
管他什么呢,无脑继续跟:
在这里插入图片描述
又能怎么样呢,继续:
在这里插入图片描述
好烦啊,无限套娃:
在这里插入图片描述
先进去看看:
在这里插入图片描述
好像做了很多,又好像什么也没做,就是setMessage哪儿换了个对象封装message:
在这里插入图片描述
意义不大,所以我们继续单步执行:
在这里插入图片描述
到这儿后跟进this.log
在这里插入图片描述
然后进入processLogEvent
在这里插入图片描述
到了这儿后,如果我们直接单步向下会发现处理发生了延迟,这就是我们的主机在请求dns解析产生的延迟,我也是在发现了这个特点之后才能在这又臭又长的调用链中坚持到最后,继续跟进:
在这里插入图片描述
这儿很关键啊,兄弟们,不信我们往下看:
在这里插入图片描述
继续:
在这里插入图片描述
这儿是挨着的两次调用:
在这里插入图片描述
继续:
在这里插入图片描述
这儿三重套娃:
在这里插入图片描述
二重套娃:
在这里插入图片描述
刚才说错了兄弟们,前面不重要,这儿很重要啊,这儿有11重循环,当循环到第8层的时候会有惊喜,所以我们至今到第8次循环让你们见识见识什么他么的叫他么的惊喜:
在这里插入图片描述
好了看到i等于8了吗:
跟进去咯:
在这里插入图片描述
继续咯,不用我教你吧:
在这里插入图片描述
亲,敲黑板划重点了啊!!!!!
这里有个进入的前提条件:
在这里插入图片描述
this.config不为空,且this.noLookupsfalse,这也是为什么你在各种各样的公众号看到的该漏洞的一个解决方案就是将noLookups的值设置为true的原因。

workingBuiler是个啥?我也不知道啊,怎么可能,这玩意就是一个stringBuilder,所以你懂了吧?
在这里插入图片描述
因为他娘的在这个声明过了,那么问题来了,长度80,也就是我的日志长度不能超过80?扯淡呢吧?当然超过80了,搞不懂搞不懂。
进入的条件判断有一个offset调试后发现是59,查了一下发现是$,也就是说message前面的58个字符的长度是固定的咯,我们输入的信息从第59个开始:
在这里插入图片描述
然后判断连续两个字符是是否为\${,如果是进入正题,截取了从59到后面的所有字符赋值给value,然后给我们的workingBuilder设置了长度并将截取的value进行处理之后赋值给他,在这里我利用了前面说到的延时特性观察到命令执行就发生在这里的对value处理过程中,所以我们跟进这个处理过程:
在这里插入图片描述
source就是value的值,继续跟进:
在这里插入图片描述
又开始套娃了:
在这里插入图片描述
这个substitute函数可以说是写的又臭又长,总结一下左右就是提取那个啥?就那个我们的payload就对了,一直单步到这儿:
在这里插入图片描述
进去:
在这里插入图片描述
到这儿后其实variableName就是我们的payload主体了,继续:
在这里插入图片描述
这里有两个重要的操作,一个是获得了协议前缀,一个是获取了具体的paload内容,this.strLookupMap里面定义了很多支持的协议,我们可以看一下:
在这里插入图片描述
进入进入断点,判断event是否为空,肯定不为空啊,所以进入的是lookup.lookup(name)
在这里插入图片描述
到了这里就有意思而了,第一个红框是获取一个JndiManager,但是在我调试的时候这里面好像是报错了还是怎么了,总是进不到第二个红框里面,而执行命令的代码又恰好在第二个红框里面,你说奇怪不奇怪?
是有意我直接强行跟踪到了第二个红框里面的代码:
在这里插入图片描述
重中之重就在这里了哈!!!lookup函数,看到这个你想到了什么?不确定吗?那来看看this.context是什么,InitialContext有没有想起点什么????
打完收工!!!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值