2.15.0之前版漏洞相关文章
Log4j2注入漏洞(CVE-2021-44228)万字深度剖析(一)—开篇与基础知识
Log4j2注入漏洞(CVE-2021-44228)万字深度剖析(二)—漏洞原理
Log4j2注入漏洞(CVE-2021-44228)万字深度剖析(三)—复现步骤(攻击方法)
Log4j2注入漏洞(CVE-2021-44228)万字深度剖析(四)—漏洞修复原理
2.15.0版漏洞相关文章
Log4j2中2.15.0版存在的漏洞(CVE-2021-45046)的注入原理、复现步骤和如何修复(2.16.0修复原理)
2.16.0版漏洞相关文章
Log4j2中2.16.0版中DOS攻击(CVE-2021-45105)的漏洞原理、复现步骤和修复方法(2.17.0修复原理)
好不容易2.16.0发布之后,Log4j2官方,又突然发布了2.17.0版本,原因想必大家通过各种号推送都已经知道了。因为在2.16.0版本上发现了一个新的漏洞,该漏洞可能会导致DoS(Denial of Service)攻击。那这个漏洞到底是怎么回事呢?它会有哪些影响呢?今天咱们就一起来深度学习下该漏洞相关原理和攻击步骤。
在继续学习本文之前,请先熟悉2.15.0之前版本漏洞的原理和2.15.0版本中漏洞的原理。否则你对对你对该文后续的部分内容理解会有一定影响。具体请参考:
2.15.0之前版漏洞相关文章
Log4j2注入漏洞(CVE-2021-44228)万字深度剖析(一)—开篇与基础知识
Log4j2注入漏洞(CVE-2021-44228)万字深度剖析(二)—漏洞原理
Log4j2注入漏洞(CVE-2021-44228)万字深度剖析(三)—复现步骤(攻击方法)
Log4j2注入漏洞(CVE-2021-44228)万字深度剖析(四)—漏洞修复原理
2.15.0版漏洞相关文章
Log4j2中2.15.0版存在的漏洞(CVE-2021-45046)的注入原理、复现步骤和如何修复(2.16.0修复原理)
介绍原理之前,我们先了解下什么是DOS攻击。参考:dos攻击_百度百科
DoS攻击是指故意的攻击网络协议实现的缺陷或直接通过野蛮手段残忍地耗尽被攻击对象的资源,目的是让目标计算机或网络无法提供正常的服务或资源访问,使目标系统服务系统停止响应甚至崩溃,而在此攻击中并不包括侵入目标服务器或目标网络设备。这些服务资源包括网络带宽,文件系统空间容量,开放的进程或者允许的连接。这种攻击会导致资源的匮乏,无论计算机的处理速度多快、内存容量多大、网络带宽的速度多快都无法避免这种攻击带来的后果。
简单来说就是通过某种方式让业务服务器无法提供正常服务。
参考:Zero Day Initiative — CVE-2021-45105: Denial of Service via Uncontrolled Recursion in Log4j StrSubstitutor
通过查看官方发布文档,我们大概对2.16.0中存在的漏洞会有一个初步的认识。大概就是疑问使用
了ctx,然后再解析的时候导致系统报错:StackOverflowError,从而实现DoS攻击。
咱们在分析2.15.0版本中的漏洞时Log4j2中2.15.0版存在的漏洞剖析),已经知道ldap的lookup漏洞不仅在日志的消息解析中存在,同时在ctx(线程上下文)中也存在。而ctx的解析过程为:
源码位置:StrSubstitutor.substitute(...)
1、判断日志规则中有ctx配置,如${ctx.apiVersion}
2、在ContextMap中找到apiVersion的内容,得到其中Value。
3、如果该Value中还存${}占位符,则会继续解析该占位符。
4、直到解析完成为止。
其实整个问题就出这里有个类似递归的解析${}占位符的逻辑。Log4j2会不断的解析${}占位符。其大致逻辑如下:
前提:日志规则中配置${ctx:apiVersion}, ContextMap.put("apiVersion", "${${ctx:apiVersion}}")
1、log4j2正常打印日志(普通日志)
2、解析日志规则中存在${ctx:apiVersion}
3、解析${}占位符得到ctx:apiVersion
4、调用ContextMap解析得到ctx:apiVersion的值=${{ctx:apiVersion}}
5、由于新值包含${}占位符,继续对齐进行解析,得到${ctx:apiVersion}
6、对${ctx:apiVersion}进行解析得到ctx:apiVersion
7、跳转到第4步,然后4-7步骤会无限执行下去,最后导致死循环。
PS:留个思考,攻击者怎样利用这里的无限循环实现拒绝服务攻击呢?
了解其原理之后,复现步骤就比较简单了。
首先然后我们只需要在日志中做如下配置:
并编写存在漏洞的接口,如下:
然后调用该接口即可。
完成之后,接口会一直请求,不断递归调用直到栈溢出。
由于该漏洞和2.15.0版中存在的漏洞机制差不多,几乎都是基于ctx的配置实现。所以他们的影响范围也有些类似。不同的是该漏洞完全不依赖jndi的lookup能力。所以2.16.0版中默认关闭了jndi中lookup功能对该漏洞并没有任何影响。因此该漏洞会更容易的被黑客利用。
该漏洞能够存在的前提如下:
1、业务代码在日志规则中使用了${ctx:}来输入线程上下文中的变量。如 apiVersion
2、该线程上下文变量来自外部用户输入,且未做安全校验
通过原理我们已经知道该漏洞存在的的原因是出现了递归解析。于是在2.17.0版本中的修复手段则比较简单:直接不允许执行递归解析即可。
源码位置:StrSubstitutor.substitute
原来解析${}都是直接用的StrSubstitutor类,而新版中都所有日志规则中的解析直接加了一个StrSubstitutor的子类:RuntimeStrSubstitutor。
该类主要用于设置默认参数,如:isRecursiveEvaluationAllowed=false。
如果你喜欢本文或觉得本文对你有所帮助,欢迎一键三连支持,非常感谢。
如果你对本文有任何疑问或者高见,欢迎添加公众号lifeofcoder共同交流探讨(添加公众号可以获得楼主最新博文推送以及”Java高级架构“上10G视频和图文资料哦)。