در سال‌های کار روی پروژه‌های وردپرسی، یک الگوی تکراری دیده‌ام که همیشه آزارم می‌دهد: سایتِ هک‌شده‌ای که روی آن دو افزونه‌ی امنیتی فعال است، پسوردهای پیچیده تنظیم شده، 2FA روشن است — و با این حال، مهاجم موفق شده. چرا؟ چون مهاجم به‌جای حمله به «در»، از پنجره‌ای وارد شده که کسی آن را ندیده بود: خودِ قالب یا افزونه‌ای که سایت روی آن بنا شده.

امنیت قالب و افزونه، بخشی از امنیت وردپرس است که معمولاً تا لحظه‌ی فاجعه نادیده گرفته می‌شود. برخلاف امنیت ورودی (که با افزونه‌های لاگین و 2FA حل می‌شود)، امنیت پوسته و افزونه‌ها یک فعالیت پیش‌فعالانه و بازرسی‌محور است: قبل از نصب، بعد از نصب، و در طول نگهداری. اگر تازه با این حوزه آشنا می‌شوید، پیشنهاد می‌کنم اول راهنمای امنیت وردپرس برای مبتدیان و افزونه وردپرس چیست و چگونه افزونه مناسب انتخاب کنیم را مرور کنید. این مقاله، ادامه‌ی مستقیم همان دو مقاله در لایه‌ی «بازرسی عملی» است.

چرا امنیت قالب و افزونه، نقطه‌ی کور اکثر صاحبان سایت است؟

پاسخ ساده است: چون بیشتر تمرکز امنیتی، روی «ورودی» است. صاحب سایت می‌آموزد که رمز قوی بگذارد، 2FA فعال کند، ورود ادمین را محدود کند. همه‌ی این‌ها درست است — ولی همه‌ی این‌ها، فقط در یک دروازه را محافظت می‌کنند. قالب و افزونه، دروازه‌ی دیگری هستند که کسی سرش را نمی‌بیند.

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

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

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

نقشه‌ی تهدید: قالب و افزونه چطور سایت را به خطر می‌اندازند؟

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

نوع تهدیدچطور کار می‌کندنشانه‌ی معمول
کد آلوده‌ی تعبیه‌شدهکد مهاجم درون فایل‌های قالب/افزونه قرار داردbase64، eval، فایل‌های ناخواسته در uploads
آسیب‌پذیری شناخته‌شدهنسخه‌ی قدیمی با CVE گزارش‌شدهافزونه‌ای که ماه‌ها آپدیت نشده
نشت از طریق افزونه‌های ثالثافزونه با API بیرونی حساس، اطلاعات را می‌فرستددرخواست‌های خروجی ناشناس در Network

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

گام اول: بازرسی هدر فایل، لایسنس و منبع

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

  1. هدر style.css (در قالب) یا فایل اصلی PHP (در افزونه): باید شامل Theme Name یا Plugin Name، سازنده، نسخه، لایسنس و آدرس لایسنس باشد.
  2. لایسنس: در اکوسیستم وردپرس، استاندارد GPL v2 or later است. اگر جایی نوشته All rights reserved یا Proprietary، پرچم قرمز است.
  3. نسخه و تاریخ آپدیت: فایل readme.txt افزونه یا changelog قالب را باز کنید. آخرین آپدیت کمتر از شش ماه قبل باشد. بی‌سابقه بودن پروژه، نشانه‌ی بدی است.
  4. منبع: از مخزن رسمی وردپرس دانلود شده؟ از سایت خود سازنده؟ از یک مارکت معتبر؟ یا از یک سایت «دانلود رایگان همه‌چیز»؟

این گام، دو دقیقه بیشتر طول نمی‌کشد ولی نود درصد پرونده‌های آلودگی را از همان اول حذف می‌کند. اگر در این مرحله، منبع مشکوک بود، به مرحله‌ی بعد نروید — قالب یا افزونه را کنار بگذارید.

