heap-buffer-overflow at sessionfuzz
(1) By qbit (junwha0511) on 2023-09-07 09:21:56 [link] [source]
Hi we found a heap-buffer-overflow bug from SQLite3 with our custom tool.
OS: Ubuntu 22.04 SQLite3 fossil-version: da4b7385 bug location: sqlite3.c:220260:11
you can also trigger the bug with Addreses Sanitizer, with following commands
export CC=/usr/bin/clang-15
export CFLAGS="-DSQLITE_OMIT_LOOKASIDE -fsanitize=address -g"
export LDFLAGS=$CFLAGS
export ASAN_OPTIONS=detect_leaks=0
mkdir build && cd build
../configure
make -j`nproc` sessionfuzz
./sessionfuzz run -v ../test/sessionfuzz-data1.db
The root cause is that it doesn't validate the pIn->iNext on reading aVal. (but we couldn't identify what is the reason invalid eType is there)
static int sessionReadRecord(
SessionInput *pIn, /* Input data */
int nCol, /* Number of values in record */
u8 *abPK, /* Array of primary key flags, or NULL */
sqlite3_value **apOut, /* Write values to this array */
int *pbEmpty
){
...
if( rc==SQLITE_OK ){
u8 *aVal = &pIn->aData[pIn->iNext]; //! [A] pIn->iNext must be validated
if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){
int nByte;
pIn->iNext += sessionVarintGet(aVal, &nByte);
rc = sessionInputBuffer(pIn, nByte);
if( rc==SQLITE_OK ){
if( nByte<0 || nByte>pIn->nData-pIn->iNext ){
rc = SQLITE_CORRUPT_BKPT;
}else{
u8 enc = (eType==SQLITE_TEXT ? SQLITE_UTF8 : 0);
rc = sessionValueSetStr(apOut[i],&pIn->aData[pIn->iNext],nByte,enc);
pIn->iNext += nByte;
}
}
}
if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
sqlite3_int64 v = sessionGetI64(aVal); //! [B] bug triggered**
if( eType==SQLITE_INTEGER ){
sqlite3VdbeMemSetInt64(apOut[i], v);
}else{
double d;
memcpy(&d, &v, 8);
sqlite3VdbeMemSetDouble(apOut[i], d);
}
pIn->iNext += 8;
}
}
...
Here, it reads 8-bytes region from pIn->aData[pIn->iNext]
,
but it was out-of-bound access on 1-byte accessible area because here pIn->iNext
is 0x25
, and pIn->nData
is 0x26
.
The patch can be as follows.
static int sessionReadRecord(
SessionInput *pIn, /* Input data */
int nCol, /* Number of values in record */
u8 *abPK, /* Array of primary key flags, or NULL */
sqlite3_value **apOut, /* Write values to this array */
int *pbEmpty
){
...
if( rc==SQLITE_OK ){
u8 *aVal = &pIn->aData[pIn->iNext];
if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){
int nByte;
pIn->iNext += sessionVarintGet(aVal, &nByte);
rc = sessionInputBuffer(pIn, nByte);
if( rc==SQLITE_OK ){
if( nByte<0 || nByte>pIn->nData-pIn->iNext ){
rc = SQLITE_CORRUPT_BKPT;
}else{
u8 enc = (eType==SQLITE_TEXT ? SQLITE_UTF8 : 0);
rc = sessionValueSetStr(apOut[i],&pIn->aData[pIn->iNext],nByte,enc);
pIn->iNext += nByte;
}
}
}
if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
#ifndef DISABLE_PATCH
if( pIn->iNext+sizeof(sqlite3_int64)>pIn->nData ){
rc = SQLITE_CORRUPT_BKPT;
} else {
#endif
sqlite3_int64 v = sessionGetI64(aVal);
if( eType==SQLITE_INTEGER ){
sqlite3VdbeMemSetInt64(apOut[i], v);
}else{
double d;
memcpy(&d, &v, 8);
sqlite3VdbeMemSetDouble(apOut[i], d);
}
pIn->iNext += 8;
}
#ifndef DISABLE_PATCH
}
#endif
}
...
---------- ASAN report -----------
==3125996==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6120000482f8 at pc 0x555555ad569f bp 0x7fffffffcb40 sp 0x7fffffffcb38
READ of size 1 at 0x6120000482f8 thread T0
#0 0x555555ad569e in sessionGetI64 /home/qbit/SQLite-da4b7385/build/./sqlite3.c:220260:11
#1 0x555555adf5a8 in sessionReadRecord /home/qbit/SQLite-da4b7385/build/./sqlite3.c:223159:27
#2 0x555555adbc82 in sessionChangesetNextOne /home/qbit/SQLite-da4b7385/build/./sqlite3.c:223414:15
#3 0x55555572da8d in sessionChangesetNext /home/qbit/SQLite-da4b7385/build/./sqlite3.c:223483:10
#4 0x55555572d93e in sqlite3changeset_next /home/qbit/SQLite-da4b7385/build/./sqlite3.c:223497:10
#5 0x555555731744 in sessionChangesetApply /home/qbit/SQLite-da4b7385/build/./sqlite3.c:224809:39
#6 0x555555731198 in sqlite3changeset_apply_v2 /home/qbit/SQLite-da4b7385/build/./sqlite3.c:224993:10
#7 0x5555557332d7 in sqlite3changeset_apply /home/qbit/SQLite-da4b7385/build/./sqlite3.c:225020:10
#8 0x555555739bd9 in main /home/qbit/SQLite-da4b7385/build/../test/sessionfuzz.c:972:16
#9 0x7ffff7c29d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#10 0x7ffff7c29e3f in __libc_start_main csu/../csu/libc-start.c:392:3
#11 0x555555600404 in _start (/home/qbit/SQLite-da4b7385/build/sessionfuzz+0xac404) (BuildId: 00776f96c0e0db6f20fbbb083d69175ab983a6e5)
0x6120000482f8 is located 0 bytes to the right of 312-byte region [0x6120000481c0,0x6120000482f8)
allocated by thread T0 here:
#0 0x555555685e2e in __interceptor_malloc (/home/qbit/SQLite-da4b7385/build/sessionfuzz+0x131e2e) (BuildId: 00776f96c0e0db6f20fbbb083d69175ab983a6e5)
#1 0x555555abfaa6 in sqlite3MemMalloc /home/qbit/SQLite-da4b7385/build/./sqlite3.c:26160:7
#2 0x55555573b410 in mallocWithAlarm /home/qbit/SQLite-da4b7385/build/./sqlite3.c:29862:7
#3 0x5555556c4383 in sqlite3Malloc /home/qbit/SQLite-da4b7385/build/./sqlite3.c:29908:5
#4 0x55555573c6dc in dbMallocRawFinish /home/qbit/SQLite-da4b7385/build/./sqlite3.c:30213:7
#5 0x55555573c564 in sqlite3DbMallocRawNN /home/qbit/SQLite-da4b7385/build/./sqlite3.c:30295:10
#6 0x5555556f8657 in sqlite3DbMallocRaw /home/qbit/SQLite-da4b7385/build/./sqlite3.c:30244:19
#7 0x5555557c327e in sqlite3VdbeMemGrow /home/qbit/SQLite-da4b7385/build/./sqlite3.c:82021:21
#8 0x5555557c5bce in vdbeMemAddTerminator /home/qbit/SQLite-da4b7385/build/./sqlite3.c:82115:7
#9 0x5555556ea5b3 in sqlite3VdbeMemMakeWriteable /home/qbit/SQLite-da4b7385/build/./sqlite3.c:82138:16
#10 0x5555556ed6b9 in sqlite3VdbeMemCopy /home/qbit/SQLite-da4b7385/build/./sqlite3.c:82859:12
#11 0x5555556ed425 in sqlite3_result_value /home/qbit/SQLite-da4b7385/build/./sqlite3.c:89812:3
#12 0x55555573b07d in sqlarUncompressFunc /home/qbit/SQLite-da4b7385/build/../test/sessionfuzz.c:730:5
#13 0x555555819a09 in sqlite3VdbeExec /home/qbit/SQLite-da4b7385/build/./sqlite3.c:100392:3
#14 0x5555556ef780 in sqlite3Step /home/qbit/SQLite-da4b7385/build/./sqlite3.c:90003:10
#15 0x5555556dbe25 in sqlite3_step /home/qbit/SQLite-da4b7385/build/./sqlite3.c:90064:16
#16 0x555555739934 in main /home/qbit/SQLite-da4b7385/build/../test/sessionfuzz.c:964:28
#17 0x7ffff7c29d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
SUMMARY: AddressSanitizer: heap-buffer-overflow /home/qbit/SQLite-da4b7385/build/./sqlite3.c:220260:11 in sessionGetI64
Shadow bytes around the buggy address:
0x0c2480001000: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd
0x0c2480001010: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2480001020: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
0x0c2480001030: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
0x0c2480001040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c2480001050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00[fa]
0x0c2480001060: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd
0x0c2480001070: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2480001080: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
0x0c2480001090: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd
0x0c24800010a0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==3125996==ABORTING
Thank you
(2) By Dan Kennedy (dan) on 2023-09-07 15:10:41 in reply to 1 [source]
Thanks for reporting this. Should now be fixed here:
https://sqlite.org/src/info/0e4e7a05c4204b47
Dan.
(3) By qbit (junwha0511) on 2023-09-12 07:43:05 in reply to 2 [link] [source]
Thanks for quickly addressing the heap-buffer-overflow I reported!:)
Could I kindly ask you to register this as a CVE, similar to prior buffer-overflow issues like CVE-2022-35737?
(4) By Richard Hipp (drh) on 2023-09-12 11:31:02 in reply to 3 [link] [source]
Thank you for reporting the issue.
We do not do CVEs. If you want to issue a CVE, that is your business and we will not try to stop you. But we do not participate in the CVE system. See https://www.sqlite.org/cves.html for additional information.