Resolving CVE-2023-7104 in Legacy System.Data.SQLite Components
Vulnerability Scope and Impact of CVE-2023-7104 in SQLite-Based Components
CVE-2023-7104 is a security vulnerability disclosed in September 2023 affecting specific versions of SQLite’s FTS3 (Full-Text Search Version 3) extension. The flaw allows remote attackers to execute arbitrary code via crafted MATCH expressions when using specialized virtual table configurations. While SQLite’s core library patched this in version 3.43.1, the vulnerability propagates to downstream libraries like System.Data.SQLite that bundle SQLite as a dependency. The System.Data.SQLite 1.0.118 series embeds SQLite 3.8.11.1 (released in 2015), which predates the fix by eight years. This creates a critical exposure in applications using FTS3 with untrusted input sources, particularly web-facing systems parsing user-generated search terms. The risk is amplified when SQLite is compiled without the SQLITE_DEFAULT_DEFENSIVE or SQLITE_DQS=0 mitigations.
The vulnerability manifests when a malicious MATCH clause triggers a heap buffer overflow during FTS3 query parsing. Successful exploitation requires two conditions: (1) the application must enable FTS3/4 virtual tables, and (2) input sanitization for MATCH operands must be absent. Attack vectors include search forms, API endpoints accepting raw SQL fragments, or ORM layers concatenating FTS predicates without parameterization. Systems using Entity Framework (EF6) via System.Data.SQLite.EF6 are at heightened risk due to LINQ-generated FTS queries.
Outdated Dependencies and Configuration Gaps Enabling CVE-2023-7104
The root cause lies in the reliance on deprecated System.Data.SQLite packages (1.0.118) that bundle a vulnerable SQLite build. These components were last updated in 2015 and lack modern security patches. The System.Data.SQLite.Core 1.0.118 binary statically links to SQLite 3.8.11.1, which lacks the upstream fix for CVE-2023-7104. Even if the host application uses a newer SQLite DLL separately, the System.Data.SQLite adapter’s internal linkage overrides external libraries, forcing the outdated engine into memory.
A secondary factor is improper FTS3 configuration. Prior to SQLite 3.43.1, the FTS3 tokenizer did not enforce bounds checks during query parsing. Applications enabling FTS3 without restricting user input to parameterized queries inherit this flaw. For example, code like var results = db.Query<User>("SELECT * FROM docs WHERE body MATCH '" + userInput + "'");
directly interpolates unsanitized input into an FTS predicate, enabling buffer overflow exploits.
Third, build settings for SQLite in legacy packages omit defensive compiler flags. SQLITE_DEFAULT_DEFENSIVE (introduced in 3.37.0) restricts certain unsafe SQL functions, while SQLITE_DQS=0 disables double-quoted string literals, reducing injection surfaces. The 1.0.118 binaries were compiled without these options, widening the attack surface.
Mitigation Strategies for CVE-2023-7104 in System.Data.SQLite Environments
Immediate Patching via Dependency Upgrades
Replace System.Data.SQLite 1.0.118 with a modern fork. The original System.Data.SQLite project is obsolete; migrate to Microsoft.Data.Sqlite (maintained by .NET Foundation) or community-supported forks like SQLitePCL.raw. For .NET Framework projects bound to System.Data.SQLite, use the unofficial updated builds from repositories like NuGet (search for "System.Data.SQLite.Core" maintained by Eric Sink). Confirm the replacement package embeds SQLite 3.44.2 or higher.
For EF6 integrations, uninstall System.Data.SQLite.EF6 1.0.118 and adopt Microsoft.EntityFrameworkCore.Sqlite. If tightly coupled to EF6, manually reference the patched SQLite.Interop.dll (version 3.45.1+) and ensure it’s deployed alongside the app.
Runtime Configuration Hardening
If immediate package replacement is unfeasible, apply runtime mitigations:
- Set
PRAGMA trusted_schema=OFF;
at database startup to disable virtual table tampering. - Enable defensive mode with
PRAGMA cell_size_check=ON;
andPRAGMA mmap_size=0;
to constrain memory operations. - Disable FTS3/4 with
PRAGMA compile_options('-DENABLE_FTS3');
during SQLite initialization. Recompile the SQLite core if necessary.
Input Sanitization and Query Parameterization
Rewrite all FTS3 queries to use parameterized commands. For example:
using (var cmd = connection.CreateCommand()) {
cmd.CommandText = "SELECT * FROM docs WHERE body MATCH @query";
cmd.Parameters.AddWithValue("@query", userInput);
}
Implement a regex filter to reject MATCH clauses containing parentheses, wildcards, or binary data. Use a whitelist approach for allowed characters (A-Z, 0-9, spaces).
Build Custom SQLite Binaries with Security Flags
For legacy apps requiring System.Data.SQLite 1.0.118, rebuild SQLite from source with:
-DSQLITE_DEFAULT_DEFENSIVE=1
-DSQLITE_DQS=0
-DSQLITE_ENABLE_FTS3_PARENTHESIS=0
(disables advanced FTS syntax prone to overflows)
Replace the native interop DLL in System.Data.SQLite.Core’s /x86 and /x64 directories.
Monitoring and Logging
Enable SQLite’s error logging via sqlite3_config(SQLITE_CONFIG_LOG, errorCallback, data);
to capture FTS-related crashes. Monitor logs for repeated MATCH expression failures, which may indicate exploitation attempts. Use WAF rules to block requests containing FTS-specific operators like NEAR, AND, or NOT in search parameters.
Long-Term Migration Planning
Transition to Microsoft.Data.Sqlite, which follows modern .NET versioning and receives timely SQLite updates. For EF6 compatibility, use Microsoft.EntityFrameworkCore.Sqlite with compatibility shims. Test all FTS queries under the new library, as tokenization rules differ post-SQLite 3.43.1. Conduct a full security audit for other CVEs fixed since 2015, including CVE-2022-35737 (CLI heap overflow) and CVE-2020-35527 (Windows directory traversal).