
SQLite 3.53.4 - उच्च - स्थानीय - UAF - rtree last_insert_rowid 0 node hash
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · sqlite-rtree-rowid0
Class: UAF Reach: Local
SQLite 3.53.4 (b09c88c14082339b66c7b7158d609a771e64ca69, SOURCE_ID 2026-07-24 19:02:57 bf7c7f30031888f4e796e429ab3978879485813aaca6f641c7b33e4e09459bcc) - Hwaci
nodeWrite एक नए rtree नोड को iNode==0 के साथ हैश करता है जब %_node में INSERT के बाद sqlite3_last_insert_rowid() 0 ही रहता है, जो अभी भी OK रिपोर्ट करता है। nodeHashDelete 0 को छोड़ देता है। SplitNode के बाद nodeRelease RtreeNode को मुक्त कर देता है जबकि हैश अभी भी उसे रखे हुए है। बाद में nodeHashLookup एक heap use-after-free है। वही nodeWrite geopoly पथ पर भी है।
RCE प्रदर्शित नहीं। nodeHashLookup में ASan READ। बाद का branch-3.53 फिक्स SQLITE_CORRUPT_VTAB है जब असाइन किया गया नोड नंबर अभी भी 0 हो। वह जाँच इस GA पर नहीं है।
| ID | अभी तक कोई CVE नहीं |
| Class | UAF (RtreeNode का heap use-after-free; RCE प्रदर्शित नहीं) |
| Reach | Local (rtree/geopoly तालिका पर अविश्वसनीय SQL या अविश्वसनीय .db) |
| CWE | CWE-416 |
| CVSS | High: 8.1 CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H |
| Product | SQLite rtree / geopoly (SQLITE_ENABLE_RTREE) |
| Affected | 3.53.4 (b09c88c) |
| Auth | हमलावर SQL या एक रोपा गया shadow-table trigger / WITHOUT ROWID %_node |
| License | GNU Affero GPL v3.0 |
| Lab | केवल 127.0.0.1:18890। ASan साक्षी। कोई exploit payload नहीं। |
एक rtree या geopoly तालिका पर, नोड INSERT को OK रिपोर्ट करवाएँ जबकि last_insert_rowid() 0 ही रहे। प्रलेखित तरीके: %_node को WITHOUT ROWID से बदलें, या shadow तालिका पर BEFORE INSERT RAISE(IGNORE) रोपें, फिर पुनः खोलें ताकि कनेक्शन का last rowid 0 हो। नोड स्प्लिट होने तक INSERT करें। दायाँ sibling नोड 0 के रूप में हैश होता है, मुक्त हो जाता है, और फिर भी खोजा जा सकता है।
इसके बाद होस्ट प्रक्रिया एक मुक्त RtreeNode का उपयोग करती है। Lab AddressSanitizer heap-use-after-free है। instruction-pointer नियंत्रण इस पैक में नहीं है। क्रैश है।
SQLITE_VTAB_INNOCUOUS सेट है, इसलिए rtree अभी भी trusted_schema बंद के साथ चलता है। डिफ़ॉल्ट कंपाइल SQLITE_DEFAULT_DEFENSIVE सेट नहीं करता। एक अविश्वसनीय DB फ़ाइल में पहले से रोपा गया trigger अभी भी चलता है जब rtree का अपना pWriteNode INSERT निष्पादित होता है।
https://github.com/sqlite/sqlite टैग https://github.com/sqlite/sqlite/tree/version-3.53.4 की बीस स्रोत खोजें। Canonical tree https://sqlite.org/src है। GitHub एक Fossil मिरर है। 3.54.0 अभी भी एक ड्राफ्ट है। यह अवशेष विशिष्ट अतिरिक्त -DSQLITE_ENABLE_RTREE है (आधिकारिक अनुशंसित कंपाइल, Windows nmake OPTS, autoconf fallback, और fuzzcheck सभी इसे सेट करते हैं)।
if( pNode->iNode==0 && rc==SQLITE_OK ){
pNode->iNode = sqlite3_last_insert_rowid(pRtree->db);
nodeHashInsert(pRtree, pNode);
}
static void nodeHashDelete(Rtree *pRtree, RtreeNode *pNode){
RtreeNode **pp;
if( pNode->iNode!=0 ){
pp = &pRtree->aHash[nodeHash(pNode->iNode)];
for( ; (*pp)!=pNode; pp = &(*pp)->pNext){ assert(*pp); }
*pp = pNode->pNext;
pNode->pNext = 0;
}
}
nodeAcquire iNode<=0 को अस्वीकार करने से पहले हैश को देखता है। मुक्त शून्य प्रविष्टि पर हिट ही UAF है। iNode<=0 पर मिस SQLITE_CORRUPT_VTAB है, जो एक अलग पथ है।
पहले से दर्ज गलत मोड़: %_rowid last_insert_rowid 0 को इस बग के रूप में मानना (वह cell rowid 0 असाइन करता है, हैश UAF नहीं); इस पिन पर SQLITE_CORRUPT_VTAB की अपेक्षा करना (वह बाद का फिक्स है); 50 cells भरना ताकि कोई स्प्लिट न हो; trigger रोपना और पुनः न खोलना; lookaside द्वारा ASan से free छिपाना; क्रैश को RCE कहना।
cd lab
./run.sh
Amalgamation 3.53.4 -DSQLITE_ENABLE_RTREE=1 और -fsanitize=address के साथ। Vendor rtreeI.test 2.0-2.2: 51 पंक्तियाँ भरें (RTREE_MAXCELLS), %_node पर BEFORE INSERT RAISE(IGNORE), last_insert_rowid()==0 पुनः खोलें, 52वीं पंक्ति INSERT करें (स्प्लिट), फिर SELECT *। trigger के बिना नियंत्रण स्प्लिट OK है। 127.0.0.1:18890 बाइंड करें। Harness lab/harness.c है।
control-split=ok
reopen-last-rowid=0
witness-before-split=SQLITE-RTREE-ROWID0-WITNESS
ERROR: AddressSanitizer: heap-use-after-free
READ of size 8 ... nodeHashLookup
freed by ... nodeRelease / SplitNode
SUCCESS sqlite-rtree-rowid0 how=asan-uaf-nodehash SQLITE-RTREE-ROWID0-WITNESS
sqlite3_last_insert_rowid() के बाद, यदि iNode अभी भी 0 है, तो SQLITE_CORRUPT_VTAB लौटाएँ और nodeHashInsert न करें। branch-3.53 11ce330557 / Git 63b6d705 (2026-09-24) यही करता है। परीक्षण "database disk image is malformed" की अपेक्षा करता है। यह GA नहीं करता।
b09c88c14082339b66c7b7158d609a771e64ca69)2026-07-24 19:02:57 bf7c7f30031888f4e796e429ab3978879485813aaca6f641c7b33e4e09459bccnodeWrite, nodeHashDelete, nodeRelease, nodeAcquire, SplitNode11ce330557 (2026-09-24, Claude / Ada Logics)