CVE-2023-32697
Patch Available.
Overview
SQLite JDBC is a JDBC driver for SQLite that bundles the SQLite engine and its native libraries, letting Java applications read and write SQLite databases with no separate database installation. The driver resolves the database to open from the JDBC connection URL, which includes a resource form that loads a database from a local or remote location.
A remote code execution vulnerability (CVE-2023-32697) has been identified in SQLite JDBC, which allows attackers who control the JDBC connection URL to write attacker-chosen bytes to a temporary file path they can compute in advance, and to have the driver open a file already waiting at that path instead of the intended database.
Per OWASP: Code Injection is the general term for attack types which consist of injecting code that is then interpreted/executed by the application. This type of attack exploits poor handling of untrusted data.
This issue affects versions 3.6.14.1 through 3.41.2.1 of SQLite JDBC.
Details
Module Info
- Product: SQLite JDBC
- Affected packages:
org.xerial:sqlite-jdbc - Affected versions: >=3.6.14.1 <3.41.2.2
- GitHub repository: https://github.com/xerial/sqlite-jdbc
- Published packages: https://central.sonatype.com/artifact/org.xerial/sqlite-jdbc
- Package manager: Maven
- Fixed in: NES for SQLite JDBC 3.36.0-sqlite-jdbc-3.36.2
Vulnerability Info
This Critical-severity vulnerability is found in the org.xerial:sqlite-jdbc package in versions 3.6.14.1 through 3.41.2.1 of SQLite JDBC.
A JDBC URL of the form jdbc:sqlite::resource:<url> tells the driver to fetch a database from a location rather than open a local file. SQLiteConnection.extractResource returns early only when the URL protocol is file, so any http, https, ftp or jar URL falls through to a download path that copies the remote bytes into the system temporary directory before SQLite inspects them:
String tempFolder = new File(System.getProperty("java.io.tmpdir")).getAbsolutePath();
String dbFileName = String.format("sqlite-jdbc-tmp-%d.db", resourceAddr.hashCode());
File dbFile = new File(tempFolder, dbFileName);
if (dbFile.exists()) {
long resourceLastModified = resourceAddr.openConnection().getLastModified();
long tmpFileLastModified = dbFile.lastModified();
if (resourceLastModified < tmpFileLastModified) {
return dbFile;
}
...
}
The destination file name derives entirely from java.net.URL.hashCode(), a 32-bit value an attacker computes offline from a URL they chose, so the full path of the dropped file is known to them in advance. The write happens regardless of the content: if the downloaded bytes are not a valid SQLite database the subsequent open fails, but the file is left on disk either way.
That yields two primitives. The first is an attacker-named file write into the temporary directory, which reaches code execution when the dropped file is picked up by something that loads from that directory, such as a native library loaded by a later connection that enables extension loading. The second is unverified cache reuse: because a file already present at that path is returned whenever its modification time is newer than the remote resource, anything able to write the predictable path first decides which database the victim connection actually opens.
No configuration gates the affected code. The resource URL handler is always present, and no property or SQLiteConfig setting is required to reach it. Exploitation requires only that the attacker supplies the JDBC connection URL, through a datasource definition, a connection-string field, or any sink that reaches DriverManager.getConnection.
This vulnerability was introduced in 2009 with SQLite JDBC 3.6.14.1.
Mitigation
The 3.36 line of SQLite JDBC is End-of-Life and will not receive any updates to address this issue. Only the most recent release of SQLite JDBC is community-supported; the project ships from a single moving line with no maintenance branches, and each new release immediately supersedes the previous one. The affected line ended at 3.36.0.3.
Users of the affected components should apply one of the following mitigations:
- Upgrade
org.xerial:sqlite-jdbcto release 3.41.2.2 or later, which contains the fix. - Leverage a commercial support partner like HeroDevs for post-EOL security support.
Credits
- Hamza Tahmi (finder)