Skip to content

[Bug]heap-buffer-overflow in sqlite3_rekey_v2() from unbounded strlen() on a non-NUL-terminated key when nKey < 0 (CWE-125) #606

Description

@1820893135-pixel

Summary

sqlite3_rekey_v2() computes the new-key length with nKey = strlen(pKey) whenever pKey is non-NULL and nKey < 0, without verifying that pKey is NUL-terminated. Passing a non-NUL-terminated key buffer with a negative nKey makes strlen() scan past the end of the heap buffer, producing an ASan heap-buffer-overflow (READ of size 6 past a 13-byte region). Same root cause as sqlite3_key_v2 (sqlite3.c:114458), here at sqlite3.c:114482.

  • Affected versions: SQLCipher 4.17.0 (SQLite kernel 3.53.3), commit 810db22f575ee7cf94ea96a3e91622b5fcece3dc
  • Severity: High (heap out-of-bounds read; DoS + potential heap info disclosure)
  • CWE: CWE-125 (Out-of-bounds Read)

Detail Gifferent from #605

Affected code

/* src/sqlcipher.c:3736 / amalgamation sqlite3.c:114482 (sqlite3_rekey_v2) */
SQLITE_API int sqlite3_rekey_v2(sqlite3 *db, const char *zDb, const void *pKey, int nKey) {
  sqlcipher_log(...);
  if(pKey && nKey < 0) {
    nKey = strlen(pKey);       /* <-- unbounded strlen on possibly non-NUL-terminated pKey */
  }
  ...
}

Identical pattern to sqlite3_key_v2 (sqlite3.c:114458). All four entry points sqlite3_key / sqlite3_key_v2 / sqlite3_rekey / sqlite3_rekey_v2 are affected.

Root cause

A key buffer that is not NUL-terminated (binary key material from file/network/hardware-token) combined with nKey = -1 drives strlen(pKey) past the heap allocation boundary, returning a bogus length that is then used by sqlcipher_cipher_ctx_set_pass() in a memcpy(ctx->pass, zKey, L) — a second OOB read of the rekey path.

POC (tested on the unmodified source)

A 44-byte input (MD5 6622bc8768c32fe7cc1320da3a1a9118) triggers the sqlite3_rekey_v2 path. Recreate it byte-for-byte:

printf '%s' '0500ffffff84796b65790a505241474d41206369706865725f2d656d6f72795f73656375726974793d4f4e3b' | xxd -r -p > poc2.bin
ASAN_OPTIONS=detect_leaks=0:abort_on_error=1 ./sqlcipher_key_fuzzer poc2.bin

Trigger result

==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7b95cf8e005d
READ of size 6 at 0x7b95cf8e005d thread T0
    #0 ... in strlen sanitizer_common_interceptors.inc:425:5
    #1 ... in sqlite3_rekey_v2 /src/sqlcipher/sqlite3.c:114482:12
    #2 ... in LLVMFuzzerTestOneInput /work/harness.c:164:5
0x7b95cf8e005d is located 0 bytes after 13-byte region [0x7b95cf8e0050,0x7b95cf8e005d)
SUMMARY: AddressSanitizer: heap-buffer-overflow /src/sqlcipher/sqlite3.c:114482:12 in sqlite3_rekey_v2
  • Replay exit code: 134 (SIGABRT), deterministic
  • Stability: reproduced on 2 independent replays
Image Image

Suggested fix

Same as for sqlite3_key_v2: do not call unbounded strlen() on pKey when nKey < 0; reject or use a bounded-length check, and validate nKey against the source-buffer size before the memcpy in sqlcipher_cipher_ctx_set_pass.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions