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

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

بخش اول: درک ماهیت حادثه

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

نوع حملههدف مهاجمنشانه اصلی
SEO Spamتزریق لینک و کلمات کلیدیریدایرکت‌ها، صفحات پنهان، پست‌های بی‌ربط
Backdoorدسترسی پایدار برای حملات بعدیفایل‌های PHP ناشناس، کاربران ادمین جدید
Malware Distributionآلوده کردن بازدیدکنندهاسکریپت‌های تزریقی در head و footer
Data Exfiltrationدزدی داده کاربران و مشتریاندسترسی‌های غیرعادی به دیتابیس، دانلود انبوه

در روزهای اول هر پرونده، اشتباه رایج این است که همه هک‌ها یکسان دیده شوند. یک Backdoor با یک Spam ساده تفاوت بنیادین دارد؛ اولی برای دسترسی دوباره است و اگر حذف نشود، شما را چند بار دیگر هک خواهد کرد. دومی کمتر خطرناک است ولی اگر پاک نشود، رتبه سایت را نابود می‌کند.

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

بخش دوم: ساعت صفر، پنج حرکت مهارکننده

ساعت صفر، لحظه‌ای است که می‌فهمید سایت هک شده. در آن دقیقه‌ها، پنج حرکت را به‌همین ترتیب اجرا می‌کنم. هیچ‌کدام از این پنج حرکت، پاک‌سازی نیست؛ همه مهار کردن است.

حرکت اول: سرعت بازدید سایت را نگیرید، ولی ورودی را محدود کنید

سایت را کامل offline نکنید؛ چون در آن صورت بازدیدکننده نمی‌فهمد چه شده و ربات‌های گوگل ممکن است سایت را در دسته سایت‌های خطرناک قرار دهند. در عوض، از طریق فایروال یا htaccess، دسترسی به wp-admin و wp-login.php را به IP خودتان محدود کنید:

# در .htaccess
<Files wp-login.php>
    Order Deny,Allow
    Deny from all
    Allow from 1.2.3.4
</Files>

این کار جلوی ورود مجدد مهاجم را می‌گیرد، ولی سایت برای کاربران عادی سالم به نظر می‌رسد.

حرکت دوم: رمز عبور ادمین را فوراً عوض کنید

اگر مهاجم روی سایت شما است، احتمالاً رمز ادمین شما را دارد. در اولین دقایق، رمز همه اکانت‌های ادمین و مدیر را عوض کنید. اگر شک دارید که دیتابیس آلوده است، بعد از پاک‌سازی، همه رمزها را یک بار دیگر تغییر دهید.

حرکت سوم: دسترسی‌های SSH، FTP و دیتابیس را بچرخانید

چرخاندن credentials (اعتبارنامه‌ها) فقط رمز عبور نیست؛ شامل کلیدهای SSH، حساب‌های FTP، کاربران دیتابیس MySQL (Structured Query Language) و کلیدهای API هم می‌شود. یک Backdoor باقی‌مانده روی سایت، با رمزهای قدیمی دوباره وصل می‌شود.

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

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

حرکت پنجم: به هاست‌تان گزارش دهید

در اکثر پروژه‌ها، تیم پشتیبانی هاست می‌تواند الگوهای حمله را از لاگ‌های سطح سرور تشخیص دهد و به شما در ریشه‌یابی کمک کند. اگر هاست شما این خدمت را ندارد، لاگ‌های access.log و error.log را خودتان دانلود کنید؛ این لاگ‌ها در مرحله ریشه‌یابی طلا هستند.

بخش سوم: بکاپ صحنه جرم، قبل از هر پاک‌سازی

این مرحله، مهم‌ترین و نادیده‌گرفته‌شده‌ترین مرحله در پاک‌سازی است. پیش از هر تغییری روی سایت، از وضعیت آلوده بکاپ بگیرید. این بکاپ را بکاپ صحنه جرم می‌نامم و سه کاربرد دارد:

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

روش بکاپ‌گیری صحنه جرم:

# بکاپ فایل‌ها بدون فشرده‌سازی (برای تحلیل سریع‌تر)
rsync -av --exclude="wp-content/cache" \
    /home/user/public_html/ /backup/forensic/$(date +%Y%m%d)/

# بکاپ دیتابیس
mysqldump -u user -p --single-transaction --routines --triggers \
    database_name > /backup/forensic/$(date +%Y%m%d)/database.sql

