ویرگول
ورودثبت نام
آرش حاتمی
آرش حاتمیSRE @ Arvancloud
آرش حاتمی
آرش حاتمی
خواندن ۳ دقیقه·۲۰ روز پیش

مقابله با آسیب‌پذیری‌ بحرانی PHP با فایروال CDN آروان‌کلاد

دو آسیب‌پذیری بحرانی جدید در PHP با شناسه‌های CVE-2026-109618 و CVE-2026-109619 منتشر شده‌اند که می‌توانند امنیت سرورهای مبتنی بر PHP را به خطر بیندازند. شدت این آسیب‌پذیری‌ها بالاست و گزارش‌هایی از تلاش برای سوءاستفاده از آن‌ها منتشر شده است.

در چنین شرایطی، تا زمانی که امکان به‌روزرسانی تمام سرورها وجود نداشته باشد، می‌توانیم از قابلیت‌های فایروال CDN آروان‌کلاد برای اضافه کردن یک لایه دفاعی دیگر استفاده کنیم.

در این مطلب می‌خواهیم یک قانون فایروال بنویسیم که بخشی از الگوهای مرتبط با این حملات را شناسایی کند و جلوی عبور درخواست‌های مشکوک را بگیرد.

‼️ توجه کنید که در حال حاضر تنها راه قطعی جلوگیری از آسیب پذیری ، آپدیت نسخه PHP است.

نوشتن قانون فایروال

در این مثال از Expression Language فایروال CDN استفاده می‌کنیم:

(lowercase(http.request.headers["content-type"]) contains "multipart/form-data") and (http.request.method in {"POST" "PUT" "PATCH"}) and not (http.request.uri.path in {"/upload" "/api/upload" "/wp-admin/async-upload.php"})

اگر حداقل یکی از این شرط‌ها برقرار باشد، درخواست با این قانون Match می‌شود. برای استفاده از آن، اپراتور قانون را روی ( مسدود ) قرار می‌دهیم تا درخواست‌های مچ شده مسدود شوند.

دقت کنید که این Expression بر اساس قابلیت‌های موتور فایروال مورد استفاده در CDN آروان‌کلاد نوشته شده است.

نمونه ای قانون ایجاد شده در پنل CDN
نمونه ای قانون ایجاد شده در پنل CDN

چرا از lowercase و url_decode استفاده می‌کنیم؟

مهاجم همیشه درخواست را دقیقن با همان حروف و قالبی که انتظار داریم ارسال نمی‌کند.

برای مثال، ممکن است عبارت مورد نظر با حروف بزرگ و کوچک متفاوتی ارسال شود. استفاده از lowercase باعث می‌شود بررسی ما نسبت به بزرگی و کوچکی حروف حساس نباشد.

از طرف دیگر، url_decode کمک می‌کند مقادیری که با URL Encoding ارسال شده‌اند، پیش از بررسی به شکل قابل‌تشخیص‌تری تبدیل شوند.

این دو کار باعث می‌شوند بعضی از تغییرات ساده در قالب درخواست، به‌راحتی از فیلتر عبور نکنند؛ البته تضمینی برای شناسایی تمام روش‌های دور زدن فیلتر نیستند.

قبل از فعال‌سازی قانون به این نکته توجه کنید

این قانون را نباید یک Patch یا راهکار قطعی برای آسیب پذیری های یاد شده در نظر بگیریم.

وجود PHPSESSID در یک درخواست به‌خودی‌خود نشانه حمله نیست؛ بسیاری از وب‌سایت‌های PHP از این کوکی برای مدیریت Session استفاده می‌کنند. همچنین درخواست‌های multipart/form-data در فرم‌های ثبت‌نام، ارسال اطلاعات و آپلود فایل کاملاً طبیعی هستند.

ممکن است با این قانون عملکرد بخشی از وب‌سایت یا اپلکیشن شما نیز تحت تاثیر قرار بگیرد.

بنابراین، اگر این قانون را بدون بررسی روی تمام ترافیک فعال کنیم، ممکن است بخشی از درخواست‌های سالم کاربران هم مسدود شوند.

