CISA در ۲۸ اکتبر ۲۰۲۶ آسیبپذیری CVE-2026-46300 را به فهرست آسیبپذیریهای شناختهشدهٔ مورد بهرهبرداری (KEV) اضافه کرد. این باگ همان Fragnesia است، یک ارتقای دسترسی در کرنل لینوکس که ۱۳ مه ۲۰۲۶ در فهرست oss-security افشا شد. مدخل این CVE در فهرست KEV میگوید میتوان آن را با CVE-2026-109618 و CVE-2026-109619 زنجیر کرد تا وبشل PHP کار گذاشته شود و فرمانها با دسترسی root اجرا شوند. آن دو CVE همان PHP2Shell هستند. یک باگ راه دور در PHP به مهاجم شِل با کاربر وبسرور میدهد و Fragnesia آن شِل را به root تبدیل میکند.
کرنلهای وصلهشده از ماه مه منتشر شدهاند و همین است که اشتباه کردن دربارهٔ این باگ را آسان میکند. روی یک VPS با unattended-upgrades ممکن است بستهٔ کرنل اصلاحشده ماهها پیش نصب شده باشد، اما ماشین چون کسی ریبوتش نکرده هنوز با کرنل قدیمی کار کند. فهرست بستهها میگوید وصله شده، کرنلِ در حال اجرا چیز دیگری میگوید. در ادامه میبینیم چه کسانی در معرضاند، چطور بفهمید سرورها و کانتینرهایتان واقعاً چه کرنلی اجرا میکنند، چطور وصله کنید و اگر احتمال میدهید کسی زودتر رسیده، سراغ چه چیزهایی بروید.
Fragnesia چه میکند
کاشفان این باگ، William Bowling و تیم V12، در گزارش عمومیشان آن را «اکسپلویت همگانی ارتقای دسترسی محلی در لینوکس» در کد XFRM ESP-in-TCP توصیف کردهاند. هنگام ادغام بستههای دریافتی TCP، کرنل فراموش میکند که یک قطعه از بافر شبکه با page cache یک فایل مشترک است (توضیح NVD ریشه را در skb_try_coalesce() نشان میدهد). سپس کد ESP داده را درجا، روی همان صفحهٔ کششدهٔ فایل، رمزگشایی میکند. مهاجم با انتخاب nonce رمزنگاری میتواند هر بایتِ هر فایلی را که اجازهٔ خواندنش را دارد تغییر دهد، و طبق همان گزارش این کار «بدون نیاز به هیچ race condition» انجام میشود.
اثبات مفهوم منتشرشده ۱۹۲ بایت اول /usr/bin/su را در حافظه بازنویسی و اجرا میکند تا شِل root بگیرد. CNA کرنل (kernel.org) به این باگ امتیاز CVSS 3.1 برابر ۷٫۸ (High) داده است. صفحهٔ CVE اوبونتو اولویت آن را بالا گذاشته، دلیلش را «ارتقای دسترسی محلی پیشپاافتاده» نوشته و گفته مهاجم «احتمالاً میتواند از کانتینر فرار کند».
یک نکته روش بررسی را عوض میکند. گزارش V12 میگوید تغییر در page cache روی دیسک نوشته نمیشود و فایل اجرایی روی دیسک دستنخورده میماند. پس بررسی یکپارچگی فایلها روی دیسک تمیز به نظر میرسد و ریبوت خودِ تغییرِ درون حافظه را پاک میکند.
چه کسانی واقعاً در معرضاند
Fragnesia محلی است، یعنی مهاجم اول باید روی ماشین کد اجرا کند. روی سرور یک تیم کوچک، این معمولاً از یکی از این راهها میآید:
- یک وباپلیکیشن با باگ اجرای کد از راه دور که شِلی با کاربر
www-dataیا مشابه آن میدهد. این همان زنجیرهای است که CISA توصیف کرده. - کانتینرهایی که با
--privilegedیا--security-opt seccomp=unconfinedاجرا شدهاند، از جمله runnerهای CI که روی همان سرور production ایمیج میسازند. - سرورهایی که چند نفر یا چند مشتری حساب شِل جداگانه دارند.
اکسپلویت باید namespace بسازد. طبق گزارش، با فراخوانی unshare(CLONE_NEWUSER | CLONE_NEWNET) قابلیت CAP_NET_ADMIN را بدون هیچ دسترسی واقعی روی میزبان به دست میآورد. دو کنترل موجود جلوی این مرحله را میگیرند. هیچکدام جای وصله را نمیگیرد.
اولی محدودیت AppArmor در اوبونتو است. همان README میگوید در اوبونتو AppArmor بهطور پیشفرض user namespaceهای بدون امتیاز را محدود میکند و اکسپلویت عمومی فقط بعد از خاموش کردن آن کار میکند. همچنین میگوید با زنجیر کردن باگهای دیگر میتوان این شرط را دور زد. وضعیت سرورتان را با sysctl kernel.apparmor_restrict_unprivileged_userns ببینید؛ مقدار ۱ یعنی محدودیت روشن است.
دومی پروفایل پیشفرض seccomp در Docker است. این را روی یکی از سرورهای Ubuntu 24.04 خودمان با Docker Engine 29.9.2 امتحان کردیم. در یک کانتینر پیشفرض، unshare -U -r -n id با خطای «Operation not permitted» شکست خورد. همان فرمان در کانتینری که با --security-opt seccomp=unconfined اجرا شده بود موفق شد و داخل namespace جدید uid=0(root) چاپ کرد. کانتینرهایی که بدون seccomp اجرا میشوند اولین جاییاند که باید نگاه کنید.
گام ۱: کرنلی را که در حال اجراست بررسی کنید، نه کرنلی را که نصب کردهاید
کانتینر کرنل مخصوص خودش را ندارد. اگر docker run --rm alpine uname -r را اجرا کنید، نسخهٔ کرنل میزبان را میبینید. پس توصیهٔ همیشگی برای باگهای کتابخانهای، یعنی بازسازی ایمیج با docker build --pull، برای Fragnesia هیچ اثری ندارد. اصلاح روی میزبان است و فقط بعد از ریبوت حساب میشود.
روی هر سرور، کرنل در حال اجرا را با آنچه نصب شده مقایسه کنید:
uname -r
dpkg -l 'linux-image*' | grep ^ii
cat /var/run/reboot-required.pkgs 2>/dev/null
sudo needrestart -k -b
روی سرورهای اوبونتو، needrestart -k -b کرنل در حال اجرا را با عنوان NEEDRESTART-KCUR و جدیدترین کرنل نصبشده را با عنوان NEEDRESTART-KEXP نشان میدهد. اگر این دو فرق داشته باشند، با کرنلی قدیمیتر از آنچه روی دیسک است بوت شدهاید. در Debian، خروجی uname -v نسخهٔ بستهٔ Debian را هم نشان میدهد.
بعد با نسخههای اصلاحشده مقایسه کنید. از صفحهٔ CVE-2026-46300 در اوبونتو:
- Ubuntu 26.04 LTS: اصلاحشده در 7.0.0-22.22
- Ubuntu 24.04 LTS: اصلاحشده در 6.8.0-124.124
- Ubuntu 22.04 LTS: اصلاحشده در 5.15.0-181.191، و برای کرنل HWE در 6.8.0-124.124~22.04.1
- Ubuntu 20.04 LTS: کرنل پیشفرض 5.4 «تحت تأثیر نیست» اعلام شده؛ کرنل HWE نسخهٔ 5.15 در 5.15.0-181.191~20.04.1 از طریق Ubuntu Pro اصلاح شده
- Ubuntu 26.10: تحت تأثیر نیست
- Debian 13 trixie: اصلاحشده در 6.12.90-1 (DSA-6295-1)
- Debian 12 bookworm: اصلاحشده در 6.1.174-1 (DSA-6306-1)
- Debian 11 bullseye LTS: اصلاحشده در 5.10.257-1 (DLA-4606-1)، یا 6.1.174-1~deb11u1 برای بکپورت linux-6.1 (DLA-4607-1)
کرنلهای مخصوص ابر مانند linux-aws یا linux-azure شمارهنسخهٔ خودشان را دارند، پس نسخهٔ کرنل خودتان را در صفحهٔ اوبونتو پیدا کنید و آن را با شمارهٔ کرنل generic تطبیق ندهید.
گام ۲: وصله و ریبوت
راهنمای Canonical برای Dirty Frag، که صفحهٔ Fragnesia در اوبونتو برای همان مراحل کاهش خطر به آن ارجاع میدهد، در نهایت به یک ارتقای معمولی و سپس ریبوت میرسد:
sudo apt update && sudo apt upgrade
sudo reboot
همان مطلب میگوید unattended-upgrades بهروزرسانیهای امنیتی را هر ۲۴ ساعت اعمال میکند، «اما ریبوت همچنان لازم است». این بخش آخر بهراحتی از چشم میافتد. بعد از ریبوت دوباره uname -r را اجرا کنید و مطمئن شوید با فهرست بالا جور است. سپس docker ps -a را اجرا کنید و دنبال کانتینرهایی بگردید که بالا نیامدهاند؛ معمولاً همانهایی که در فایل compose سیاست restart: ندارند.
حالا که روی سرور هستید، کانتینرهایی را که بدون seccomp یا در حالت privileged اجرا میشوند فهرست کنید:
docker inspect --format '{{.Name}} privileged={{.HostConfig.Privileged}} {{.HostConfig.SecurityOpt}}' $(docker ps -q) \
| grep -E 'privileged=true|unconfined'
خروجی خالی یعنی هیچکدام از کانتینرهای در حال اجرا این تنظیمات را ندارند. هر چیزی که نشان داده شود باید دلیل مکتوب داشته باشد.
گام ۳: اگر امروز نمیتوانید ریبوت کنید
راهکار موقت همان است که برای Dirty Frag استفاده شد: جلوی بارگذاری ماژولهای esp4، esp6 و rxrpc در کرنل را بگیرید. این فرمانها از مطلب Canonical آمدهاند:
echo "install esp4 /bin/false" | sudo tee /etc/modprobe.d/dirty-frag.conf
echo "install esp6 /bin/false" | sudo tee -a /etc/modprobe.d/dirty-frag.conf
echo "install rxrpc /bin/false" | sudo tee -a /etc/modprobe.d/dirty-frag.conf
sudo update-initramfs -u -k all
sudo rmmod esp4 esp6 rxrpc 2>/dev/null
grep -qE '^(esp4|esp6|rxrpc) ' /proc/modules && echo "Affected modules are loaded" || echo "Affected modules are NOT loaded"
پیش از اجرا بدانید چه چیزی از کار میافتد. Canonical هشدار میدهد که این کار روی استقرارهای IPsec اثر میگذارد، که «در VPNهایی مانند StrongSwan رایجاند». کاربران Docker یک مورد دیگر هم دارند: شبکههای overlay که با --opt encrypted ساخته شدهاند از رمزنگاری IPsec استفاده میکنند، پس ترافیک overlayهای رمزشده در یک کلاستر Swarm قطع میشود. وقتی کرنل وصلهشده بالا آمد، فایل /etc/modprobe.d/dirty-frag.conf را حذف کنید و دوباره sudo update-initramfs -u -k all را اجرا کنید.
گام ۴: اگر فکر میکنید قبلاً از آن استفاده شده
مدخل KEV برای این CVE میگوید طبق BOD 26-04 «بررسی جرمشناسی لازم است». این قاعده فقط برای نهادهای فدرال آمریکا الزامی است، اما منطقش برای همه صدق میکند: سروری که کرنل آسیبپذیر را کنار یک اپ PHP در معرض اینترنت اجرا کرده، باید از نظر نفوذ بررسی شود، نه فقط وصله.
ریبوت page cache تغییریافته را پاک میکند، اما هر چیزی را که مهاجم بعد از root شدن روی دیسک نوشته باقی میگذارد. دنبال فایلهای PHP در پوشههای آپلود و کش بگردید که اپلیکیشن شما نساخته، حسابهای تازه در /etc/passwd، کلیدهای ناشناس در authorized_keys، و cron job یا سرویس systemd جدید. روی سروری که هرگز از IPsec استفاده نمیکند، ظاهر شدن esp4 یا esp6 در /proc/modules ارزش نگاه دقیقتر دارد، چون اکسپلویت یک security association از نوع ESP میسازد. آن را سرنخ بدانید، نه مدرک.
root روی میزبان Docker یعنی دسترسی به همهٔ کانتینرها، همهٔ volumeها و همهٔ secretهایی که بهصورت متغیر محیطی داده شدهاند. اگر نشانهای از نفوذ پیدا کردید، بهجای پاکسازی، سرور را از یک ایمیج سالم از نو بسازید و اعتبارنامههایی را که روی آن بوده عوض کنید. ترتیب این کار را در اول وصله، بعد چرخش همهٔ secretهای دستگاه نوشتهایم. اگر نقطهٔ ورود PHP بوده، راهنمای PHP2Shell وصله کردن PHP داخل ایمیجها را توضیح میدهد. لاگهایی هم که پیشتر از سرور خارج شدهاند همانهاییاند که مهاجمِ root نمیتواند بیصدا دستکاری کند؛ این یکی از دلایلی است که ما لاگ کانتینرها را به stdout میفرستیم و از سرور بیرون میبریم.
پرسشهای متداول
ایمیجهایم هر هفته بازسازی میشوند. در امانم؟
نه. کانتینرها از کرنل میزبان استفاده میکنند، پس Fragnesia فقط با کرنل وصلهشدهٔ میزبان و ریبوت رفع میشود. بازسازی ایمیج برای باگهای سطح کاربر مثل PHP2Shell مهم است، نه برای این یکی.
آیا Fragnesia از طریق شبکه قابل بهرهبرداری است؟
بهتنهایی نه. به اجرای کد محلی نیاز دارد. مدخل CISA زنجیر شدن آن با باگهای راه دور PHP2Shell را توصیف میکند و سرورِ رو به اینترنت از همین راه در معرض قرار میگیرد.
اوبونتو user namespaceهای بدون امتیاز را محدود میکند. همین کافی است؟
جلوی اکسپلویت عمومی را به شکل فعلیاش میگیرد، اما پژوهشگران میگویند با زنجیر کردن باگهای دیگر میتوان آن را دور زد. در هر حال کرنل اصلاحشده را نصب کنید.
واقعاً باید ریبوت کنم؟
بله. راهنمای Canonical میگوید بعد از بهروزرسانی کرنل ریبوت لازم است، حتی اگر unattended-upgrades آن را برایتان نصب کرده باشد. تا آن موقع کرنل قدیمی اجرا میشود.
مسدود کردن esp4 و esp6 چیزی را خراب میکند؟
IPsec را از کار میاندازد، از جمله VPNهای strongSwan و شبکههای overlay در Docker که با --opt encrypted ساخته شدهاند. اگر از هیچکدام استفاده نمیکنید، این راهکار تا زمان ریبوت کمخطر است.
منابع: هشدار KEV در CISA، ۲۸ اکتبر ۲۰۲۶، فهرست KEV در CISA، NVD برای CVE-2026-46300، ردیاب CVE اوبونتو، ردیاب امنیتی Debian، رشتهٔ افشا در oss-security، گزارش Fragnesia از V12، مطلب Canonical دربارهٔ کاهش خطر Dirty Frag و مستندات شبکهٔ overlay در Docker. فرمانها در ۱ نوامبر ۲۰۲۶ روی Ubuntu 24.04.5 LTS با کرنل 6.8.0-147-generic و Docker Engine 29.9.2 آزموده شدند. راهکار مسدودسازی ماژولها روی آن سرور اعمال نشد.



