Apache Log4j2 JNDI注入分析调试笔记

2023年 7月 10日 21.1k 0

Apache Log4j2是一款优秀的Java日志框架,最近爆出了一个jndi注入的漏洞,影响面非常广,各大厂商都被波及。Log4j2作为日志记录的第三方库,被广泛得到使用,这次主要分享一下,最近的一些调试记录。

JNDI简介

JNDI 全称为 Java Naming and Directory Interface,即 Java 名称与目录接口。本质上就是一个接口,ND代表的Naming 和 Directory,分别代表Naming Service(名称服务)和Directory Service(目录服务)。参考JNDI 注入漏洞的前世今生

名称服务就是通过名称查找实际对象的服务,例如:通过域名寻找ip地址即DNS服务、文件系统、以及LDAP(Lightweight Directory Access Protocol)即轻量级目录访问协议都是名称服务,不同的是LDAP(RFC2251(RF**511) )是一个协议,是和HTTP一样是通用的,而不止局限于JAVA.目录服务是名称服务的一种拓展,除了名称服务中已有的名称到对象的关联信息外,还允许对象拥有属性(attributes)信息。由此,我们不仅可以根据名称去查找(lookup)对象(并获取其对应属性),还可以根据属性值去搜索(search)对象。目录服务也是一种特殊的名称服务,关键区别是在目录服务中通常使用搜索(search)操作去定位对象,而不是简单的根据名称查找(lookup)去定位。

JNDI 架构上主要包含两个部分,即 Java 的应用层接口和 SPI,SPI 全称为 Service Provider Interface,即服务供应接口,主要作用是为底层的具体目录服务提供统一接口,从而实现目录服务的可插拔式安装,如下图所示:

Apache Log4j2 JNDI注入分析调试笔记

如上JNDI为不同的目录服务提供统一的操作接口

JDK 中包含了下述内置的目录服务:

  • RMI: Java Remote Method Invocation,Java 远程方法调用;
  • LDAP: 轻量级目录访问协议;
  • CORBA: Common Object Request Broker Architecture,通用对象请求代理架构,用于 COS 名称服务(Common Object Services);

RMI

RMI(Remote Method Invocation)即java的远程方法调用,Java RMI是专为Java环境设计的远程方法调用机制,远程服务器实现具体的Java方法并提供接口,客户端本地仅需根据接口类的定义,提供相应的参数即可调用远程方法并获取执行结果,即JAVA的RPC机制。关于RMI需要注意以下两点:

  • RMI的传输是基于反序列化的。
  • 对于任何一个以对象为参数的RMI接口,你都可以发一个自己构建的对象,迫使服务器端将这个对象按任何一个存在于服务端classpath(不在classpath的情况,可以看后面RMI动态加载类相关部分)中的可序列化类来反序列化恢复对象。
  • 更多可以参考:https://paper.seebug.org/1091/#java-rmi_1

    LDAP

    LDAP即是JNDI SPI支持的Service Provider之一,但同时也是协议。是早期 X.500 DAP (目录访问协议) 的一个子集,因此有时也被称为 X.500-lite。LDAP目录服务是由目录数据库和一套访问协议组成的系统,目录服务是一个特殊的数据库,用来保存描述性的、基于属性的详细信息,能进行查询、浏览和搜索,以树状结构组织数据。LDAP目录服务基于客户端-服务器模型,它的功能用于对一个存在目录数据库的访问。LDAP目录和RMI注册表的区别在于是前者是目录服务,并允许分配存储对象的属性。

    LDAP 的目录信息是以树形结构进行存储的,在树根一般定义国家(c=CN)或者域名(dc=com),其次往往定义一个或多个组织(organization,o)或组织单元(organization unit,ou)。一个组织单元可以包含员工、设备信息(计算机/打印机等)相关信息。

    一些定义:

    Apache Log4j2 JNDI注入分析调试笔记

    漏洞环境

    pom.xml
    
    
      4.0.0
      org.example
      log4j-test
      1.0-SNAPSHOT
      
          
              org.apache.logging.log4j
              log4j-api
              2.9.0
          
          
              org.apache.logging.log4j
              log4j-core
              2.9.0
          
      
    
    
    log4jTest.java
    import org.apache.logging.log4j.LogManager;
    
    public class log4jTest {
      //获取日志记录器Logger,名字为本类类名
      private static final Logger logger = LogManager.getLogger();
      public static void main(String[] args) {
          for(int i=0;i payload

    Apache Log4j2 JNDI注入分析调试笔记

    放在mysql服务器的py文件同级目录,并且运行mysq服务器。

    Apache Log4j2 JNDI注入分析调试笔记

    流程分析

    log4j三大组件为Logger、Appender、Layout。Logger负责收集处理日志记录,Layout负责日志输出的形式,而Appender负责配置日志的输出位置和方式。

    其中Appender可以配置的一种方式为数据库输出(JDBCAppender),通过JDBC链接把日志输出到数据库中,配置时需要配置JDBC驱动,连接字符串,用户名,密码以及SQL语句。

    我们直接把断点打在JDBCAppender.java的getConnection()处,因为这也是MYSQL JDBC反序列化的执行点。

    调用链如下:

    Apache Log4j2 JNDI注入分析调试笔记

    成功执行:

    Apache Log4j2 JNDI注入分析调试笔记

    Apache Log4j2 JNDI注入分析调试笔记

    但是正常情况下我们是无法控制log4j的配置文件的,所以是比较鸡肋的,但是一些可以动态配置服务的,例如nacos,也许可以找到利用方式。

    Apache Log4j2 JNDI注入分析调试笔记

    但是不知道是否支持log4j1.x,:)。

    参考:

    https://paper.seebug.org/1091/

    https://paper.seebug.org/942/

    https://githubmemory.com/repo/Ea3i0n/JNDIExploit

    https://www.docs4dev.com/docs/zh/log4j2/2.x/all/manual-lookups.html

    https://evilpan.com/2021/12/13/jndi-injection/

    https://mp.weixin.qq.com/s/vAE89A5wKrc-YnvTr0qaNg

    本文作者:合天网安实验室

    相关文章

    服务器端口转发,带你了解服务器端口转发
    服务器开放端口,服务器开放端口的步骤
    产品推荐:7月受欢迎AI容器镜像来了,有Qwen系列大模型镜像
    如何使用 WinGet 下载 Microsoft Store 应用
    百度搜索:蓝易云 – 熟悉ubuntu apt-get命令详解
    百度搜索:蓝易云 – 域名解析成功但ping不通解决方案

    发布评论