
إثبات مفهوم لاستغلال CVE-2026-31431، وهو تصعيد صلاحيات محلي في نواة لينكس عبر كتابة ذاكرة التخزين المؤقت للصفحات في AF_ALG، مما يحقق صلاحيات الجذر على التوزيعات الرئيسية.
algif_aead كتابة ذاكرة التخزين المؤقت للصفحات ("Copy Fail")
المؤلف: Van Glenndon Enad
الاكتشاف الأصلي: Theori / Xint Code Research Team (Taeyang Lee)
تاريخ النشر: 29 أبريل 2026
الخطورة: عالية
درجة CVSS v3.1: 7.8
متجه CVSS v3.1: CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
CWE: CWE-787 (كتابة خارج الحدود)، CWE-269 (إدارة امتيازات غير سليمة)
CVE-2026-31431، المعروفة علنًا باسم "Copy Fail"، هي ثغرة تصعيد امتيازات محلية (LPE) عالية الخطورة في وحدة algif_aead بنواة لينكس — واجهة تشفير AEAD الخاصة بواجهة برمجة التطبيقات المشفرة لمستخدمي النواة (AF_ALG). ينبع الخلل من تحسين أداء (العملية في المكان) تم تقديمه في عام 2017 عبر الالتزام 72548b093ee3، والذي سمح عن غير قصد بوضع صفحات ملفات مدعومة بذاكرة التخزين المؤقت للصفحات في قائمة التشتت الوجهة القابلة للكتابة أثناء عملية تشفير AEAD.
من خلال ربط ثلاثة أنظمة فرعية للنواة — مقابس AF_ALG، واستدعاء النظام splice()، وسلوك الكتابة المؤقتة لخوارزمية authencesn — يمكن لمستخدم محلي غير مميز تنفيذ كتابة محكومة من 4 بايت في ذاكرة التخزين المؤقت للصفحات لأي ملف قابل للقراءة. باستهداف ثنائي setuid مثل /usr/bin/su، تُفسد هذه الكتابة صورة التنفيذ في الذاكرة دون تعديل الملف على القرص، متجاوزةً بذلك أدوات سلامة الملفات على القرص. تصعيد الامتيازات الناتج إلى root هو حتمي — لا توجد حالة سباق، ولا إزاحات نواة خاصة بالتوزيعات، ولا امتيازات خاصة مطلوبة. استغلال Python عام متاح علنًا بحجم 732 بايت يمنح قذائف root على Ubuntu وAmazon Linux وRHEL وSUSE في تشغيل واحد غير معدّل.
| المكوّن | التفاصيل |
|---|---|
| النظام الفرعي المتأثر | crypto/algif_aead.c — واجهة AEAD الخاصة بـ AF_ALG في نواة لينكس |
| تاريخ إدخال الثغرة | نواة لينكس 4.14 (2017)، الالتزام 72548b093ee38a6d4f2a19e6ef1948ae05c181f7 |
| الإصدارات المُصلَّحة | 6.18.22، 6.19.12، 7.0 |
| التزام الإصلاح | a664bf3d603dc3bdcf9ae47cc21e0daec706d7a5 |
| التوزيعات المُتحقق منها | Ubuntu 24.04 LTS، Amazon Linux 2023، RHEL 10.1، SUSE 16 |
| المتأثرة ضمنيًا | Debian، Arch، Fedora، Rocky، AlmaLinux، Oracle Linux، وأي توزيعة تعمل بنواة غير مُصلَّحة مبنية منذ 2017 |
كانت الثغرة حاضرة بصمت في كل توزيعات لينكس الرئيسية لما يقارب تسع سنوات. وفقًا لـ Theori، فإن AF_ALG مفعّل في تكوين النواة الافتراضي لكل توزيعة تقريبًا، مما يعني عدم الحاجة لأي أعلام بناء أو إعدادات خاصة ليكون النظام عرضة للثغرة.
تكشف نواة لينكس البدائيات المشفرة لمستخدمي الفضاء عبر واجهة مقبس AF_ALG (crypto/algif_aead.c). في عام 2017، تم دمج تحسين أداء سمح لـ algif_aead بتنفيذ عمليات AEAD في المكان — إعادة استخدام مخزن الذاكرة المصدر كوجهة — لتجنب نسخ البيانات غير الضروري.
يظهر الخلل عندما يُدخل مستخدم الفضاء بيانات إلى مقبس AF_ALG عبر استدعاء النظام splice(). في هذه الحالة، تكون الصفحات الموضوعة في قائمة التشتت المصدر صفحات ذاكرة تخزين مؤقت — ذاكرة مشتركة مُدارة من النواة تدعم الملف المُقسَّم. بسبب تحسين العملية في المكان الذي يضبط req->src = req->dst، تنتهي صفحات ذاكرة التخزين المؤقت هذه في قائمة التشتت الوجهة القابلة للكتابة. تقوم خوارزمية authencesn لاحقًا بكتابة مؤقتة عند dst[assoclen + cryptlen]، والتي تُحل إلى إزاحة داخل صفحات ذاكرة التخزين المؤقت تلك — مما يكتب فعليًا بيانات يتحكم بها المهاجم في الصورة الذاكرية للملف المُقسَّم.
لأن ذاكرة التخزين المؤقت للصفحات مشتركة عبر المضيف بأكمله بما في ذلك الحاويات، فإن الكتابة من عملية واحدة تؤثر على الصفحات المخزنة مؤقتًا لذلك الملف لكل العمليات والحاويات على نفس النواة.
التغيير المخالف في algif_aead.c ضبط req->src = req->dst وسلسل صفحات العلامات من قائمة التشتت المصدر إلى قائمة التشتت الناتجة عبر sg_chain():
/* تحسين العملية في المكان لعام 2017 — الالتزام 72548b093ee3 */
req->src = req->dst; /* المصدر == الوجهة */
sg_chain(dst, n + 1, src_tag); /* صفحات العلامات مُسلسلة في dst القابلة للكتابة */
عند استخدام splice() لتغذية ملف في المقبس، تكون صفحات قائمة التشتت مدعومة بذاكرة التخزين المؤقت للصفحات، وليست ذاكرة خاصة مجهولة. تسلسلها في قائمة dst القابلة للكتابة ينتهك الافتراض بأن الوجهة هي ذاكرة خاصة قابلة للكتابة.
authencesnيكتب قالب authencesn قيمة مؤقتة لرقم التسلسل (seqno_lo، البايتات 4–7 من AAD) عند dst[assoclen + cryptlen]. لأن dst يحتوي الآن على صفحات ذاكرة تخزين مؤقت من الملف المُقسَّم، تهبط هذه الكتابة عند إزاحة يتحكم بها المهاجم داخل الصورة الذاكرية للملف:
/* الكتابة المؤقتة لـ authencesn — الإزاحة محددة بواسطة assoclen + cryptlen */
scatterwalk_map_and_copy(seqno, dst,
req->assoclen + req->cryptlen,
sizeof(seqno), 1); /* يكتب في ذاكرة التخزين المؤقت للصفحات */
البايتات الأربعة المكتوبة تتوافق مع seqno_lo، والتي يتحكم بها المهاجم عبر حمولة AAD المرسلة عبر sendmsg().
مقبس AF_ALG (SOCK_SEQPACKET)
│
│ splice() — يسلّم صفحات مدعومة بملف إلى المقبس
▼
تحسين العملية في المكان لـ algif_aead
│ req->src = req->dst
│ صفحات ذاكرة التخزين المؤقت تهبط في قائمة التشتت القابلة للكتابة
▼
الكتابة المؤقتة لـ authencesn
│ يكتب seqno_lo عند dst[assoclen + cryptlen]
│ = 4 بايت يختارها المهاجم عند إزاحة ملف يختارها المهاجم
▼
فساد ذاكرة التخزين المؤقت للصفحات (بدون تغيير على القرص)
الإصلاح (a664bf3d603d) يتراجع عن تحسين العملية في المكان بالكامل — يعمل algif_aead الآن دائمًا خارج المكان، مخصصًا مخزن وجهة منفصلًا. بما أن المصدر والوجهة يأتيان الآن من تعيينات مختلفة، لا يمكن لصفحات ذاكرة التخزين المؤقت في src أن تُصل إليها مسار كتابة dst أبدًا.
| المتطلب | ملاحظات |
|---|---|
| حساب مستخدم محلي غير مميز | لا حاجة لأي صلاحيات مرتفعة |
| نواة مبنية من 2017 فصاعدًا (≥ 4.14) | يغطي فعليًا جميع التوزيعات الرئيسية |
AF_ALG (CONFIG_CRYPTO_USER_API) مفعّل | افتراضي في جميع تكوينات نواة التوزيعات تقريبًا |
وحدة algif_aead قابلة للتحميل/محملة | تُحمّل تلقائيًا عند أول إنشاء لمقبس AF_ALG |
ثنائي setuid واحد قابل للقراءة على الأقل | مثل /usr/bin/su، /usr/bin/sudo |
| Python 3.10+ (لإثبات المفهوم العام) | فقط os، socket، zlib من المكتبة القياسية |
بشكل ملحوظ غير موجود في المتطلبات الأساسية: الوصول إلى الشبكة، ميزات تصحيح أخطاء النواة، CAP_SYS_ADMIN، وحدات نواة محملة مسبقًا، أو أي بدائيات موجودة مسبقًا. سطح الهجوم محلي بالكامل ومكتفٍ ذاتيًا.