پیشنهاد می‌کنم پیش از اعمال سیاست مسدودسازی:

  • درخواست‌های مچ شده و میزان False Positive را بررسی کنید.

  • مسیرهای حساس و Endpointهایی را که واقعاً به آپلود فایل نیاز دارند، با دقت بررسی کنید.

  • در صورت نیاز، قانون را به مسیرها یا سرویس‌های مشخص محدود کنید.

راهکار اصلی همچنان به‌روزرسانی است

فایروال CDN یک لایه دفاعی در برابر درخواست‌های ورودی است، اما نمی‌تواند جای اصلاح آسیب‌پذیری در خود PHP را بگیرد.

نسخه PHP مورد استفاده در سرورها، کانتینرها، هاستینگ‌ها و سرویس‌هایی مانند PHP-FPM را بررسی کنید و به‌ محض انتشار نسخه اصلاح‌شده و تأیید سازگاری آن، به‌روزرسانی را انجام دهید.

اگر امکان به‌روزرسانی فوری وجود ندارد، محدود کردن سطح دسترسی سرویس‌های آسیب‌پذیر و استفاده از کنترل‌های موقت چندلایه می‌تواند به کاهش ریسک کمک کند. با این حال، تا زمانی که نسخه اصلاح‌شده نصب نشده، نباید فرض کنیم سیستم کاملاً ایمن شده است.

بهبود های دیگر

جهت جلوگیری از این آسیب پذیری ها ، می‌توانید بر اساس نرم افزارهای به کار رفته نیز تغییراتی را نیز اعمال کنید

PHP

session.upload_progress.enabled = Off session.use_only_cookies = On

Nginx

map "$http_cookie|$args|$content_type" $block_php2shell { default 0; "~*(?:p|%[57]0)(?:h|%[46]8)(?:p|%[57]0)(?:s|%[57]3)(?:e|%[46]5)(?:s|%[57]3)(?:s|%[57]3)(?:i|%[46]9)(?:d|%[46]4)" 1; "~*multipart/form-data" 1; } In each server {} block: if ($block_php2shell) { return 403; }

Caddy

@php2shell expression `{header.Cookie}.matches("(?i)(?:p|%[57]0)(?:h|%[46]8)(?:p|%[57]0)(?:s|%[57]3)(?:e|%[46]5)(?:s|%[57]3)(?:s|%[57]3)(?:i|%[46]9)(?:d|%[46]4)") || {query}.matches("(?i)(?:p|%[57]0)(?:h|%[46]8)(?:p|%[57]0)(?:s|%[57]3)(?:e|%[46]5)(?:s|%[57]3)(?:s|%[57]3)(?:i|%[46]9)(?:d|%[46]4)") || {header.Content-Type}.matches("(?i)multipart/form-data")` respond @php2shell 403

Apache

SecRequestBodyAccess On SecRule ARGS_NAMES "@streq PHP_SESSION_UPLOAD_PROGRESS" \ "id:1026109618,phase:2,t:none,deny,status:403,log,\ msg:'php2shell: PHP_SESSION_UPLOAD_PROGRESS field blocked (CVE-2026-109618/109619)'"

Traefik v3

http: routers: block-php2shell: rule: "HeaderRegexp(`Cookie`, `(?i)(?:p|%[57]0)(?:h|%[46]8)(?:p|%[57]0)(?:s|%[57]3)(?:e|%[46]5)(?:s|%[57]3)(?:s|%[57]3)(?:i|%[46]9)(?:d|%[46]4)`) || QueryRegexp(`PHPSESSID`, `.*`) || HeaderRegexp(`Content-Type`, `(?i)multipart/form-data`)" priority: 100000 entryPoints: [https] middlewares: [deny-all] service: noop@internal tls: {} middlewares: deny-all: ipAllowList: sourceRange: ["255.255.255.255/32"]

Lighttpd

$HTTP["request-method"] =~ "^(POST|PUT|PATCH)$" { $REQUEST_HEADER["Content-Type"] =~ "(?i)^\s*multipart/form-data([;,[:space:]]|$)" { url.access-deny = ( "" ) } }

فایروالcdnsecurityphp
۴
۰
آرش حاتمی
آرش حاتمی
SRE @ Arvancloud
شاید از این پست‌ها خوشتان بیاید