چطور مچ نفوذی رو گرفتم و یک سناریوی تکراری رو پایان دادم.

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

و اینبار گفتم همون اشتباه رو دوباره انجام ندم و اول لباس کاراگاهیم رو پوشیدم وگفتم " دستان پرتوان برسید به داد این ناتوان :)) " با کمک خدایگان این روزها استاد GPT شروع کردم به بررسی میدانی و هر داده ایی که گیرم میومد.
اول از همه به پیشنهاد جی پی تی جان از روی یکی از بکاپ ها یک سرور بکاپ ساختم که بریم لاگ ها رو توی اون بررسی کنیم تا در مراحل بررسی دوست نفوذگر خیلی شاخکاش فعال نشه.
همه فایلها و پوشههای سایت با یک پسوند عجیب، تغییر نام داده شده بودن. مثلاً:
wp-content__8a534d5 wp-admin__8a534d5 wp-includes__8a534d5
اولین کار این بود که از روی زمان تغییرات فایلها بفهمیم این اتفاق دقیقاً چه ساعتی افتاده ، نتیجه: عملیات تغییر نام فایلها در روز ۲۶ ژوئن، بین ساعت ۱۱:۰۲ تا ۱۱:۰۵ انجام شده بود. یعنی خرابکاری نه در طول چند ساعت، بلکه در حدود سه دقیقه اتفاق افتاده بود. این بازه زمانی شد نقطه شروع بررسی لاگها.
در همون حوالی، چند درخواست مشکوک به فایلهایی با اسمهای عجیب پیدا کردیم
wp-wlx.php lock360.php admin.php style.php
یکی از درخواستها حتی با User-Agent زیر ارسال شده بود
ShellBot 2.0
مهاجم از طریق یکی از همین فایلها فرمانهای مختلفی ارسال کرده بود؛ از باز کردن قفل و ساخت ادمین گرفته تا دانلود کد از یک دامنه خارجی. جالبتر اینکه زمان اجرای یکی از این فرمانها دقیقاً با زمان شروع تغییر نام فایلها یکی بود. اینجا دیگه مشخص شد که با یک اختلال ساده، خرابی تصادفی یا مشکل آپدیت وردپرس طرف نیستیم. یک نفر از طریق یک Webshell داخل سایت، فرمان اجرا کرده بود.
::: با روحیه پیگیر و چالش دوستم گفتم هر فایل مخربی، نقطه ورود نیست ، باید پی کارو بگیرم :::
یکی از اولین فایلهایی که پیدا کردیم، فایلی به نام about.php بود که ظاهرش شبیه یک فایل معمولی و حتی محافظتشده توسط یک سرویس امنیتی بود. اما وقتی بازش کردیم، مشخص شد کاملاً Obfuscated و مخرب است.
در نگاه اول ممکن بود بگوییم همین فایل نقطه ورود بوده، ولی زمان ساختش نشان میداد بیش از دو ساعت بعد از خرابکاری اصلی ایجاد شده است. پس این فایل نقطه ورود نبود؛ یکی از ابزارهایی بود که مهاجم بعداً برای حفظ دسترسی خودش ساخته بود.
این یکی از مهمترین نکات این بررسی بود ( کاربر پیگیر و کرمو ):
هر فایل مخربی که پیدا میکنیم الزاماً عامل اولیه نفوذ نیست. بعضی فایلها فقط ابزار ماندگاری مهاجماند.
کمی عقبتر رفتیم و به فایل دیگری در قالب پیشفرض وردپرس رسیدیم:( اسیر شدیم )
themes/twentytwentythree/patterns/style.php
این فایل هم یک Backdoor کامل بود؛ میتوانست فایل دانلود کند، فایل جدید بسازد، index.php را تغییر بدهد، Shell ایجاد کند و حتی بعد از انجام کار خودش را حذف کند. بررسی زمانها نشان داد این فایل یک روز قبل از خرابکاری اصلی ساخته شده بود. بعد باز هم عقبتر رفتیم.
در روز ۲۴ ژوئن، دقیقاً در ساعت ۱۱:۰۱:۲۷، چندین فایل PHP در مسیرهای کاملاً تصادفی داخل وردپرس ساخته شده بودند. مثلاً در مسیرهایی شبیه این:
wp-includes/.../uploads/docs/media/.../admin.php wp-admin/.../tmp/resources/.../index.php wp-content/plugins/.../languages/.../admin.php
همه آنها در یک ثانیه ساخته شده بودند و مالک تمام فایلها هم کاربر همان سایت بود، نه root.
یکی از فایلها فقط ۵۰۴ بایت حجم داشت. وقتی بازش کردیم، کد آن تقریباً این کار را انجام میداد:
اتصال به یک دامنه خارجی
غیرفعال کردن بررسی SSL
دانلود کد از راه دور
اجرای مستقیم آن با eval
یعنی فایل روی سرور فقط یک Loader کوچک بود و مغز اصلی بدافزار هر لحظه میتوانست از سرور مهاجم دریافت شود. همان Loader چند دقیقه بعد در مسیر دیگری هم کپی شده بود؛ با هش کاملاً یکسان. این یعنی یک اسکریپت مرکزی داخل سایت، بهصورت خودکار Backdoorها و Loaderهای مختلف را در مسیرهای تصادفی پخش میکرد تا اگر یکی حذف شد، چند نسخه دیگر باقی بماند. ( نفوذی از منم پیگیر تر بود )
یکی از نگرانیهای اصلی من این بود که شاید کسی رمز SSH یا پنل سرور را پیدا کرده باشد ، لاگهای ورود را بررسی کردیم. تلاش برای ورود زیاد بود؛ مثل اکثر سرورهای عمومی، هر چند ثانیه یک ربات با اسمهایی مثل root، scott، omar و دهها نام دیگر رمز امتحان میکرد، اما همه آنها با این وضعیت تمام شده بودند:
Failed password Invalid user preauth
هیچ ورود موفق SSH در زمان حمله پیدا نشد.
لاگهای Cron، Sudo و System Journal را هم بررسی کردیم. در همان ساعت فقط Job عادی ساخت Snapshot توسط CloudPanel اجرا شده بود و نشانهای از اجرای فرمان مشکوک در سطح سیستم وجود نداشت.
در پوشههای زیر هم فایل موقت مشکوکی ساخته نشده بود:
/tmp /var/tmp /dev/shm
تمام فایلهای مخرب فقط داخل همان سایت ساخته شده بودند و مالکشان هم کاربر PHP همان سایت بود.
پس نتیجهای که به آن رسیدیم این بود:
مهاجم به احتمال بسیار زیاد از طریق WordPress، قالب، افزونه یا یک Backdoor قدیمی وارد شده بود؛ نه از طریق SSH و نه با دسترسی Root به کل سرور.
این نتیجه با یک نشانه دیگر هم هماهنگ بود: این بار فقط همین سایت آسیب دیده بود و بقیه سایتهای سرور مشکلی نداشتند.
برای روز ۲۴ ژوئن، یعنی روزی که اولین مجموعه Backdoorها ساخته شده بودند، Access Log کامل در دسترس نبود. به همین دلیل میتوانستیم مسیر حمله، زمان اجرای بدافزار، فایلهای ایجادشده و روش ماندگاری را ببینیم، اما نمیتوانستیم با قطعیت بگوییم اولین درخواست از کدام افزونه یا آسیبپذیری وارد شده است. ممکن بود یک افزونه قدیمی آسیبپذیر بوده باشد، ممکن بود قالب دستکاری شده باشد یا حتی Backdoor از ماهها قبل داخل سایت وجود داشته و تازه در آن روز فعال شده باشد. بنابراین من «اسم دقیق حفره» را پیدا نکردم، اما توانستم سناریوی حمله را تا حد زیادی بازسازی کنم:
یک کد مخرب از قبل در سایت اجرا شده است.
در ۲۴ ژوئن چندین Backdoor و Loader ایجاد کرده است.
در روزهای بعد مهاجم از همان دسترسیها استفاده کرده است.
در ۲۶ ژوئن فرمان خرابکاری اصلی و تغییر نام فایلها اجرا شده است.
بعد از آن هم Webshellهای جدیدی برای حفظ دسترسی ساخته شدهاند.
بعد از اینکه شواهد کافی جمع شد، سایت آلوده را در یک پوشه جداگانه قرنطینه کردم و یک مسیر کاملاً تمیز برای سایت ساختم. هسته وردپرس را از منبع اصلی دوباره دانلود کردم و فایلهای Core با Checksum رسمی بررسی شدند. از wp-content هم فقط فایلهای رسانهای مجاز مثل عکس، ویدئو، PDF و فونت را منتقل کردم. هیچ فایل PHP، افزونه یا قالبی از نسخه آلوده وارد نصب جدید نشد.
دیتابیس را نگه داشتیم، اما اقدامات امنیتی زیر روی آن انجام شد:
همه افزونهها غیرفعال شدند.
Cronهای قدیمی حذف شدند.
Transientها پاک شدند.
تمام Sessionهای کاربران باطل شدند.
Saltهای وردپرس تغییر کردند.
رمز ادمین اصلی عوض شد.
یک حساب Administrator ناشناس هم پیدا شد که من ساختنش را به خاطر نمیآوردم و نیازی هم به آن نبود؛ (این هم یه شک ریزی واسم بود ولی حس میکردم کار خودمه :)) ) واسه همین پیگیر نشدم و فقط حذفش کردم.
در نهایت فقط یک حساب ادمین اصلی باقی ماند.