گام دوم: کاوش در فایل‌های PHP و الگوهای آلوده

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

  • eval( — اجرای کد از رشته؛ در ۹۹٪ موارد مشکوک.
  • base64_decode( — اگر همراه eval باشد، الگوی کلاسیک backdoor است.
  • gzinflate( / str_rot13( — توابع فشرده‌سازی که برای پنهان‌کردن کد استفاده می‌شوند.
  • file_get_contents( با URL بیرونی — قالب سالم، از اینترنت بیرون چیزی نمی‌گیرد.
  • shell_exec( / system( / passthru( — اجرای دستور سیستم؛ در قالب یا افزونه‌ی معمولی تقریباً هرگز دیده نمی‌شود.

روش عملی من در پروژه‌های واقعی: پوشه‌ی افزونه یا قالب را در VS Code باز می‌کنم و با Ctrl+Shift+F این پنج الگو را یکی‌یکی جستجو می‌کنم. یک base64_decode تنها، حکم صادر نمی‌کند — بعضی افزونه‌های قانونی هم از آن استفاده می‌کنند. ولی ترکیب base64_decode با eval در فایلی ناشناس، الگوی امضاشده‌ی backdoor است. جزئیات دقیق‌تر این جستجو در بدافزار مخفی در وردپرس چگونه پیدا می‌شود آمده است.

دومین چیز در این گام، بررسی فایل‌های ناخواسته است. یک افزونه‌ی سئو به‌طور طبیعی نباید داخلش یک فایل theme-settings.php داشته باشد. قالب‌های سالم، درونشان فایل‌های PHP با نام‌های هدفمند دارند، نه فایل‌هایی مثل wp-lock.php که در ساختار استاندارد وجود ندارند. اگر ساختار فایل‌های قالب یا افزونه برایتان تازگی دارد، ساختار فایل‌های یک قالب استاندارد وردپرس و ساختار فایل‌های یک افزونه استاندارد وردپرس نقشه‌ی مرجع شما هستند.

گام سوم: بررسی enqueue و اسکریپت‌های تزریق‌شده

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

  1. خطوط wp_footer دست‌کاری‌شده: در footer.php قالب، یا در تابعی که با add_action( 'wp_footer', ... ) وصل شده، به‌دنبال echo با محتوای ناشناس بگردید.
  2. اسکریپت‌های بلااستفاده در Network: سایت را در DevTools باز کنید و تب Network را نگاه کنید. اگر درخواستی به دامنه‌ای ناشناس وجود دارد که مربوط به افزونه‌های شما نیست، پرچم قرمز است.
  3. فایل‌های ناشناس در wp-content/uploads/: پوشه‌ی uploads، محل تصویر و فایل است، نه PHP. اگر در آن فایل .php دیدید، بدون تردید آلودگی است.

نکته‌ای که در پروژه‌های واقعی زیاد دیده‌ام: خطوط تزریق‌شده در footer، اغلب با کامنت‌های فریبنده مثل // optimization helper یا // cache preloader همراه هستند. هیچ افزونه‌ی سالمی برای «بهینه‌سازی سرعت» به‌صورت دستی در footer کد اضافه نمی‌کند — این ادعا خودش یک پرچم قرمز است.

گام چهارم: تست سازگاری و تعارض پیش از فعال‌سازی

این گام، بیشتر به کیفیت نگهداری مربوط است تا امنیت مستقیم — ولی نتایج آن، به‌طور غیرمستقیم روی امنیت اثر می‌گذارد. افزونه‌ای که با سایر افزونه‌ها تعارض دارد، اغلب منجر به غیرفعال‌شدن یا دورزدن‌شدن لایه‌های امنیتی دیگر می‌شود. تست سازگاری پیش از فعال‌سازی، سه بخش دارد:

  • سازگاری با نسخه‌ی وردپرس و PHP: در readme.txt بررسی کنید که حداقل نسخه‌ی پشتیبانی‌شده چقدر است. اگر روی PHP 7.4 تست شده ولی سایت شما روی PHP 8.2 است، محیط تست لازم است.
  • تعارض با افزونه‌های حیاتی: افزونه‌ی جدید را روی محیط لوکال نصب کنید و با افزونه‌های فعلی (کش، سئو، فرم‌ساز) تست کنید. مسیر کامل در چگونه سازگاری افزونه‌های وردپرس را بررسی کنیم آمده.
  • بررسی نبود behavior مشکوک: بعد از فعال‌سازی، با DevTools ببینید افزونه‌ی جدید به کدام دامنه‌های بیرونی درخواست می‌فرستد. بعضی افزونه‌های «رایگان» اطلاعات سایت شما را به سرور خودشان می‌فرستند.

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

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

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

  1. افزونه‌ی امنیتی با اسکنر امضامحور: افزونه‌هایی مثل Wordfence یا Sucuri، فایل‌های هسته، قالب و افزونه را با نسخه‌ی رسمی مقایسه می‌کنند. اگر فایلی متفاوت بود، گزارش می‌دهند. فهرست و تحلیل کامل‌شان در بهترین افزونه‌های امنیتی وردپرس برای محافظت از سایت آمده است.
  2. اسکنرهای آنلاین مستقل: ابزارهایی مثل Sucuri SiteCheck یا VirusTotal که بدون نصب، از بیرون سایت را اسکن می‌کنند. ارزش این‌ها در این است که «چشم دومی» هستند — همان منطق دو نگاه متفاوت.
  3. ابزارهای تحلیل کد (SAST): برای توسعه‌دهنده‌های جدی، ابزارهایی مثل PHPStan یا SonarQube که کد را تحلیل ایستا می‌کنند. این‌ها برای بررسی افزونه‌های سفارشی خیلی مفیدند.

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

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

نشانه‌های قرمز امنیتی که باید فوراً شما را متوقف کنند

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

  1. eval یا base64_decode همراه با هم در فایل ناشناس.
  2. فایل PHP در wp-content/uploads/.
  3. درخواست‌های خروجی به دامنه‌های ناشناس در Network.
  4. حذف یا تغییر فایل readme.txt یا changelog.
  5. فایل‌های nاشناس در پوشه‌های عمیق با نام‌های شبیه هسته (مثل wp-config.php.bak).
  6. نبود آپدیت بیش از ۱۲ ماه.
  7. منبع دانلود ناشناس، همراه با نسخه‌ی نال‌شده (Nulled).

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

اگر قالب یا افزونه‌ی آلوده نصب شده باشد، چه کنیم؟

این سناریویی است که هیچ‌کس دوست ندارد به آن برسد، ولی دانستن ترتیب مراحل در آن، تفاوت بین «یک روز تعمیر» و «دوهفته کابوس» است:

  1. بکاپ لحظه‌ی جرم بگیرید. قبل از هر تغییر، یک بکاپ کامل از فایل‌ها و دیتابیس بگیرید. این نسخه، ممکن است بعداً برای تحلیل «از کجا آمد» لازمتان شود.
  2. منبع را قطع کنید. قالب یا افزونه‌ی مشکوک را غیرفعال کنید. اگر دسترسی به پیشخوان ندارید، پوشه‌اش را از طریق FTP یا File Manager تغییر نام دهید.
  3. اسکن عمیق اجرا کنید. با ابزارهای اسکن، کل سایت را برای فایل‌های ناشناس بررسی کنید. مسیر کامل در راهنمای پاک‌سازی سایت وردپرسی هک شده و پاک‌سازی بدافزار وردپرس بدون از دست دادن داده آمده است.
  4. رمزها و کلیدها را بچرخانید. بعد از پاکسازی، رمزهای وردپرس، FTP، دیتابیس و کلیدهای API را عوض کنید. backdoor باقی‌مانده، رمزهای قدیمی را می‌جوید.
  5. اگر آلودگی عمیق بود، بازنصب هسته. در موارد پیشرفته، تنها راه مطمئن، بازنصب هسته‌ی وردپرس از منبع رسمی و بازگرداندن داده‌ی سالم است. زمان‌بر است ولی «تمیزی قطعی» را می‌خرد.

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

عادت‌های پیشگیرانه برای نگهداری بلندمدت

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

  • پیش از هر نصب، لیست مجاز را چک کنید. در تیم‌های حرفه‌ای، لیستی از قالب‌ها و افزونه‌های تأییدشده وجود دارد و هر نصب جدید باید از این لیست عبور کند. اضافه‌کردن یک افزونه به این لیست، یعنی کسی آن را بررسی کرده و مسئولیتش را پذیرفته.
  • هر سه ماه، بازرسی دوره‌ای. فهرست افزونه‌ها را مرور کنید. هر افزونه‌ای که در سه ماه گذشته «لم نخورده»، کاندیدای حذف است. افزونه‌ی حذف‌نشده، ریسک امنیتی بی‌دلیل است.
  • پایش هفتگی خروجی Network. یک اسکرین‌شات از درخواست‌های یک صفحه‌ی نمونه بگیرید و هر هفته مقایسه کنید. درخواست جدید ناشناس، زنگ خطر اولیه است.

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

نگاه سطح بالا: مدیریت زنجیره‌ی تأمین نرم‌افزار در وردپرس

برای توسعه‌دهنده‌ای که در محیط‌های مهندسی بزرگ کار کرده، مسئله‌ی «امنیت قالب و افزونه» یک نام دقیق‌تر دارد: Software Supply Chain Security. در وردپرس، ما به‌طور روزمره با یک زنجیره‌ی تأمین نرم‌افزاری طرفیم — بخشی از آن رسمی (مخزن وردپرس)، بخشی نیمه‌رسمی (مارکت‌های ثالث)، و بخشی کاملاً غیررسمی. این زنجیره، چهار حلقه دارد که هر یک می‌تواند آلوده شود:

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

این چهار حلقه، به یک اصل مهندسی ساده می‌رسند: هر فایلی که با دسترسی اجرا روی سرور شما می‌نشیند، یک مؤلفه‌ی زنجیره‌ی تأمین شماست و باید مثل یک dependency در یک پروژه‌ی نرم‌افزاری مدیریت شود. یعنی: منبع مشخص، نسخه‌ی قفل‌شده، بازرسی اولیه، و پایش مداوم. همین انضباط را اگر روی وردپرس اعمال کنید، در عمل از ۹۰٪ پروژه‌های نرم‌افزاری جهان جلوتر هستید. برای زمینه‌ی بیشتر، چرا وردپرس هدف حملات سایبری است و گیت در وردپرس را در نظر بگیرید.

بازرسی، عادت است نه پروژه

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

قدم عملی امشب‌تان: فهرست افزونه‌های فعلی سایت را باز کنید و برای هرکدام، سه سؤال را بپرسید — از کجا آمده؟ آخرین آپدیتش کِی بوده؟ و آیا از آن استفاده می‌کنم؟ هر سه پاسخ روشن بود، سایت شما در وضعیت بهتری از اکثر سایت‌های وردپرسی جهان است.

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