2026年11月12日

2026年11月12日

إخفاء إصدار WordPress: وسم generator وكلمة ver= وملف readme.html

هذه المقالة نسخة مُوطَّنة من الأصل الياباني. اقرأ الأصل الياباني

يكتب WordPress رقم إصداره افتراضيًا في HTML الصفحات وفي الخلاصات (Feeds). وقد يستخدم المهاجم هذا الرقم دليلًا لمعرفة هل الإصدار فيه ثغرات معروفة. تشرح هذه المقالة أماكن ظهور الإصدار وخطوات إخفائه. المحتوى وفق وضع أكتوبر 2026.

أول ما ينبغي معرفته أن إخفاء الإصدار إجراء مساعد. فهناك طرق لتخمين الإصدار من محتوى ملفات CSS وJavaScript وغيرها، لذلك لا يضمن الإخفاء منع التعرّف عليه. والأكثر فاعلية هو إبقاء نواة WordPress والإضافات والقوالب محدَّثة.

أماكن ظهور الإصدار

المكان ما يظهر المعالجة
<head> في HTML وسم مثل <meta name="generator" content="WordPress 6.9.4"> الفلتر the_generator
خلاصات RSS وAtom سطر مثل <generator>https://wordpress.org/?v=6.9.4</generator> الفلتر the_generator نفسه
روابط CSS وJavaScript ?ver= مثل style.min.css?ver=6.9.4 الفلترَان style_loader_src وscript_loader_src
ترويسة HTTP X-Powered-By: PHP/8.3.x (إصدار PHP لا WordPress) expose_php في php.ini
readme.html أنك تستخدم WordPress (لا يتضمن readme.html الحالي رقم إصدار) رفض الوصول إليه

لا تتضمن معلومات الموقع التي يعيدها /wp-json/ في REST API (الاسم والوصف وعنوان URL والمنطقة الزمنية ومساحات الأسماء وغيرها) إصدار WordPress. فلا حاجة إلى حذف شيء من مخرجات REST API بغرض إخفاء الإصدار.

الخطوة 1: تحقق من الوضع الحالي للعرض

غيّر العنوان إلى عنوان موقعك ونفّذ الأوامر على جهازك أو على الخادم. وإذا كنت تستخدم إضافات كاش أو CDN فامسح الكاش بعد التغيير ثم تحقق.

# وسم generator في HTML
curl -s https://example.com/ | grep -i 'name="generator"'

# generator في الخلاصة
curl -s https://example.com/feed/ | grep -i '<generator>'

# قائمة قيم ver= الموجودة في CSS وJS
curl -s https://example.com/ | grep -oE 'ver=[0-9][0-9.]*' | sort | uniq -c

# الترويسة X-Powered-By في HTTP
curl -sI https://example.com/ | grep -i 'x-powered-by'

# هل يمكن قراءة readme.html (200 تعني أنه مقروء)
curl -s -o /dev/null -w '%{http_code}\n' https://example.com/readme.html

إذا كانت في قائمة ver= قيمة مطابقة لإصدار WordPress الظاهر في «لوحة التحكم ← التحديثات» (Dashboard → Updates) فهذا يعني أنه يمكن معرفة إصدار WordPress من ملفات CSS وJS تلك. فعندما تحمّل نواة WordPress أو القالب ملفات CSS وJS دون تحديد إصدار، يدخل إصدار WordPress في ver=.

الخطوة 2: حدّد مكان وضع الشيفرة

ضع شيفرة هذه المقالة في أحد موضعين.

  • mu-plugin (الموصى به): ضع ملف PHP في المجلد wp-content/mu-plugins/ (أنشئه إن لم يوجد) فيُحمَّل دون خطوة تفعيل، ويستمر أثره حتى لو غيّرت القالب
  • functions.php في قالب فرعي: إذا كتبتها في functions.php للقالب الأصل فستُمحى عند تحديث القالب

إذا اخترت mu-plugin فاحفظ شيفرة الخطوة التالية كلها في ملف واحد باسم مثل wp-content/mu-plugins/hide-wp-version.php.

الخطوة 3: إخفاء إصدار وسم generator و ver=

<?php
/**
 * Plugin Name: Hide WordPress Version
 * Description: يخفي وسم generator وإصدار WordPress الظاهر في ver= بملفات CSS وJS.
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

// يفرّغ <meta name="generator"> في HTML و<generator> في الخلاصة.
add_filter( 'the_generator', '__return_empty_string' );

/**
 * يستبدل قيمة ver= في CSS وJS بقيمة أخرى فقط عندما تساوي إصدار WordPress.
 * ولأنه يستبدل ver= ولا يحذفه، يتحدّث كاش المتصفح بعد تحديث WordPress أيضًا.
 */
function wpdr_replace_wp_version_query( $src ) {
	if ( ! is_string( $src ) || '' === $src ) {
		return $src;
	}

	$query = wp_parse_url( $src, PHP_URL_QUERY );
	if ( empty( $query ) ) {
		return $src;
	}

	parse_str( $query, $args );
	$wp_version = get_bloginfo( 'version' );

	if ( isset( $args['ver'] ) && $args['ver'] === $wp_version ) {
		$src = add_query_arg( 'ver', substr( wp_hash( $wp_version ), 0, 10 ), $src );
	}

	return $src;
}
add_filter( 'style_loader_src', 'wpdr_replace_wp_version_query', 20 );
add_filter( 'script_loader_src', 'wpdr_replace_wp_version_query', 20 );

