
SQLite 3.53.4 - उच्च - स्थानीय - UAF - rtree last_insert_rowid 0 node hash
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · sqlite-rtree-rowid0
लेख: https://abraxaslabs.tech/research/sqlite-rtree-rowid0
वर्ग: UAF पहुँच: स्थानीय
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 रहता है और INSERT फिर भी OK रिपोर्ट करता है। nodeHashDelete 0 को छोड़ देता है। SplitNode के बाद nodeRelease उस RtreeNode को मुक्त कर देता है जबकि हैश अभी भी उसे रखे हुए है। बाद में nodeHashLookup एक हीप use-after-free बन जाता है। वही nodeWrite geopoly पथ पर भी मौजूद है।
RCE प्रदर्शित नहीं किया गया। nodeHashLookup में ASan READ। बाद का branch-3.53 फ़िक्स तब SQLITE_CORRUPT_VTAB देता है जब आवंटित नोड संख्या अभी भी 0 हो। वह जाँच इस GA पर नहीं है।
| ID | अभी कोई CVE नहीं |
| वर्ग | UAF (RtreeNode का हीप use-after-free; RCE प्रदर्शित नहीं) |
| पहुँच | स्थानीय (rtree/geopoly तालिका पर अविश्वसनीय SQL या अविश्वसनीय .db) |
| CWE | CWE-416 |
| CVSS | उच्च: 8.1 CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H |
| उत्पाद | SQLite rtree / geopoly (SQLITE_ENABLE_RTREE) |
| प्रभावित | 3.53.4 (b09c88c) |
| प्रमाणीकरण | हमलावर SQL या छिपी हुई तालिका पर रोपा गया ट्रिगर / WITHOUT ROWID %_node |
| लाइसेंस | GNU Affero GPL v3.0 |
| लैब | केवल 127.0.0.1:18890। ASan साक्ष्य। कोई एक्सप्लॉइट पेलोड नहीं। |
किसी rtree या geopoly तालिका पर, नोड INSERT को OK रिपोर्ट करवाएँ जबकि last_insert_rowid() 0 रहे। प्रलेखित तरीके: %_node को WITHOUT ROWID से बदलें, या छिपी हुई तालिका पर BEFORE INSERT RAISE(IGNORE) रोपें, फिर दोबारा खोलें ताकि कनेक्शन का अंतिम rowid 0 हो जाए। तब तक INSERT करें जब तक कोई नोड विभाजित न हो जाए। दायाँ सहोदर नोड 0 के रूप में हैश होता है, मुक्त किया जाता है, और फिर भी खोजा जा सकता है।
इसके बाद होस्ट प्रक्रिया एक मुक्त किए गए RtreeNode का उपयोग करती है। लैब में AddressSanitizer heap-use-after-free है। इस पैक में इंस्ट्रक्शन-पॉइंटर नियंत्रण शामिल नहीं है। क्रैश शामिल है।
SQLITE_VTAB_INNOCUOUS सेट है, इसलिए trusted_schema बंद होने पर भी rtree चलता रहता है। डिफ़ॉल्ट कंपाइल SQLITE_DEFAULT_DEFENSIVE सेट नहीं करता। अविश्वसनीय DB फ़ाइल में पहले से रोपा गया ट्रिगर तब भी चलता है जब rtree का अपना pWriteNode INSERT निष्पादित होता है।
https://github.com/sqlite/sqlite टैग https://github.com/sqlite/sqlite/tree/version-3.53.4 के बीस स्रोत अन्वेषण। विहित ट्री https://sqlite.org/src है। GitHub एक Fossil मिरर है। 3.54.0 अभी भी ड्राफ़्ट है। यह अवशेष अतिरिक्त -DSQLITE_ENABLE_RTREE का विशिष्ट परिणाम है (आधिकारिक अनुशंसित कंपाइल, Windows nmake OPTS, autoconf फ़ॉलबैक, और 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 को इस बग के रूप में मानना (वह सेल rowid 0 निर्दिष्ट करता है, हैश UAF नहीं); इस पिन पर SQLITE_CORRUPT_VTAB की अपेक्षा करना (वह बाद का फिक्स है); 50 सेल भरना ताकि कोई स्प्लिट न हो; ट्रिगर लगाकर फिर से न खोलना; lookaside द्वारा ASan से फ्री को छिपाना; क्रैश को RCE कहना।
cd lab
./run.sh
-DSQLITE_ENABLE_RTREE=1 और -fsanitize=address के साथ Amalgamation 3.53.4। Vendor rtreeI.test 2.0-2.2: 51 पंक्तियाँ भरें (RTREE_MAXCELLS), %_node पर BEFORE INSERT RAISE(IGNORE), last_insert_rowid()==0 को फिर से खोलें, 52वीं पंक्ति INSERT करें (split), फिर SELECT *। ट्रिगर के बिना नियंत्रण split ठीक है। 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)