Copy Fail: ۷۳۲ بایت کافیه برای روت گرفتن از لینوکس
خلاصهٔ کاملتر
آسیبپذیری Copy Fail با شناسه CVE-2026-31431 یه باگ منطقی جدی در کرنل لینوکسه که توسط تیم تحقیقاتی Xint Code، با کمک محقق Theori به اسم Taeyang Lee کشف شده. این آسیبپذیری ریشهاش در قالب رمزنگاری authencesn هست که برای IPsec و Extended Sequence Number استفاده میشه.
ماجرا اینه که AF_ALG یه نوع سوکت در لینوکسه که به کاربرهای عادی (بدون root) اجازه میده از سیستم رمزنگاری کرنل استفاده کنن. از طرفی تابع splice() داده رو بین file descriptorها و pipeها بدون کپی کردن جابهجا میکنه، یعنی صفحات page cache فایل رو مستقیماً پاس میده. وقتی این دو تا کنار هم بیان، scatterlist ورودی AF_ALG مستقیماً به صفحات page cache فایل اشاره میکنه؛ همون صفحاتی که هر read، mmap و execve از اونها استفاده میکنه.
مشکل اصلی اینجاست که در مسیر رمزگشایی AEAD، کرنل عملیات رو in-place تنظیم میکنه، یعنی یه scatterlist هم ورودیه هم خروجی. دادههای AAD و ciphertext کپی میشن، ولی تگ احراز هویت کپی نمیشه و با sg_chain به scatterlist خروجی متصل میمونه. این یعنی صفحات page cache فایل هدف الان در یه scatterlist قابل نوشتن قرار دارن.
req->src ----+
|
v
req->dst --> [ AAD || CT ] --> [ Tag (page cache pages) ]
| |
+-- RX buffer --+ +-- chained from TX SGL --+
| (user mem) | | (file's page cache) |
حالا authencesn وارد میشه و گند میزنه. این الگوریتم برای محاسبه HMAC باید بایتهای sequence number رو جابهجا کنه. برای این کار از بافر مقصد به عنوان scratch space استفاده میکنه:
scatterwalk_map_and_copy(tmp, dst, 0, 8, 0);
scatterwalk_map_and_copy(tmp, dst, 4, 4, 1);
scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 1);خط سوم ۴ بایت رو در آفست assoclen + cryptlen مینویسه، یعنی دقیقاً بعد از تگ، جایی که دیگه متعلق به بافر کاربر نیست. توی مسیر in-place ی که گفتیم، این نوشتن از بافر خروجی رد میشه و مستقیم توی page cache فایل هدف مینشینه. حتی وقتی recvmsg() با خطا برمیگرده (چون ciphertext جعلیه)، اون ۴ بایت قبلاً نوشته شدن.
نکتهی خیلی مهم اینه که کرنل هیچوقت این صفحه رو dirty علامت نمیزنه. یعنی فایل روی دیسک دست نمیخوره، ولی page cache که همه ازش میخونن دستکاری شده. ابزارهایی مثل AIDE یا Tripwire که چکسام فایل روی دیسک رو بررسی میکنن، هیچ چیز غیرعادی نمیبینن. ولی هر بار که کاربر یا سیستم اون فایل رو اجرا میکنه، نسخه دستکاریشدهی توی حافظه اجرا میشه.
با یه اسکریپت ۷۳۲ بایتی پایتون که فقط از ماژولهای استاندارد (os, socket, zlib) استفاده میکنه و به Python 3.10+ نیاز داره، میشه page cache یه setuid binary رو دستکاری کرد و root گرفت. این اسکریپت روی همه توزیعهای اصلی لینوکس از جمله Ubuntu، Amazon Linux، RHEL و SUSE کار میکنه بدون هیچ تنظیم یا آفست خاصی.
علاوه بر local privilege escalation، چون page cache بین همهی پروسههای روی سیستم، حتی containerها، مشترکه، این آسیبپذیری یه ابزار container escape هم هست. یعنی از داخل یه کانتینر میشه فایلهای هاست یا کانتینرهای دیگه رو دستکاری کرد. قسمت دوم این تحقیق به جزئیات فرار از Kubernetes میپردازه.
این آسیبپذیری با همکاری سازندگان توزیعها (coordinated disclosure) افشا شده و باید پچهای کرنل رو در اسرع وقت اعمال کرد.
نکات کلیدی:
- CVE-2026-31431 یه باگ منطقی در authencesn کرنل لینوکسه، نه یه race condition
- با ترکیب AF_ALG و splice()، صفحات page cache فایل توی یه scatterlist قابل نوشتن قرار میگیرن
- authencesn غیرمجاز ۴ بایت رو خارج از محدودهی مجاز مینویسه و مستقیم به page cache میزنه
- فایل روی دیسک دست نمیخوره؛ ابزارهای checksum اصلاً متوجه تغییر نمیشن
- یه اسکریپت ۷۳۲ بایتی پایتون کافیه برای root گرفتن روی همه توزیعهای اصلی لینوکس
- این باگ از مرز containerها رد میشه و یه Kubernetes escape vector هم محسوب میشه
- اعمال فوری پچهای کرنل الزامیه




