您当前的位置: 首页 >  log4j

合天网安实验室

暂无认证

  • 0浏览

    0关注

    748博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

log4j2 JNDI注入分析笔记

合天网安实验室 发布时间:2021-12-27 15:30:00 ,浏览量:0

bb182893cd46183a3d1534c1376b8db3.gif

原创稿件征集

邮箱:edu@antvsion.com

QQ:3200599554

黑客极客技术、信息安全热点安全研究分析等安全相关的技术文章

稿件通过并发布还能收获

200-800元不等的稿酬

4a3c9f2b0de9cc5bb5101bdcb60e99d2.png

01

前言

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

dc6edce03985f4c394b598c93870b14f.png

02

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(RFC4511) )是一个协议,是和HTTP一样是通用的,而不止局限于JAVA.目录服务是名称服务的一种拓展,除了名称服务中已有的名称到对象的关联信息外,还允许对象拥有属性(attributes)信息。由此,我们不仅可以根据名称去查找(lookup)对象(并获取其对应属性),还可以根据属性值去搜索(search)对象。目录服务也是一种特殊的名称服务,关键区别是在目录服务中通常使用搜索(search)操作去定位对象,而不是简单的根据名称查找(lookup)去定位。

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

c51be57e5882dd51c1d1be5634e2202f.png

如上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需要注意以下两点:

  1. RMI的传输是基于反序列化的。

  2. 对于任何一个以对象为参数的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)。一个组织单元可以包含员工、设备信息(计算机/打印机等)相关信息。

一些定义:

b4f5f3aaaf71127d051490a5838c386c.png

aa30c3a51f90871a4fc9b9c3763b7460.png

03

漏洞环境
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

c7ca8377e7daa6cc47519d8ba38ff5a5.png

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

f2e53ea53b81ec073b44cd02bc1c9f1f.png

流程分析

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

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

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

调用链如下:

148197978a930514d078dd2d8e759574.png

成功执行:

0be37dccfc0dc3438f658f7fee8ffdf9.png

1e413c0508cdaa31852c707d560f4935.png

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

5e0eedfc56569b5f846c536800077cd2.png

但是不知道是否支持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

98c400b71a29b67c02daacae52557cf7.gif

戳“阅读原文”体验免费靶场!

关注
打赏
1665306545
查看更多评论
立即登录/注册

微信扫码登录

0.0880s