Log4j漏洞源码分析,学到啦!
共 1754字,需浏览 4分钟
·
2021-12-27 17:54
点击上方蓝色字体,选择“标星公众号”
优质文章,第一时间送达
这几天Log4j的问题消息满天飞,今天我们就一起来看看从源码角度看看这个漏洞是如何产生的。
大家都知道这次问题主要是由于Log4j中提供的jndi的功能。
具体涉及到的入口类是log4j-core-xxx.jar中的org.apache.logging.log4j.core.lookup.StrSubstitutor
这个类。
原因是Log4j提供了Lookups的能力(关于Lookups可以点这里去看官方文档的介绍),简单来说就是变量替换的能力。
在Log4j将要输出的日志拼接成字符串之后,它会去判断字符串中是否包含${
和}
,如果包含了,就会当作变量交给org.apache.logging.log4j.core.lookup.StrSubstitutor
这个类去处理。
相关的代码下面这个
首先是org.apache.logging.log4j.core.pattern.MessagePatternConverter
这个类的format
方法
图中标注1的地方就是现在漏洞修复的地方,让noLookups这个变量为true,就不会进去里面的逻辑,也就没有这个问题了。
图中标注2的地方就是判断字符串中是否包含
${
,如果包含,就将从这个字符开始一直到字符串结束,交给图中标注3的地方去进行替换。图中标注3的地方就是具体执行替换的地方,其中
config.getStrSubstitutor()
就是我们上面提到的org.apache.logging.log4j.core.lookup.StrSubstitutor
。
在StrSubstitutor
中,首先将${
和}
之间的内容提取出来,交给resolveVariable
这个方法来处理。
我们看下resolver
的内容,它是org.apache.logging.log4j.core.lookup.Interpolator
类的对象。
它的lookups定义了10中处理类型,还有一个默认的defaultLoopup,一种11中。如果能匹配到10中处理类型,就交给它们去处理,其他的都会交给defaultLookup去处理。
匹配规则也很简单,下面简单举个例子。
1.如果我们的日志内容中有${jndi:rmi://127.0.0.1:1099/hello}这些内容,去掉
${
和}
,传递给resolver
的就是jndi:rmi://127.0.0.1:1099/hello。2.
resolver
会将第一个:之前的内容和lookups做匹配,我们这里获取到的是jndi
,就会将剩余部分jndi:rmi://127.0.0.1:1099/hello交给jdni
的处理器JndiLookup
去处理。
图中标注1的地方入参就是jndi:rmi://127.0.0.1:1099/hello
图中标注2的地方就是jndi
图中标注3的地方就是rmi://127.0.0.1:1099/hello
图中标注4的地方就是处理器
JndiLookup
类的对象图中标注5的地方就是jndi来处理的入口
关于jndi相关的,以及漏洞如何复现网上有一大把的教程,这里就不展开了。
关于漏洞的修复。
主要是通过设置noLookups变量的值,不让它进去这个if
里面的逻辑。
这个变量的值是来自下面这个属性
所以在在代码中加入System.setProperty("log4j2.formatMsgNoLookups","true");
这句也就可以了。当然网上有更多其他的修复方法,这里就不讨论了。
作者 | wang03
来源 | cnblogs.com/wbo112/p/15690699.html
加锋哥微信: java1239 围观锋哥朋友圈,每天推送Java干货!