اگر بکاپ را با cPanel (کنترل پنل هاست) می‌گیرید، مطمئن شوید که شامل wp-content کامل باشد. اگر با rsync کار می‌کنید، سوییچ --exclude="wp-content/cache" حجم را کم می‌کند بدون از دست دادن داده مهم. راهنماهای مرتبط در بکاپ وردپرس و بکاپ دیتابیس وردپرس آمده است.

بکاپ صحنه جرم، بیمه‌نامه شماست؛ اگر این بکاپ را نگیرید، در صورت شکست پاک‌سازی، وضعیت بدتر از قبل می‌شود.

بخش چهارم: طبقه‌بندی نوع حمله

پس از مهار کردن و بکاپ، نوبت به طبقه‌بندی می‌رسد. سه پرسش را با خودتان بپرسید:

پرسش اول: حمله فقط روی این سایت است یا روی همه سایت‌های هاست؟

اگر هاست شما اشتراکی است و بیش از یک سایت دارد، مهاجم اغلب از یک سایت ضعیف‌تر (یا با افزونه قدیمی) وارد می‌شود و به بقیه سرایت می‌کند. برای بررسی:

# جستجو در همه سایت‌های هاست
find /home/*/public_html/wp-content/plugins \
    -name "*.php" -newer /etc/passwd -mtime -30

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

پرسش دوم: مهاجم از کدام نسخه یا افزونه وارد شده؟

در لاگ سرور، الگوهای درخواست مشکوک را جستجو کنید:

# پیدا کردن درخواست‌های POST مشکوک
grep -E "POST.*(eval|base64|shell|cmd|passwd)" /var/log/apache2/access.log

# پیدا کردن درخواست‌های حاوی .env یا wp-config
grep -E "(wp-config|.env|.git)" /var/log/apache2/access.log

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

پرسش سوم: چه مدت مهاجم روی سایت بوده؟

اگر زمان ورود را بدانید، می‌توانید بفهمید چه بخش‌هایی از سایت آسیب دیده. بررسی تایم‌استمپ فایل‌های تغییر یافته:

find /home/user/public_html -mtime -60 -type f -not -path "*/cache/*" | head -50

این دستور، فایل‌های تغییر یافته در ۶۰ روز اخیر را نشان می‌دهد.

بخش پنجم: شناسایی IOCs و تحلیل لایه‌ای

IOC (Indicator of Compromise) یا شاخص آلودگی، الگوهایی هستند که وجود بدافزار را نشان می‌دهند. در پرونده‌های مختلف، این IOCs را بررسی می‌کنم:

IOC اول: فایل‌های PHP غیرعادی در مسیرهای غیرمنتظره

find /home/user/public_html -name "*.php" \
    -not -path "*/wp-admin/*" \
    -not -path "*/wp-includes/*" \
    -not -path "*/wp-content/plugins/*" \
    -not -path "*/wp-content/themes/*" \
    -not -path "*/wp-content/mu-plugins/*"

هر فایل PHP که در این لیست ظاهر شود و شما یادتان نیاید که ساخته‌اید، مشکوک است.

IOC دوم: فایل‌های PHP در پوشه uploads

find /home/user/public_html/wp-content/uploads -name "*.php"

اگر خروجی این دستور خالی نیست، تقریباً مطمئن باشید که مهاجم از این مسیر استفاده کرده است. پوشه uploads باید فقط شامل فایل تصویر، ویدیو و اسناد باشد.

IOC سوم: توابع خطرناک در فایل‌های قالب و افزونه

grep -rE "(eval|base64_decode|gzinflate|str_rot13|create_function|shell_exec|passthru|proc_open)\(" \
    /home/user/public_html/wp-content/ \
    --include="*.php" | grep -v "wp-includes"

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

IOC چهارم: کد رمزگذاری شده طولانی

grep -rE "[a-zA-Z0-9+/=]{500,}" /home/user/public_html/wp-content/ --include="*.php" | head -20

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

IOC پنجم: تزریق در فایل‌های core وردپرس

فایل‌های هسته وردپرس باید با نسخه اصلی امضا مطابقت داشته باشند. برای بررسی از WP-CLI (رابط خط فرمان وردپرس) استفاده کنید:

wp core verify-checksums
wp plugin verify-checksums --all
wp theme verify-checksums --all

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

IOC ششم: کاربران ادمین غیرمنتظره

wp user list --role=administrator
wp user meta list 1 --format=table

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

در پاک‌سازی، فرض اصلی باید این باشد که هر چیز ناشناخته، مشکوک است؛ تشخیص بر اساس شک، نه بر اساس اطمینان.

بخش ششم: پاک‌سازی لایه فایل

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

گام اول: نصب مجدد هسته وردپرس

wp core download --force --skip-content
wp core update-db

سوییچ --skip-content یعنی فقط فایل‌های هسته دوباره دانلود شوند، بدون دست زدن به محتوا و افزونه‌ها.

گام دوم: نصب مجدد افزونه‌ها و قالب‌ها از منابع رسمی

افزونه‌هایی که در مخزن رسمی وردپرس هستند، با یک دستور نصب مجدد می‌شوند:

wp plugin install $(wp plugin list --field=name) --force
wp theme install $(wp theme list --field=name) --force

افزونه‌های پولی و نال باید دستی بررسی شوند؛ مخصوصاً اگر از منابع غیررسمی نصب شده‌اند. به یاد داشته باشید که رایج‌ترین منبع آلودگی، افزونه‌های نال است. راهنمای تشخیص منبع امن در دانلود افزونه مطمئن آمده است.

گام سوم: پاکسازی فایل‌های اضافی در wp-content

پس از نصب مجدد، هر فایل PHP یا اسکریپت ناشناس در مسیرهای غیراستاندارد را حذف کنید. قبل از حذف، یک لیست از فایل‌های مشکوک بسازید:

find /home/user/public_html/wp-content \
    -type f \( -name "*.php" -o -name "*.phtml" \) \
    -not -path "*/plugins/*" \
    -not -path "*/themes/*" \
    -not -path "*/mu-plugins/*" > /tmp/suspicious.txt
cat /tmp/suspicious.txt

هر فایل در این لیست باید با چشم بررسی شود. اگر با فایل‌های سشن یا کش مطابقت دارد، سالم است؛ در غیر این صورت، مشکوک.

گام چهارم: بررسی مو‌پلاگین‌ها (mu-plugins)

پوشه mu-plugins یک پوشه خاص است که افزونه‌های آن به‌طور خودکار و بدون امکان غیرفعال‌سازی اجرا می‌شوند. مهاجم‌ها این پوشه را دوست دارند چون کاربران عادی آن را نمی‌بینند:

ls -la /home/user/public_html/wp-content/mu-plugins/

هر فایل ناشناس در این پوشه، مشکوک است و باید حذف شود.

گام پنجم: بررسی .htaccess و wp-config.php

مهاجم ممکن است ریدایرکت‌های مخفی در .htaccess یا کد تزریقی در wp-config.php اضافه کرده باشد:

grep -nE "(RewriteRule|ErrorDocument|php_value|auto_prepend)" /home/user/public_html/.htaccess
grep -nE "(eval|base64|gzinflate|file_get_contents)" /home/user/public_html/wp-config.php

روش سخت‌سازی wp-config در امن‌سازی فایل wp-config آمده است. یکی از مهم‌ترین دستورات پیشگیرانه:

chmod 400 /home/user/public_html/wp-config.php

گام ششم: مقایسه تصاویر و فایل‌های media

برخی بدافزارها داخل فایل‌های GIF یا JPG قرار می‌گیرند. برای بررسی:

find /home/user/public_html/wp-content/uploads -type f \
    -name "*.jpg" -o -name "*.gif" -o -name "*.png" | \
    xargs file | grep -v "image data"

اگر فایلی با پسوند تصویر، نوع image data نبود، مشکوک است.

بخش هفتم: پاک‌سازی لایه دیتابیس

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

جستجوی کد مخرب در جدول wp_posts

SELECT ID, post_title, post_name
FROM wp_posts
WHERE post_content LIKE '%base64%'
   OR post_content LIKE '%eval(%'
   OR post_content LIKE '%<script%'
   OR post_content LIKE '%iframe%'
   OR post_content LIKE '%onload=%';

هر رکوردی که در خروجی است، باید دستی بررسی شود. معمولاً به سه دسته تقسیم می‌شوند: محتوای سالم که کد مخرب درون آن تزریق شده، پست اسپم جدید که مهاجم ساخته، و پست‌هایی که اسم‌شان دست‌کاری شده.

جستجوی محتوای مخرب در wp_postmeta

SELECT meta_id, post_id, meta_key
FROM wp_postmeta
WHERE meta_value LIKE '%base64%'
   OR meta_value LIKE '%<script%'
   OR meta_value LIKE '%javascript:%';

جستجوی کد مخرب در wp_options

یکی از رایج‌ترین محل‌های پنهان شدن بدافزار، گزینه‌های autoload در wp_options است:

SELECT option_id, option_name, LENGTH(option_value) as size
FROM wp_options
WHERE autoload = 'yes'
  AND LENGTH(option_value) > 5000
ORDER BY size DESC;

هر گزینه autoload حجیم که نمی‌شناسید، مشکوک است. اگر توضیح لازم دارید، پست کار با Options API در وردپرس را ببینید.

جستجوی کاربران مشکوک

SELECT u.ID, u.user_login, u.user_email, u.user_registered, m.meta_value as capabilities
FROM wp_users u
JOIN wp_usermeta m ON u.ID = m.user_id
WHERE m.meta_key = 'wp_capabilities'
  AND m.meta_value LIKE '%administrator%'
ORDER BY u.user_registered DESC;

هر کاربر ادمینی که در تاریخ مشکوک ثبت شده، حذف شود.

پاکسازی جدول wp_usermeta

SELECT user_id, meta_key
FROM wp_usermeta
WHERE meta_key LIKE '%session_tokens%'
   OR meta_key LIKE '%wp_user-settings%';

حذف session_tokens برای همه کاربران، تمام sessionهای فعال را باطل می‌کند:

DELETE FROM wp_usermeta WHERE meta_key = 'session_tokens';

پاکسازی جدول wp_terms و wp_termmeta

مهاجم‌ها گاهی دسته‌بندی یا برچسب اسپم با کلمات کلیدی خارجی می‌سازند:

SELECT t.term_id, t.name, tt.taxonomy
FROM wp_terms t
JOIN wp_term_taxonomy tt ON t.term_id = tt.term_id
WHERE t.name REGEXP '[آ-ی]' = 0
  AND tt.taxonomy IN ('category', 'post_tag');

این کوئری، دسته‌ها و برچسب‌هایی که فقط حروف لاتین دارند را نشان می‌دهد. سایت فارسی که ناگهان دسته‌بندی تماماً لاتین دارد، معمولاً اسپم است.

دیتابیس، حافظه پنهان سایت است؛ مهاجم‌ها می‌دانند که بعد از پاکسازی فایل‌ها، دیتابیس بازرسی نمی‌شود.

بخش هشتم: پاک‌سازی کاربران، کرون و تنظیمات

پاکسازی کاربران

پس از پاکسازی لایه دیتابیس، سه کار روی کاربران انجام دهید:

  1. حذف کاربران ناشناس: هر کاربری که ثبت‌نامش را به‌یاد نمی‌آورید.
  2. تغییر نقش کاربران مشکوک: اگر کاربر ادمین است ولی نمی‌شناسید، به subscriber تغییر دهید.
  3. باطل کردن sessionهای همه کاربران: از طریق پاکسازی session_tokens در دیتابیس.

پاکسازی کرون

کرون یکی از محل‌های پرکاربرد مهاجم است. با WP-CLI لیست کرون‌های زمان‌بندی‌شده را ببینید:

wp cron event list

هر کرونی که با نام‌های ناشناس یا هش‌مانند است، مشکوک است:

wp cron event delete my_suspicious_hook

راهنمای تفصیلی در عیب‌یابی cron وردپرس.

بررسی و پاکسازی wp-config.php

فایل wp-config.php یکی از محل‌های کلاسیک تزریق بدافزار است. به دنبال این الگوها بگردید:

grep -nE "(eval|base64_decode|gzinflate|include\s*\(|require\s*\(" \
    /home/user/public_html/wp-config.php

فایل سالم wp-config.php فقط شامل ثابت‌های استاندارد وردپرس است:

define( 'DB_NAME', 'database' );
define( 'DB_USER', 'user' );
define( 'DB_PASSWORD', 'password' );
define( 'DB_HOST', 'localhost' );
define( 'AUTH_KEY', '...' );
// ... بقیه ثابت‌ها
$table_prefix = 'wp_';

بعد از پاکسازی، همه ثابت‌های AUTH_KEY و SALTها را عوض کنید. این کار همه sessionهای فعال را باطل می‌کند. راهنمای تولید کلیدهای جدید در سایت رسمی وردپرس وجود دارد.

پاکسازی هدرها در .htaccess

مهاجم‌ها گاهی از طریق .htaccess ریدایرکت‌های هوشمند می‌سازند:

grep -nE "(RewriteRule|RewriteCond|Header set)" /home/user/public_html/.htaccess

هر ریدایرکتی که به دامنه خارجی می‌رود، حذف شود. اگر مطمئن نیستید، کل .htaccess را با نسخه پیش‌فرض وردپرس جایگزین کنید:

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

بخش نهم: ریشه‌یابی و بستن دروازه ورود

بدون ریشه‌یابی، پاکسازی ناقص است. سه مسیر اصلی ورود مهاجم را باید بررسی کنید:

مسیر اول: رمز ضعیف یا لو رفته

در لاگ سرور، به دنبال تلاش‌های Brute Force یا ورودهای موفق از IP ناشناس بگردید:

grep -E "POST /wp-login.php" /var/log/apache2/access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -20

اگر یک IP مشخص بارها تلاش کرده، احتمالاً Brute Force بوده. راهنمای مقابله در حمله Brute Force و روش‌های مقابله.

مسیر دوم: افزونه یا قالب نال یا قدیمی

افزونه‌های نال، کلاسیک‌ترین کانال ورود بدافزار هستند. اگر سایت شما افزونه‌ای از منابع ناشناس دارد، همان را به‌عنوان دروازه ورود فرض کنید. لیست CVE (Common Vulnerabilities and Exposures) افزونه‌های قدیمی در سایت رسمی ثبت شده است. راهنمای تشخیص منبع امن در دانلود افزونه مطمئن آمده است.

مسیر سوم: سرور هاست یا سایت مجاور در هاست اشتراکی

در هاست‌های اشتراکی، اگر یکی از سایت‌های همسایه هک شده باشد، مهاجم می‌تواند به سایت شما هم دسترسی پیدا کند. برای بررسی:

grep -E "POST.*wp-config|GET.*.env" /home/user/logs/*.log

اگر چیز مشکوکی پیدا شد، به هاست خود اطلاع دهید؛ ممکن است این حملات از سطح سرور شروع شده باشد.

ریشه‌یابی، مهم‌ترین بخش پاکسازی است؛ اگر دروازه ورود را نبندید، دو ماه بعد همان مهاجم با همان روش برمی‌گردد.

بخش دهم: تصمیم بازسازی یا تعمیر

پس از پاکسازی، با یک تصمیم سخت روبرو می‌شوید: سایت را همان‌طور که هست برگردانیم یا از صفر بازسازی کنیم؟ جدول تصمیم من:

شرایطتصمیم
آلودگی فقط در چند فایل استتعمیر هدفمند
آلودگی در فایل‌های هسته وردپرسنصب مجدد هسته کافی است
آلودگی در افزونه‌های نالحذف افزونه و بازسازی
آلودگی گسترده در قالب و wp-configبازسازی از بکاپ سالم قدیمی
حساب کاربری هاست هم هک شدهبازسازی کامل روی سرور جدید

اگر آلودگی عمیق است، بازسازی از بکاپ سالم، سریع‌تر و امن‌تر از تعمیر است. اگر بکاپ سالم ندارید، می‌توانید از داده‌های زیر سایت را بازسازی کنید:

  1. محتوای پست‌ها و برگه‌ها: از دیتابیس آلوده استخراج کنید، ولی قبل از بازگرداندن، همه رکوردها را برای IOC بررسی کنید.
  2. کاربران: کاربران ادمین را دوباره بسازید، رمز جدید تعیین کنید.
  3. افزونه‌ها و قالب: همه از منابع رسمی نصب مجدد شوند.
  4. تنظیمات: از ابتدا تنظیم کنید، به‌جای بازیابی از دیتابیس آلوده.

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

بخش یازدهم: سخت‌سازی پس از حادثه

پاک‌سازی، پایان کار نیست؛ سخت‌سازی شروع کار است. هفت مرحله سخت‌سازی که در همه پرونده‌ها اجرا می‌کنم:

گام اول: چرخاندن همه رمزها

رمز پنل هاست، رمز FTP، رمز SSH، رمز دیتابیس، رمز ادمین وردپرس، و کلیدهای API. همه باید یک بار دیگر عوض شوند، چون احتمال اینکه مهاجم رمزهای قدیمی را داشته باشد زیاد است.

گام دوم: فعال‌سازی 2FA روی همه ادمین‌ها

2FA (احراز هویت دو مرحله‌ای) باید اجباری باشد. راهنمای فعال‌سازی در فعال‌سازی 2FA برای کاربران وردپرس و چگونه 2FA امنیت را بالا می‌برد.

گام سوم: نصب افزونه امنیتی

یک لایه دفاعی با افزونه امنیتی معتبر. مقایسه در بهترین افزونه‌های امنیتی وردپرس. نکته مهم: پیش از نصب، افزونه قدیمی امنیتی (اگر داشتید) را حذف کنید تا تعارض نکنند.

گام چهارم: سخت‌سازی wp-config

سه خط زیر به wp-config.php اضافه کنید:

define( 'DISALLOW_FILE_EDIT', true );
define( 'DISALLOW_FILE_MODS', false );
define( 'FORCE_SSL_ADMIN', true );

سوییچ دوم روی false می‌ماند چون در غیر این صورت نمی‌توانید افزونه نصب کنید. اگر سایت شما به‌مدت طولانی بدون نصب افزونه کار می‌کند، می‌توانید آن را هم true بگذارید.

گام پنجم: فعال‌سازی SSL و HTTPS اجباری

اگر سایت شما روی HTTP است، همه‌چیز باید به HTTPS منتقل شود. راهنما در نصب و فعال‌سازی SSL.

گام ششم: تنظیم بکاپ خودکار بیرون‌سروری

بکاپ باید در سروری جدا از سایت باشد، وگرنه در صورت هک هاست، هر دو از دست می‌روند. مسیر بکاپ وردپرس.

گام هفتم: بازبینی کاربران و افزونه‌ها

هر افزونه‌ای که در سه ماه گذشته استفاده نشده، حذف شود. هر کاربری که نقش ادمین دارد ولی نیازی ندارد، تغییر نقش داده شود. این دو کار ساده، سطح حمله را به‌شدت کم می‌کنند.

بخش دوازدهم: پایش هفتاد ساعت اول

هفتاد ساعت اول پس از پاکسازی، حیاتی‌ترین دوره است. اگر بدافزار باقی‌مانده باشد، در همین بازه ظاهر می‌شود. پنج کار پایش:

پایش اول: بررسی خروجی wp core verify-checksums هر روز

wp core verify-checksums
wp plugin verify-checksums --all
wp theme verify-checksums --all

هر تغییری در فایل‌های هسته، نشانه بازگشت بدافزار است.

پایش دوم: پایش ترافیک خروجی سرور

netstat -anp | grep ESTABLISHED | grep -v "127.0.0.1"

اتصالات خروجی به IP ناشناس نشانه بدافزار است.

پایش سوم: بررسی فایل‌های جدید در uploads

find /home/user/public_html/wp-content/uploads -type f -mtime -3

هر فایل جدیدی که خودتان آپلود نکرده‌اید، مشکوک است.

پایش چهارم: بررسی لاگ‌های ورود

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

پایش پنجم: بررسی Google Search Console

در Search Console، بخش Security Issues را روزانه چک کنید. اگر گوگل هشدار جدیدی داد، یعنی بدافزار برگشته.

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

خط پایان

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

سه تجربه شخصی که در همه پرونده‌ها تکرار می‌شوند:

  1. سرعت مهار، مهم‌تر از سرعت پاکسازی است. در ساعت اول، هدف محدود کردن مهاجم است، نه حذف کد او.
  2. بدافزار باقی‌مانده در دیتابیس، بی‌صداترین نوع است. در تجربه من، حدود یک‌سوم بازگشت‌ها به‌خاطر بدافزاری است که در wp_options یا wp_postmeta پنهان شده بود.
  3. ریشه‌یابی، جایگزین‌پذیر نیست. اگر ندایند مهاجم از کجا وارد شده، هیچ‌وقت مطمئن نخواهید بود که پاکسازی کامل است.

اگر امروز درگیر پاکسازی سایت خود هستید، ترتیب کار را حفظ کنید: مهار، بکاپ، تشخیص، پاکسازی لایه‌ای، ریشه‌یابی، سخت‌سازی، پایش. اگر در هر مرحله سوالی داشتید یا سناریوی خاصی دارید که در این راهنما مطرح نشده، در دیدگاه‌ها بنویسید. تجربه‌های واقعی هر پروژه، این پروتکل را دقیق‌تر می‌کند. 🛡️