روز ۲۱ اکتبر ۲۰۲۶ (۲۹ مهر ۱۴۰۵) پروژهٔ PHP نسخههای 8.5.12، 8.4.27، 8.3.36 و 8.2.35 را منتشر کرد و از همهٔ کاربران خواست فوراً بهروزرسانی کنند. دو باگی که این نسخهها رفع میکنند، CVE-2026-109618 و CVE-2026-109619، که حالا با نام PHP2Shell شناخته میشوند، میتوانند به مهاجم اجازه بدهند بدون ورود به سایت روی سرور وب کد اجرا کند. پژوهشگرانی که این باگها را گزارش کردند، حمله را روی وردپرس، دروپال و جوملا نشان دادهاند.
نکتهای که خیلیها را غافلگیر میکند جای باگ است. باگ در خود PHP است، نه در وردپرس یا افزونهها. زدن دکمهٔ «بهروزرسانی» در پیشخوان وردپرس هیچ اثری روی آن ندارد و بهروزرسانی بستههای Composer هم همینطور. اگر سایتتان در Docker اجرا میشود، کانتینرِ در حال اجرا تا وقتی دوباره ساخته نشود روی همان PHP قبلی میماند. در این مطلب میگوییم چطور بفهمید واقعاً چه نسخهای اجرا میشود، چطور وصله کنید و بعد از آن چه چیزهایی را بررسی کنید.
PHP2Shell چیست
طبق اطلاعیهٔ امنیتی پروژهٔ PHP، این دو باگ عبارتاند از:
- CVE-2026-109618، اجرای کد از راه دور با خرابی ناشی از کمبود حافظه. اگر حافظهٔ PHP در لحظهٔ نامناسب تمام شود، ممکن است دادههای درخواست نیمهکاره بماند و کد پاکسازی بعداً آن را دادهٔ معتبر فرض کند.
- CVE-2026-109619، اجرای کد از راه دور با وضعیت سراسری کهنه. وضعیتی که مال یک درخواست بوده ممکن است بعد از آزاد شدن حافظهاش باقی بماند و درخواست بعدیِ همان پردازه از آن استفاده کند.
سایت افشای این باگها که Wiz Research، OpenAI Codex Security و Calif منتشر کردهاند، شدت هر دو را CVSS 9.2 اعلام کرده است. این سایت میگوید اجرای کد از راه دور پیش از احراز هویت را روی وردپرس، دروپال و جوملا انجام داده و باگ دوم میتواند حافظهٔ پردازه را هم نشت دهد. مهمترین نکته برای صاحبان سایت: حتی یک اسکریپت سادهٔ «Hello World» روی نسخهٔ آسیبپذیر PHP هم در معرض خطر است، چون کد معیوب پیش از برنامهٔ شما اجرا میشود.
پروژهٔ PHP، نسخههای PHP-FPM، آپاچی با mod_php، php-cgi، FrankenPHP و LiteSpeed را آسیبپذیر میداند و بیشترین خطر را برای mod_php میبیند، چون برای آن اکسپلویتی دارد که پیش از اجرای هر کدی از برنامه عمل میکند. بولتن Red Hat اضافه میکند که پیکربندی پیشفرض PHP-FPM در توزیعهایش سوءاستفاده را در عمل سختتر میکند و mod_php با تنظیمات پیشفرض پرخطرتر است. این تفاوت برای وردپرس در Docker مهم است: ایمیجهای رسمی wordpress:*-apache PHP را داخل آپاچی و به شکل mod_php اجرا میکنند. هاستهای اشتراکی هم اغلب از LiteSpeed یا آپاچی استفاده میکنند، پس اگر هاست دارید، نسخهٔ PHP را کتبی از پشتیبانی بپرسید.
گام ۱: نسخهٔ PHP را که واقعاً به درخواستها پاسخ میدهد بررسی کنید
روی یک سرور معمولی، php -v نسخهٔ خط فرمان را نشان میدهد که همیشه همان نسخهای نیست که وبسرور استفاده میکند. روی دبیان و اوبونتو ممکن است برعکس هم گمراهتان کند: اوبونتو وصله را به نسخهٔ خودش منتقل کرده، پس اوبونتو 24.04 با 8.3.6-0ubuntu0.24.04.13 امن است، با اینکه نسخه هنوز 8.3.6 نشان داده میشود. شمارهٔ کامل بسته را با اطلاعیهٔ توزیع خودتان مقایسه کنید، نه با شمارهٔ نسخهٔ اصلی.
برای کانتینرها، از هر کانتینرِ در حال اجرا مستقیم بپرسید. این دستور همهٔ کانتینرهای دارای PHP روی سرور را با نسخه و ایمیجشان فهرست میکند:
for c in $(docker ps --format '{{.Names}}'); do v=$(docker exec "$c" php -r 'echo PHP_VERSION;' 2>/dev/null) && echo "$c $v $(docker inspect -f '{{.Config.Image}}' "$c")"; done
نسخههای رسمی PHP از 8.2.35، 8.3.36، 8.4.27 و 8.5.12 به بعد وصله شدهاند. هر نسخهٔ قدیمیتر در همان شاخه، یا هر نسخهٔ 8.1 و پایینتر، نیاز به اقدام دارد.
گام ۲: دوباره بسازید، فقط ریاستارت نکنید
داکر میگوید ایمیجهای رسمیاش در Docker Hub نسخهٔ وصلهشدهٔ PHP را دارند. این فقط وقتی کمک میکند که ایمیج جدید را بکشید. ریاستارت همان ایمیج قدیمی را دوباره اجرا میکند، و Dockerfileی که برچسب دقیقی مثل FROM php:8.2.33-apache را ثابت کرده هیچوقت خودبهخود وصله نمیگیرد. برای پروژهٔ Compose که از Dockerfile ساخته میشود:
docker compose build --pull && docker compose up -d
برای سرویسی که مستقیم از ایمیج منتشرشده استفاده میکند، پیش از up -d دستور docker compose pull را بزنید. بعد حلقهٔ گام ۱ را دوباره اجرا کنید و نسخهٔ جدید را داخل کانتینر ببینید. اگر ایمیجی از طرف سوم (بستهٔ آمادهٔ LAMP یا محصول یک فروشنده) هنوز نسخهٔ وصلهشده نداده، منتظر همان فروشندهاید و تا آن موقع فقط راهکارهای کاهش خطر پایین را دارید.
گام ۳: اگر روی PHP 8.1 یا قدیمیتر هستید
پروژهٔ PHP دیگر برای 8.1 و قبل از آن نسخه منتشر نمیکند. تیم امنیت برای 7.4، 8.0 و 8.1 وصلههای حداقلی در سطح کد منبع منتشر کرده است، برای کسانی که PHP را خودشان کامپایل میکنند، و بعضی توزیعها و فروشندگان پشتیبانی بلندمدت هم نسخهٔ وصلهشدهٔ خودشان را دارند. اما کانتینری که از برچسب قدیمی php:7.4 ساخته شده، هیچکدام را نمیگیرد. سایتهای وردپرسی قدیمی که به افزونههای رمزشده با ionCube وابستهاند، معمولاً دقیقاً به همین دلیل روی 7.4 ماندهاند. راهحل اصلی، انتقال به یک شاخهٔ پشتیبانیشده است. تا آن موقع این سایتها را در معرض خطر بدانید.
کاهش خطر تا زمان وصله
هم پروژهٔ PHP و هم پژوهشگران میگویند تنها راهحل کامل، بهروزرسانی است. اگر به جای چند دقیقه چند ساعت زمان لازم دارید، اطلاعیهٔ PHP راههایی برای بستن مسیرهای مشخصی از حمله پیشنهاد میکند:
memory_limit=-1را طوری تنظیم کنید که برنامه نتواند تغییرش بدهد، مثلاً باphp_admin_valueدر pool مربوط به FPM یا پیکربندی آپاچی. این کار خطای قابلپیشبینی محدودیت حافظه را که اکسپلویت اول به آن تکیه دارد حذف میکند، اما همهٔ مسیرها را نمیبندد.post_max_sizeرا محافظهکارانه نگه دارید و اندازهٔ درخواست، عمق ورودیها و تعداد بخشهای multipart را در پراکسی معکوس محدود کنید. اگر سایت اصلاً دادهٔ multipart نمیگیرد، آن را در لایهٔ جلویی مسدود کنید.session.upload_progress.enabled=0را تنظیم کنید. پروژهٔ PHP روز ۲۳ اکتبر از همه خواست تا انتشار نسخهٔ عادی بعدی این کار را بکنند، به خاطر یک مسیر جداگانه و کماحتمالتر برای اجرای کد (CVE-2026-115560) که در نسخههای وصلهشده هم وجود دارد.
گام ۴: بررسی کنید کسی پیش از شما وارد نشده باشد
وصله کردن حفره را میبندد، اما چیزی را که مهاجم احتمالاً جا گذاشته پاک نمیکند. برای وردپرس، اینها بررسیهایی است که روی سرورهای خودمان انجام میدهیم، همه با WP-CLI داخل کانتینر:
wp core verify-checksums --allow-rootهمهٔ فایلهای هستهٔ وردپرس را با نسخهٔ wordpress.org مقایسه میکند.wp plugin verify-checksums --all --allow-rootهمین کار را برای افزونههای مخزن wordpress.org انجام میدهد. افزونههای تجاری و اختصاصی با هشدار 404 رد میشوند، پس آنها را جداگانه بررسی کنید. ناهمخوانی بهتنهایی نشانهٔ نفوذ نیست، چون بعضی سازندگان کتابخانههای داخل افزونه را تغییر میدهند، اما هر فایل ناهمخوان ارزش جستوجویeval،base64_decodeیاgzinflateروی ورودی درخواست را دارد.find wp-content/uploads -name "*.php*"فایلهای PHP داخل پوشهٔ آپلود را پیدا میکند، جایی که نباید کدی باشد. بعضی افزونههای امنیتی تنظیماتشان را آنجا نگه میدارند، پس هر نتیجه را پیش از حذف بررسی کنید.- فایلهای PHP تغییرکرده از ۲۰ اکتبر را فهرست کنید و با بهروزرسانیهایی که میدانید نصب کردهاید تطبیق بدهید.
به گفتهٔ پژوهشگران، باگ دوم میتواند حافظهٔ پردازه را نشت دهد. اگر سایتی بعد از افشای ۲۱ اکتبر بدون وصله و در دسترس مانده، هر چیزی را که ممکن است در آن حافظه بوده عوض کنید: کلیدهای امنیتی وردپرس در wp-config.php، رمز پایگاه داده، اطلاعات SMTP، و کلیدهای API درگاه پرداخت یا سامانهٔ پیامکی.
بهروزرسانی ۲۷ اکتبر ۲۰۲۶، فقط ویندوز: پروژهٔ PHP روز ۲۶ اکتبر بستههای بازسازیشدهٔ ویندوز 8.5.12-1، 8.4.27-1، 8.3.36-1 و 8.2.35-1 را منتشر کرد. این بستهها Brotli 1.2.1 را دارند که CVE-2026-111497 را رفع میکند، یک نوشتن خارج از محدوده که به گفتهٔ PHP وقتی رفع فشردهسازی خودکار پاسخ HTTP روشن باشد از راه افزونهٔ cURL قابل دسترسی است. شمارهٔ نسخهٔ PHP تغییر نمیکند، پس روی ویندوز بستهٔ -1 را از صفحهٔ دانلود ویندوز بررسی کنید، نه فقط php -v را. نسخههای لینوکس و Docker جزو این بازسازی نیستند.
پرسشهای متداول
آیا بهروزرسانی وردپرس PHP2Shell را رفع میکند؟
نه. باگ در محیط اجرای PHP است. به PHP 8.2.35، 8.3.36، 8.4.27، 8.5.12 یا نسخهٔ توزیعی دارای وصلهٔ منتقلشده نیاز دارید، و بعد ریاستارت یا بازسازی کانتینر تا وبسرور از آن استفاده کند.
آیا PHP-FPM امن است؟
نه. پروژهٔ PHP، FPM را آسیبپذیر میداند و پژوهشگران اجرای کد روی آن را از مسیرهای کد برنامه تأیید کردهاند. Red Hat میگوید سوءاستفاده روی پیکربندی پیشفرض FPM آن سختتر از mod_php است؛ این خطر را کم میکند، اما از بین نمیبرد.
هاستم میگوید PHP 8.3.6 وصله شده است. درست است؟
ممکن است درست باشد. اوبونتو و توزیعهای دیگر PHP2Shell را با انتقال وصله و بدون تغییر شمارهٔ نسخه رفع کردهاند. شمارهٔ کامل بسته را با اطلاعیهٔ توزیع مقایسه کنید.
کدام نسخههای PHP اصلاً وصله ندارند؟
پروژهٔ PHP برای 8.1 و قدیمیتر نسخهای منتشر نمیکند. فقط وصلههای کد منبع، نسخههای توزیعها و فروشندگان پشتیبانی بلندمدت آنها را پوشش میدهند.
منابع: اطلاعیهٔ امنیتی PHP (۲۱ و ۲۳ اکتبر ۲۰۲۶)، php2shell.com (Wiz Research، OpenAI Codex Security و Calif)، Red Hat RHSB-2026-013، اوبونتو و داکر.