jdbc

连接数据库

1
2
3
4
5
6
7
8
9
10
public static Connection Connect() throws SQLException, ClassNotFoundException {
String CLASS_NAME="com.mysql.cj.jdbc.Driver";
Class.forName(CLASS_NAME);


String URL="jdbc:mysql://localhost:3306/jfinal_cms";
String USER="root";
return DriverManager.getConnection(URL,USER,"");
}

这个就是完整的连接数据库的逻辑

现在就有一个问题了

为什么需要Class.forName 提前注册?

需要了解Class.forName 的作用:动态加载类到 JVM 中并执行类的初始化

那为什么需要呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.mysql.cj.jdbc;

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

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
public Driver() throws SQLException {
}

static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
}

可以通过这个类发现,需要通过反射,registerDriver

但是为什么在删除这个之后有时候发现也能正常的执行数据库连接?

那就又要掏出另一个概念了-SPI

深入理解 Java 中 SPI 机制 - 知乎 (zhihu.com)

简单的说就是会主动的找classpath 对应的目录下的META-INF/services 并将这个包中的内容加载到jvm 中

这一步就是完全自动化的

在jdbc 中

image-20250517173259976

这个类就会自动的加载

问题思考

  1. SPI机制是否有安全性问题?

    1. SPI通过扫描META-INF/services目录下的配置文件动态加载实现类,攻击者可能篡改配置文件或植入恶意JAR包,导致加载未经验证的类并执行恶意代码。例如,若服务提供者的实现类中包含反射调用危险方法(如Runtime.exec()),可能直接触发远程代码执行(RCE)
    2. Java默认的类加载机制未严格限制SPI实现类的来源。若未配合安全管理器(SecurityManager)或沙箱类加载器,攻击者可利用SPI加载来自不可信路径的类,突破权限隔离
    3. SPI的配置文件以明文形式存储于JAR包中,攻击者可通过修改META-INF/services下的接口文件内容,指定恶意实现类路径,从而劫持服务加载过程
  2. Java反射有那些安全问题?

    1. 默认加载的时候可能存在恶意的static 代码,以至于不需要实例化对象,就在默认调用的时候完成了攻击
    2. 反射允许直接访问和修改类的私有字段、方法或构造器,例如通过setAccessible(true)绕过private修饰符的限制。这可能导致敏感数据泄露(如密码字段)或破坏对象封装性。
    3. 反射常与反序列化结合使用,若反序列化数据不可信,可能触发恶意代码执行(如通过ObjectInputStream加载恶意对象)
  3. Java类加载机制是什么?

    就是将class 文件加载到jvm 中的机制。这个机制中最出名的模型是双亲委派模型。就是子加载在加载的时候不会先加载,而是向上抛给上一层加载器。一直到顶层的加载器无法加载,才会逐步向下尝试加载。

    一些风险:

    1. 如果攻击者能够控制应用程序使用的类加载器,或者能够注入一个恶意的自定义类加载器,他们就可以加载任意的恶意代码。
    2. 虽然自定义类加载器通常建议重写findClass()以遵循双亲委派,但如果错误地重写了loadClass()并破坏了委派链,可能会导致命名空间混淆或加载非预期的类版本。
    3. java.lang.ClassLoaderprotected final byte[] defineClass(String name, byte[] b, int off, int len)方法可以将一个字节数组转换为Class对象。如果攻击者能够控制传递给此方法的字节数组内容,他们就可以在JVM中定义任意类。
    4. java.net.URLClassLoader可以从指定的URL加载类和资源。如果URL来源不受信任或可被攻击者控制,那么JVM就会加载并可能执行恶意代码。
    5. 类加载器不仅加载类,还加载资源(如配置文件、图片等)通过getResource()getResourceAsStream()。如果自定义类加载器在构造资源路径时未对输入进行充分验证,可能导致路径操纵,读取到非预期的本地文件或发起非预期的网络请求(类似SSRF,如果从URL加载资源)。
  4. 数据库连接时密码安全问题?

  5. 使用JDBC如何写一个通用的数据库密码爆破模块?


jdbc
https://tsy244.github.io/2025/05/17/java安全/jdbc/
Author
August Rosenberg
Posted on
May 17, 2025
Licensed under