
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 عندما تبقى sqlite3_last_insert_rowid() مساوية لـ 0 بعد عملية INSERT في %_node التي لا تزال تُبلّغ عن النجاح. تتخطى nodeHashDelete القيمة 0. تقوم nodeRelease بعد SplitNode بتحرير RtreeNode بينما لا يزال جدول التجزئة يحتفظ بها. لاحقًا تصبح nodeHashLookup حالة use-after-free في الكومة. نفس nodeWrite موجودة على مسار geopoly.
لم يتم إثبات RCE. قراءة ASan في nodeHashLookup. الإصلاح اللاحق في الفرع 3.53 هو SQLITE_CORRUPT_VTAB عندما يبقى رقم العقدة المُسنَد مساويًا لـ 0. هذا الفحص غير موجود في هذا الإصدار GA.
| المعرّف | لا يوجد CVE بعد |
| الفئة | UAF (heap use-after-free لـ RtreeNode؛ لم يتم إثبات RCE) |
| النطاق | محلي (SQL غير موثوق أو ملف .db غير موثوق على جدول rtree/geopoly) |
| 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 من المهاجم أو trigger مزروع في الجدول الظل / %_node من نوع WITHOUT ROWID |
| الترخيص | GNU Affero GPL v3.0 |
| المختبر | 127.0.0.1:18890 فقط. إثبات ASan. لا حمولة استغلال. |
على جدول rtree أو geopoly، اجعل INSERT للعقدة يُبلّغ عن النجاح بينما تبقى last_insert_rowid() مساوية لـ 0. الطرق الموثّقة: استبدال %_node بنسخة WITHOUT ROWID، أو زرع BEFORE INSERT RAISE(IGNORE) على الجدول الظل، ثم إعادة الفتح بحيث يصبح last rowid للاتصال مساويًا لـ 0. كرّر INSERT حتى يحدث انقسام للعقدة. تُجزّأ العقدة الشقيقة اليمنى كعقدة 0، وتُحرَّر، وتبقى قابلة للعثور عليها.
ثم تستخدم العملية المضيفة RtreeNode محرَّرة. المختبر هو heap-use-after-free من AddressSanitizer. التحكم في مؤشر التعليمات غير مشمول في هذه الحزمة. أما الانهيار فهو مشمول.
يتم تعيين SQLITE_VTAB_INNOCUOUS، لذا لا يزال rtree يعمل مع تعطيل trusted_schema. البناء الافتراضي لا يعيّن SQLITE_DEFAULT_DEFENSIVE. لا يزال trigger مزروع مسبقًا في ملف DB غير موثوق يعمل عند تنفيذ INSERT الخاص بـ pWriteNode داخل rtree نفسه.
عشرون عملية بحث في المصدر لـ 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 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 يبحث في الـ hash قبل رفض iNode<=0. الإصابة على المدخل الصفري المحرَّر هي الـ UAF. الفشل في العثور على iNode<=0 هو SQLITE_CORRUPT_VTAB، وهو مسار مختلف.
المسارات الخاطئة المسجَّلة مسبقًا: التعامل مع %_rowid last_insert_rowid 0 على أنه هذا العلة (ذلك يعيّن cell rowid 0، وليس الـ hash UAF)؛ توقّع SQLITE_CORRUPT_VTAB على هذا الـ pin (ذلك هو الإصلاح اللاحق)؛ ملء 50 خلية بحيث لا يحدث split؛ زرع الـ trigger وعدم إعادة الفتح؛ lookaside يخفي الـ free عن ASan؛ تسمية الـ crash بـ RCE.
cd lab
./run.sh
Amalgamation 3.53.4 مع -DSQLITE_ENABLE_RTREE=1 و-fsanitize=address. اختبار rtreeI.test المورّد 2.0-2.2: ملء 51 صفًا (RTREE_MAXCELLS)، BEFORE INSERT RAISE(IGNORE) على %_node، إعادة فتح last_insert_rowid()==0، إدراج الصف 52 (انقسام)، ثم SELECT *. انقسام التحكم بدون المشغّل سليم. ربط 127.0.0.1:18890. أداة الاختبار هي 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)