Analysis of MySQL JDBC Client Deserialization Vulnerability

First security guest: https://www.anquanke.com/post/id/203086


In the past few days, I studied the topic "New Exploit Technique In Java Deserialization Attack" of BlackHat Europe 2019. While admiring the masters, I did a simple vulnerability analysis.

The vulnerability needs to be able to control the client's JDBC connection string, which can be triggered during the connection phase without continuing to execute SQL statements.

Test code

You need to select the JDBC connection string according to the version, and finally there is a summary based on the connector connection string of each version.

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?autoDeserialize=true&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&user=yso_JRE8u20_calc";//8.x使用
        //String DB_URL = "jdbc:mysql://127.0.0.1:3306/test?detectCustomCollations=true&autoDeserialize=true&user=yso_JRE8u20_calc";//5.x使用
        Class.forName(driver);
        Connection conn = DriverManager.getConnection(DB_URL);
    }
}

MySQL server use: https://github.com/fnmsd/MySQL_Fake_Server

A fake server that can conveniently assist the MySQL client to read files and provide the serialized data required by the MySQL JDBC deserialization vulnerability. Please read the tool description briefly before reading this article.

Here is a copy of YSOSerial I added JRE8u20 for testing (integrated with the code of the n1nty master, film it):

Link: https://pan.baidu.com/s/12o5UFaln0qDUo0hPcIR1Eg Extraction code: qdfc

ServerStatusDiffInterceptor trigger mode

Using this method in the original topic, the environment should be 8.x connector

The analysis environment here uses mysql-java-connector 8.0.14+jdk 1.8.20

Refer to the MySQL Connector/J 8.0 connection string parameter property manual

**queryInterceptors:** A comma-separated list of Classes (Classes that implement the com.mysql.cj.interceptors.QueryInterceptor interface), executed "between" queries to affect the results. (The effect is to insert an operation before and after the execution of the Query)
**autoDeserialize:** Automatically detect and deserialize the objects stored in the BLOB field.

So as mentioned above, if you want to trigger queryInterceptors, you need to trigger SQL Query, and in the getConnection process SET NAMES utf, set autocommit=1a type of request will be triggered, so the queryInterceptors we configured will be triggered.

ServerStatusDiffInterceptorThe preProcessmethod ( the method that needs to be executed before executing SQL Query), called populateMapWithSessionStatusValues:

Insert picture description here
Execute the SHOW SESSION STAUSstatement and get the result, continue to follow the resultSetToMapmethod:

Insert picture description here

ResultSetImplThe getObject method of MySQL, when the MySQL field type is BLOB, will deserialize the data, so as long as the first or second field is BLOB and our serialized data is stored, it can be triggered.

One extra sentence: In addition to the BLOB column type in the protocol message, the FLAGS must be greater than 128 and the source table is not empty. Otherwise, it will be regarded as Text. This is stuck for a long time when developing tools.

Insert picture description here

During the test, it was found that 5.x and 6.x could not be used normally. Refer to the connection string description of 5.1 , 6.0 and 8.0 of mysql java connector , and summarize after analyzing the code of each version:

  1. Since 6.0, the main package name has changed from · com.mysqlto com.mysql.cj, so ServerStatusDiffInterceptorthe location has also changed.

  2. The interceptors attribute used in 5.1.11-6.0.6 is statementInterceptors, and the queryInterceptors used above 8.0 is queryInterceptors. (This is not very sure, because the 6.0 manual says that it has become queryInterceptors since 5.1.11, but it is still statementInterceptors after the actual test)

  3. Below 5.1.11, it cannot be triggered directly by connection:

    When executing getConnection, it will execute to the following code block in com.mysql.jdbc.ConnectionImpl:

Insert picture description here

It can be found that the two lines of code marked above have exchanged positions (emm, not exactly the same, understand the spirit).

The SQL query during connection described in the previous analysis is triggered in the createNewIO method, but because 5.1.10 and before, Interceptors were initialized after createNewIO, resulting in no Interceptors before the query was triggered, so it could not be triggered during getConnection.

PS: If you continue to use the acquired connection for SQL execution, you can still trigger the deserialization.

DetectCustomCollations trigger method

This point seems to have been found out by Master Chybeta at the earliest.

One digression: Look at the 5.x manual mentioned earlier. detectCustomCollationsThis option starts from 5.1.29. After code comparison, it can be considered that detectCustomCollationsthis option has been true before 5.1.29.

Use mysql-connector-java 5.1.29+java 1.8.20 in the test environment:

The trigger point is in com.mysql.jdbc.ConnectionImplthe buildCollationMappingmethod:

(The call stack will not be placed, just hit a breakpoint)

Insert picture description here

You can see two conditions:

  1. The server version is greater than or equal to 4.1.0, and the detectCustomCollationsoption is true

PS: This judgment condition of 5.1.28 only has the server version greater than 4.1.0

  1. After obtaining the SHOW COLLATIONresults, the server version is greater than or equal to 5.0.0 before entering the resultSetToMapmethod mentioned in the previous section to trigger deserialization

Insert picture description here

Here, getObject is consistent with the previous article and will not be repeated here. Only field 2 or 3 is required to load our serialized data for BLOB.

Since version 5.1.41, SHOW COLLATIONthe result obtained by getObject is no longer used , this method is invalid.

5.1.18 The following does not use getObject to obtain, and this method cannot be used:

Insert picture description here

Summarize the available connection strings

The user name is based on the MySQL Fake Server tool, please modify it yourself during specific use.

ServerStatusDiffInterceptor triggers:

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 (different attribute names):jdbc:mysql://127.0.0.1:3306/test?autoDeserialize=true&statementInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&user=yso_JRE8u20_calc

5.1.11 and above 5.x version (the package name does not have cj):jdbc:mysql://127.0.0.1:3306/test?autoDeserialize=true&statementInterceptors=com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor&user=yso_JRE8u20_calc

5.1.10 and below 5.1.X version: Same as above, but need to execute query after connection.

5.0.x: There is no ServerStatusDiffInterceptorsuch thing yet┓( ´∀` )┏

detectCustomCollations trigger:

5.1.41 and above: Not available

5.1.29-5.1.40:jdbc:mysql://127.0.0.1:3306/test?detectCustomCollations=true&autoDeserialize=true&user=yso_JRE8u20_calc

5.1.28-5.1.19:jdbc:mysql://127.0.0.1:3306/test?autoDeserialize=true&user=yso_JRE8u20_calc

5.1.x versions below 5.1.18: Not available

Version 5.0.x is not available

to sum up

The above summarizes the analysis of the two methods of triggering vulnerabilities through MySQL JDBC Connector and the related version situation, I hope it can be helpful to everyone.

Since it is still the scope of the Java deserialization vulnerability, there is still a need for a Gadget available in the operating environment.

Several masters who found loopholes in the film again~

references

Vulnerability related:

https://i.blackhat.com/eu-19/Thursday/eu-19-Zhang-New-Exploit-Technique-In-Java-Deserialization-Attack.pdf

https://www.cnblogs.com/Welk1n/p/12056097.html

https://github.com/codeplutos/MySQL-JDBC-Deserialization-Payload

MySQL java Connector manual:

https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-reference-configuration-properties.html

https://docs.oracle.com/cd/E17952_01/connector-j-6.0-en/connector-j-6.0-en.pdf

https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-configuration-properties.html

The last is the recruitment notice

The 360 ​​cloud security team is currently recruiting a large number of people, welcome to send your resumes, everyone come and play happily~

https://www.anquanke.com/post/id/200462

Insert picture description here

Guess you like

Origin blog.csdn.net/fnmsd/article/details/106232092