النقاط المهمة هي الآتية.

  • يؤثر الفلتر the_generator في وسم generator في HTML وفي generator الخلاصات معًا. أما remove_action( 'wp_head', 'wp_generator' ); فيزيل وسم HTML فقط، فلا يؤثر في الخلاصات
  • إذا حذفت ?ver= كله فقد يستمر المتصفح في استخدام CSS وJS القديمين بعد تحديث إضافة أو قالب. تستبدل الشيفرة أعلاه القيمة بسلسلة أخرى مشتقة من الإصدار عندما تساوي إصدار WordPress فقط. وتتغير القيمة عند تحديث WordPress فيتحدّث كاش المتصفح
  • لا تُغيَّر قيم ver= التي تضع فيها الإضافات أو القوالب أرقام إصداراتها الخاصة

بعد الحفظ تحقق بأوامر الخطوة 1 من أن generator لا يظهر، ومن عدم بقاء إصدار WordPress في قائمة ver=. وإذا كنت تستخدم إضافة كاش فامسح الكاش قبل التحقق.

الخطوة 4: إيقاف ترويسة X-Powered-By

الترويسة X-Powered-By تضيفها PHP لا WordPress، وتكشف إصدار PHP. لإيقافها اضبط expose_php على Off في ملف إعداد PHP (php.ini). ولا يمكن تغيير هذا الإعداد إلا في php.ini.

expose_php = Off

هذا مثال لخادم VPS بنظام Ubuntu يستخدم PHP-FPM (غيّر 8.3 بحسب إصدار PHP لديك).

# تحقق من الإعداد الحالي
grep -n '^expose_php' /etc/php/8.3/fpm/php.ini

# بعد التعديل أعد تشغيل PHP-FPM
sudo systemctl restart php8.3-fpm

في حزمة php.ini لنظام Ubuntu يكون expose_php = Off افتراضيًا. فإذا ظهرت الترويسة فتحقق من أن ملف php.ini آخر لا يُستخدم. وفي الاستضافات المؤجَّرة قد يمكن التغيير من إعدادات PHP في لوحة الإدارة وقد لا يمكن.

وإذا تعذّر عليك تغيير php.ini فيمكن إزالة الترويسة من شيفرة WordPress. لكن send_headers خطاف يعمل عندما يعرض WordPress صفحات الواجهة الأمامية، فلا يؤثر في لوحة التحكم وصفحة تسجيل الدخول.

add_action( 'send_headers', function () {
	header_remove( 'X-Powered-By' );
} );

الخطوة 5: رفض الوصول إلى readme.html وlicense.txt

الملفان readme.html وlicense.txt من ملفات نواة WordPress. لا يتضمن readme.html الحالي رقم إصدار، لكنه يدل على أنك تستخدم WordPress.

وإذا حذفتهما فسيعودان عند تحديث نواة WordPress. ورفض الوصول من خادم الويب أقل جهدًا من الحذف.

في حالة Apache (.htaccess)

أضف إلى .htaccess في مجلد WordPress. ما بين # BEGIN WordPress و# END WordPress يعيد WordPress كتابته، فاكتب خارج هذا النطاق. هذه صيغة Apache 2.4 (Order وDeny from all صيغة قديمة من Apache 2.2).

<FilesMatch "^(readme\.html|license\.txt)$">
    Require all denied
</FilesMatch>

في حالة Nginx

أضف إلى كتلة server الخاصة بموقعك، وتحقق من الإعداد ثم أعد التحميل.

location ~* ^/(readme\.html|license\.txt)$ {
    deny all;
}
sudo nginx -t && sudo systemctl reload nginx

بعد الإضافة نفّذ curl -s -o /dev/null -w '%{http_code}\n' https://example.com/readme.html وتأكد من إعادة 403.

ما لا يمنعه الإخفاء

  • محتوى ملفات CSS وJS في WordPress يختلف قليلًا بين إصدار وآخر، فيمكن تخمين الإصدار بجلب الملفات ومقارنتها
  • قد يُعرف إصدار الإضافة أو القالب من readme.txt أو ver= فيهما. والأكثر استهدافًا هو ثغرات الإضافات لا النواة
  • أما من يستطيع تسجيل الدخول إلى لوحة التحكم فيظهر له الإصدار كما هو

لذلك، إلى جانب إخفاء الإصدار، حدّث النواة والإضافات والقوالب، واحذف الإضافات غير المستخدمة، وعطّل تحرير الملفات في لوحة التحكم.

الخلاصة

  • يظهر الإصدار أساسًا في generator داخل HTML والخلاصات، وفي ?ver= بروابط CSS وJS. ولا يتضمن /wp-json/ في REST API إصدار WordPress
  • يزيل add_filter( 'the_generator', '__return_empty_string' ); generator في HTML والخلاصات معًا
  • لا تحذف ?ver= بل استبدل القيمة المطابقة لإصدار WordPress وحدها، فلا يتوقف تحديث الكاش
  • أوقف X-Powered-By بـ expose_php = Off في php.ini
  • يعود readme.html بعد التحديث حتى لو حذفته، فارفض الوصول إليه من خادم الويب
  • الإخفاء إجراء مساعد، والأهم هو مواصلة التحديث

مقالات ذات صلة:

لديك أسئلة حول WordPress؟ ناشر هذا الموقع موجود في اليابان ويرد باللغة اليابانية. تواصل معنا (باليابانية)

お気軽にご相談ください

お見積りへ お問い合わせへ
▲