CVE-2017-3523|MySQL Connector/J remote code execution vulnerability
What is MySQL Connector/J?
MySQL Connector/J is a driver for MySQL adhering to the Java JDBC interface. One of the features offered by MySQL Connector/J is support for automatic serialization and deserialization of Java objects, to make it easy to store arbitrary objects in the database.
When deserializing objects, it is important to never deserialize objects received from untrusted sources. As certain functions are automatically called on objects during deserialization and destruction, attackers can combine objects in unexpected ways to call specific functions, eventually leading to the execution of arbitrary code (depending on which classes are loaded). As the code is often executed as soon as the object is constructed or destructed, additional type-checking on the constructed object is not enough to protect against this.
MySQL Connector/J requires the flag “autoDeserialize” to be set to true before objects are automatically deserialized, which should only be set when the database and its contents are fully trusted by the application.
During a short evaluation of the MySQL Connector/J source code, a method was found to deserialize objects from the database when this flag is not set and when API functions are used which do not imply the deserialization of objects at all.
The conditions are the following:
* The flag “useServerPrepStmts” is set to true. With this flag enabled, the server caches prepared SQL statements and arguments are sent to it separately. As this allows statements to be reused, it is often enabled for increased performance.
* The application is reading from a column having type BLOB, or the similar TINYBLOB, MEDIUMBLOB or LONGBLOB.
* The application is reading from this column using .getString() or one of the functions reading numeric values (which are first read as strings and then parsed as numbers). Notably not .getBytes() or .getObject().
When these conditions are met, MySQL Connector/J will check if the data starts with “0xAC 0xED” (the magic bytes of a serialized Java object) and if so, attempt to deserialize it and try to convert it to a string.
The vulnerable code can be found here:
The combination of a column of type BLOB and the vulnerable functions does not follow common best practices for using a database: BLOB columns are meant to store arbitrary binary data, which should be read using .getBytes(). However,
there are many scenarios where this can still be exploited by an attacker:
* An application does not follow best practices and stores text (or numbers) in a column of type BLOB and an attacker can insert arbitrary binary data into this column.
* An application is configured to connect to a remote untrusted database or over an unencrypted connection which is intercepted by an attacker.
* An application has an SQL injection vulnerability which allows an attacker to change the type of a columm to BLOB.
An attacker who is able to abuse this vulnerability, can have the application deserialize arbitrary objects. The direct impact is that the attacker can call into any loaded classes. Often, but depending on the application, this can be leveraged to gain code execution by calling into loaded classes that perform actions on files or system commands.
The vulnerability can be resolved by updating MySQL Connector/J to version 5.1.41 and ensuring the flag “autoDeserialize” is not set.