
كاشف وإثبات مفهوم لثغرة كتابة في ذاكرة التخزين المؤقت للصفحات بنواة لينكس (CVE-2026-31431) في algif_aead، بما في ذلك ماسح غير مدمر واستغلال لتصعيد الامتيازات محليًا.
يحتوي هذا المستودع على أداة الكشف وPoC لثغرة الكتابة الخاطئة في ذاكرة التخزين المؤقت للصفحات (page cache scratch-write) في algif_aead / authencesn بنظام Linux، والمعروفة باسم CVE-2026-31431.
مقالة الإفصاح: https://xint.io/blog/copy-fail-linux-distributions
يُسمح باستخدام هذه الأدوات فقط على الأجهزة التي تمتلكها أو التي لديك إذن صريح لاستخدامها عليها. أداة الكشف غير مدمرة وتتعامل فقط مع ملفات sentinel في دليل مؤقت؛ بينما تعد PoC وLPE تقنيات حقيقية لتصعيد الامتيازات المحلية لأنها تعدّل حالة ذاكرة التخزين المؤقت للصفحات في الذاكرة، وقد يكون تشغيلها دون إذن غير قانوني.
ينفّذ algif_aead عمليات AEAD في مكانها (in-place)، أي أن req->src == req->dst. عندما يتم إدخال البيانات عبر splice() من ملف عادي، تحتوي قائمة scatterlist الهدف على مراجع لصفحات ذاكرة التخزين المؤقت لهذا الملف، مما قد يؤدي إلى كتابة النواة في نسخة ذاكرة التخزين المؤقت للصفحات الخاصة بالملف.
يقوم authencesn(hmac(sha256),cbc(aes)) بكتابة خاطئة بحجم 4 بايت في حقل seqno_lo داخل AAD (البايتات من 4 إلى 7 في AAD). عند دمج ذلك مع خاصية AEAD في المكان ومسار splice()، يمكن للمهاجم جعل هذه الـ 4 بايتات تقع في صفحة ذاكرة تخزين مؤقت لملف قابل للقراءة.
لا يتم كتابة هذا التعديل مرة أخرى إلى القرص، بل يؤثر فقط على ذاكرة التخزين المؤقت للصفحات الحالية في النواة. لذلك تبقى محتويات الملف على القرص دون تغيير، لكن القراء الذين يشاركون نفس ذاكرة التخزين المؤقت سيرون المحتوى الملوّث. يمكن استهداف ملفات قابلة للقراءة عالميًا مثل /etc/passwd و/usr/bin/su.
يتطلب تثبيت Rust toolchain وCargo على الجهاز.
بناء جميع ثنائيات Rust:
cargo build --release --bins
بعد اكتمال البناء، سيتم إنشاء:
target/release/cve_2026_31431_detector
target/release/cve_2026_31431_poc
إذا كنت ترغب في إرسال ملفات مُجمّعة مسبقًا في المستودع، فضعها في:
dist/linux-x86_64/cve_2026_31431_detector
dist/linux-x86_64/cve_2026_31431_poc
dist/linux-x86_64/SHA256SUMS
لا ترسل دليل target/ بالكامل؛ فهو يحتوي على منتجات Cargo الوسيطة وذاكرة التخزين المؤقت المحلية.
بناء أداة الكشف غير المدمرة فقط:
cargo build --release --bin cve_2026_31431_detector
بناء نسخة Rust من poc.py فقط:
cargo build --release --bin cve_2026_31431_poc
يُوصى باستخدام أداة الكشف غير المدمرة بلغة Rust:
./target/release/cve_2026_31431_detector
echo $?
يمكن أيضًا تشغيلها مباشرة عبر Cargo:
cargo run --release --bin cve_2026_31431_detector
echo $?
استخدام أداة الكشف بلغة Python:
python3 test_cve_2026_31431.py
echo $?
معنى رموز الخروج:
| رمز الخروج | المعنى |
|---|---|
0 | لم يتم اكتشاف ثغرة، أو لم تتحقق الشروط المسبقة، مثل عدم توفر AF_ALG / authencesn. |
تفسير المخرجات الشائعة:
العمليات التي تنفذها أداة الكشف:
AF_ALG وauthencesn(hmac(sha256),cbc(aes)).sendmsg مع تعيين seqno_lo في AAD على marker PWND.splice() إلى op socket الخاص بـ AF_ALG.recv() لدفع تنفيذ الخوارزمية.لا تعدّل أداة الكشف ملفات /usr/bin/su أو /etc/passwd أو أي ملفات نظام أخرى. يتم حذف ملف sentinel المؤقت عند الخروج.
نسخة Rust من poc.py:
./target/release/cve_2026_31431_poc
أو:
cargo run --release --bin cve_2026_31431_poc
ملاحظة: تفتح هذه الـ PoC ملف /usr/bin/su وفقًا لمنطق poc.py، وتلوّث نسخة ذاكرة التخزين المؤقت الخاصة به عبر بدائية الثغرة، ثم تنفّذ su. هذه ليست عملية كشف غير مدمرة، ويجب تشغيلها فقط في بيئة اختبار مصرح بها.
python3 exploit_cve_2026_31431.py
python3 exploit_cve_2026_31431.py --shell
يبحث هذا السكربت عن حقل UID الخاص بالمستخدم الحالي في /etc/passwd ويحاول تغيير UID في ذاكرة التخزين المؤقت إلى 0000. لا يتم تعديل ملف /etc/passwd على القرص، لكن عمليات النظام التي تقرأ ذاكرة التخزين المؤقت قد ترى المحتوى الملوّث.
الشروط المسبقة:
1000 إلى 9999.nscd وsssd وsystemd-userdbd تغييرات ذاكرة التخزين المؤقت لـ /etc/passwd./etc/passwd موجودة بين تطبيق التصحيح وتنفيذ su.تنظيف ذاكرة التخزين المؤقت:
python3 -c "import os; fd=os.open('/etc/passwd', os.O_RDONLY); os.posix_fadvise(fd, 0, 0, os.POSIX_FADV_DONTNEED); os.close(fd)"
إذا حصلت بالفعل على shell بصلاحيات root، يمكنك أيضًا تنفيذ:
echo 3 > /proc/sys/vm/drop_caches
إعادة التشغيل تمسح أيضًا حالة ذاكرة التخزين المؤقت.
قبل إصدار إصلاح من توزيعة Linux، يمكن تعطيل algif_aead:
sudo tee /etc/modprobe.d/disable-algif-aead.conf <<<'install algif_aead /bin/false'
sudo rmmod algif_aead 2>/dev/null
بعد تطبيق التخفيف، يجب أن تُخرج أداة الكشف عادةً نتيجة الكشف: لم يتم العثور على ثغرة مع توضيح أن الشروط المسبقة للتفعيل غير متوفرة، ورمز الخروج 0.
فكرة الإصلاح من الجهة العليا هي إعادة عمليات AEAD من المعالجة في المكان إلى المعالجة غير الموضعية، لتجنب دخول صفحات ذاكرة التخزين المؤقت إلى قائمة scatterlist الوجهة القابلة للكتابة.
| الملف | الوصف |
|---|
test_cve_2026_31431.py | أداة كشف غير مدمرة بلغة Python. تتعامل فقط مع ملفات sentinel مؤقتة ولا تلمس ملفات النظام. |
src/main.rs | أداة كشف غير مدمرة بلغة Rust. منطق الكشف ورموز الخروج مطابقة لأداة Python. |
src/bin/poc.rs | نسخة Rust من poc.py. تلوّث ذاكرة التخزين المؤقت لـ /usr/bin/su وتنفّذ su. |
poc.py | PoC بلغة Python. |
exploit_cve_2026_31431.py | LPE بلغة Python. يحاول الحصول على shell بصلاحيات root عبر تلويث ذاكرة التخزين المؤقت لـ /etc/passwd. |
2 |
| تم اكتشاف قابلية التأثر بـ CVE-2026-31431. |
1 | حدث خطأ أثناء عملية الاختبار، ولا يمكن استخدام النتيجة كحكم على وجود الثغرة. |
| المخرجات | الاستنتاج |
|---|
نتيجة الكشف: لم يتم العثور على ثغرة | لم يتم اكتشاف ثغرة، أو لم تتحقق الشروط المسبقة للتفعيل. |
نتيجة الكشف: توجد ثغرة CVE-2026-31431 | نجح marker PWND في الوصول إلى صفحة ذاكرة التخزين المؤقت المُدخلة عبر splice()، مما يعني وجود الثغرة. |
نتيجة الكشف: توجد ثغرة CVE-2026-31431 مشتبه بها | تم تعديل ذاكرة التخزين المؤقت للصفحات، حتى لو لم يصل marker إلى الموضع المتوقع، يجب اعتبار النظام متأثرًا. |
حدث خطأ أثناء عملية الاختبار، لا يمكن تحديد وجود الثغرة | فشل الكشف، رمز الخروج 1، يجب التحقق من رسالة الخطأ وإعادة التشغيل. |