برای نصب مجدد قالب، نسخهای را که از حساب کاربریام در RTL-Theme دانلود کرده بودم بررسی کردم. داخل فایل دانلودی، علاوه بر قالب و افزونههای همراه، یک Installer و چند فایل مربوط به لایسنس وجود داشت.
اما نکتهای که باعث شد پروسه بازسازی را متوقف کنم، این بود که فایلهای مهمی از قالب، از جمله functions.php، با ionCube رمزگذاری شده بودند.functions.php یکی از اصلیترین فایلهای هر قالب وردپرس است و تقریباً در تمام درخواستها اجرا میشود. وقتی چنین فایلی رمزگذاری شده باشد، من نه میتوانم محتوایش را بررسی کنم، نه میتوانم مطمئن شوم دقیقاً چه کاری انجام میدهد.
در اسکن فایل جدید، هیچکدام از دامنهها، هشها یا الگوهای بدافزار قبلی پیدا نشد. بنابراین مدرکی ندارم که بگویم RTL-Theme یا ناشر قالب عمداً Backdoor در محصول قرار داده است. اما در عین حال نمیتوانم سلامت کامل محصول را هم تأیید کنم. نسخهای که دریافت کردم، نسخه دستنخورده سازنده اصلی نبود؛ یک نسخه بازبستهبندیشده با Installer، سیستم لایسنس و فایلهای رمزگذاریشده بود.
و اینجاست که واسم عجیب شد ، موقع انتشار هر قالبی در سایت بسیار سختگیرانه رفتار میکنن و دوستای وردپرس کارم به شدت از ایرادهایی الکی که میگیرن شاکی هستن پس چطوری این داستان پیش اومده و از دستشون در رفته !! راستش انتقادی بهشون دارم و تجربه ایی واسه خودم بود ولی انتظارم ازشون بیشتر بود و حرفه ایی تر تصورشون میکردم. و اما درسی که گرفتم: وقتی یک فروشگاه، قالب یا افزونه وردپرس میفروشد، صرفاً یک فایل ZIP نمیفروشد. دارد بخشی از زیرساخت سایت، کسبوکار و اطلاعات مشتری را تحویل میدهد. وقتی فایلهای حیاتی یک محصول رمزگذاری میشوند، خریدار عملاً مجبور است بدون امکان بررسی، به فروشنده اعتماد کامل کند. شاید این رمزگذاری فقط برای کنترل لایسنس و جلوگیری از کپی غیرمجاز انجام شده باشد، اما نتیجه برای من بهعنوان خریدار این است که:
نمیتوانم کد را Audit کنم.
نمیتوانم نسخه را با نسخه اصلی سازنده مقایسه کنم.
نمیتوانم مطمئن شوم چه تغییراتی روی قالب انجام شده.
در زمان رخداد امنیتی، نمیتوانم منبع آلودگی را با قطعیت رد یا تأیید کنم.
نمیتوانم با خیال راحت همان فایل را دوباره روی سایت مشتری نصب کنم.
محصولی که روی سرور مشتری اجرا میشود باید شفاف، قابل بررسی و قابل اعتماد باشد.
(نتیجه گیری اصلی: واسه پروژه های مهم بریم نسخه اصلی بخریم ، نه نال شده هایی که ارزون تر فروخته میشن )
ممکن است RTL-Theme هیچ ارتباط مستقیمی با این نفوذ نداشته باشد، اما فروش نسخهای که بخشهای اصلی آن غیرقابل بررسی است، من و مشتری من را در موقعیتی قرار داده که بعد از یک رخداد امنیتی، مجبور شدیم کل سایت را کنار بگذاریم و از صفر بازسازی کنیم.
اولین درس این بود که بکاپ داشتن با امن بودن فرق داره ، زیادی روی بکاپ هفت روزه حساب کرده بودم.
درس دوم این بود که قالب رو از خود توسعه دهنده بخریم نه راست چین. ( ارزونی بی دلیل نیست )
درس سوم اینکه مخرب یا نفوذی این همه زحمت نمیشه که یک فایل مخرب بزاره و پیچیده تر از این حرفا عمل میکنه که راحت مسیرش مسدود بشه . ( ولی خدایی دمش گرم )
این پرونده کاراگاهی شاید با پیدا کردن مجرم تمام نشد، اما باعث شد تصمیم بگیرم چند وقت دیگه دوباره همین بلا سرم نیاد و بازهم یک تجربه جدید کسب کردم و در مسیر حل یک مسئله قدم برداشتم و چیزای جدید یاد گرفتم.
گاهی حل مسئله به معنی تعمیر همان چیزی که شکسته نیست. گاهی بهترین راهحل این است که بفهمی دیگر نباید به آن پایه اعتماد کنی و همهچیز را از نو، اما این بار درستتر بسازی.