WordPress Versiyon Bilgisini Gizleme
WordPress sitenizi kurup yayına aldıktan sonra güvenlik konusunu düşünmeye başlıyorsunuz. Peki ya saldırganların ilk baktığı şeyin ne olduğunu hiç düşündünüz mü? Çoğu zaman bu, sitenizin hangi WordPress versiyonunu çalıştırdığıdır. Versiyon bilgisi açıkta kaldığında, bilinen güvenlik açıklarına sahip eski bir sürüm kullanıyorsanız saldırganlar bunu anında fark eder ve hedef alır. Bu yazıda WordPress versiyon bilgisini nerede sakladığını, neden gizlemeniz gerektiğini ve bunu functions.php üzerinden nasıl etkili şekilde yapabileceğinizi ele alacağız.
Neden Versiyon Bilgisini Gizlemeliyiz?
Güvenlik dünyasında “security through obscurity” yani belirsizlik yoluyla güvenlik tartışmalı bir kavramdır. Tek başına bir güvenlik yöntemi olarak kullanmak yanlıştır, ancak derinlemesine savunmanın bir parçası olarak değerlendirildiğinde kesinlikle mantıklıdır.
WordPress versiyon bilgisi varsayılan olarak birkaç farklı yerde açığa çıkar:
- HTML kaynak kodundaki
etiketi wp-login.phpsayfasının kaynak kodu- RSS ve Atom feed’lerindeki generator etiketi
readme.htmldosyası (WordPress kurulum dizininde)wp-jsonREST API endpoint’leri- Stil ve script dosyalarının URL’lerindeki
?ver=parametreleri
Bir saldırgan sitenizi taradığında ilk yaptığı şey bu bilgileri toplamaktır. WordPress 6.3 çalıştırdığınızı öğrendiğinde, o versiyona ait tüm bilinen CVE’leri (Common Vulnerabilities and Exposures) kontrol eder ve buna göre saldırı planlar. Versiyon bilgisini gizlemek bu işi zorlaştırır, imkansız kılmaz ama vakit kaybettirir ve çoğu otomatik tarayıcıyı geri çevirir.
functions.php’ye Neden Dokunuyoruz?
WordPress’te özelleştirmelerin merkezi functions.php dosyasıdır. Plugin kullanmadan, çekirdek dosyalara dokunmadan bu dosya üzerinden WordPress davranışlarını değiştirebilirsiniz. Çekirdek dosyaları düzenlemeniz kesinlikle önerilmez çünkü her WordPress güncellemesinde yaptığınız değişiklikler silinir. functions.php ise temanıza aittir ve güncellemelerden etkilenmez.
Önemli not: Eğer aktif temanızı doğrudan düzenliyorsanız, bir güncelleme geldiğinde değişiklikleriniz silinebilir. Bu yüzden her zaman bir child theme (alt tema) oluşturmanız ve değişikliklerinizi orada yapmanız önerilir.
functions.php Dosyasını Bulma ve Düzenleme
Dosyaya iki farklı şekilde erişebilirsiniz:
FTP/SFTP ile:
# SFTP bağlantısı kur
sftp [email protected]
# Tema dizinine git
cd /var/www/html/wp-content/themes/aktif-temaniz/
# Dosyayı indir
get functions.php
# Düzenleyip tekrar yükle
put functions.php
SSH ile doğrudan düzenleme:
# SSH ile bağlan
ssh [email protected]
# functions.php'yi düzenle
nano /var/www/html/wp-content/themes/aktif-temaniz/functions.php
# Değişiklikleri kaydet
# CTRL+X, Y, Enter
WP-CLI kullanıyorsanız:
# Aktif temayı öğren
wp theme list --status=active
# Tema dizinine git
cd $(wp theme path --active)
# Dosyayı düzenle
nano functions.php
Versiyon Bilgisini Gizleme Yöntemleri
1. Meta Generator Etiketini Kaldırma
HTML kaynak kodunda görünen etiketini kaldırmak için:
<?php
// WordPress generator meta etiketini kaldır
remove_action('wp_head', 'wp_generator');
// RSS feed'den de kaldır
add_filter('the_generator', '__return_empty_string');
Bu iki satır birlikte çalışır. remove_action HTML head bölümünden kaldırırken, add_filter ile RSS/Atom feed’lerindeki generator bilgisini boş string döndürerek temizliyoruz.
2. Script ve Style URL’lerinden Versiyon Parametrelerini Kaldırma
WordPress her script ve CSS dosyasının URL’sine ?ver=6.4 gibi bir parametre ekler. Bu parametre cache yönetimi için kullanılsa da versiyon bilgisini ele verir. Kaldırmak için:
<?php
// Script ve style dosyalarından versiyon parametresini kaldır
function wp_versiyonu_url_den_kaldir($src) {
if (strpos($src, '?ver=') !== false) {
$src = remove_query_arg('ver', $src);
}
return $src;
}
add_filter('style_loader_src', 'wp_versiyonu_url_den_kaldir', 9999);
add_filter('script_loader_src', 'wp_versiyonu_url_den_kaldir', 9999);
Dikkat: Bu yöntemi kullanırsanız tarayıcı cache’i doğru yönetemeyebilir. Eğer bir CDN veya caching plugin kullanıyorsanız bu adımı atlamayı düşünebilirsiniz.
3. WP-Login.php’den Versiyon Bilgisini Temizleme
Giriş sayfasının kaynak kodunda da versiyon bilgisi bulunabilir. Bunu temizlemek için:
<?php
// Login sayfası kaynak kodundaki versiyon bilgisini temizle
function login_sayfasi_versiyon_temizle() {
remove_action('wp_head', 'wp_generator');
}
add_action('login_head', 'login_sayfasi_versiyon_temizle');
// Login sayfasına özel CSS versiyonunu da kaldır
function login_css_versiyon_kaldir($url) {
if (false !== strpos($url, 'wp-login.php')) {
return remove_query_arg('ver', $url);
}
return $url;
}
add_filter('style_loader_src', 'login_css_versiyon_kaldir');
4. REST API’den Versiyon Bilgisini Kaldırma
WordPress REST API, /wp-json/ endpoint’i üzerinden WordPress versiyonunu açığa çıkarabilir. Bu bilgiyi temizlemek için:
<?php
// REST API response'undan versiyon bilgisini kaldır
function rest_api_versiyon_gizle($response) {
if (isset($response->data['namespaces'])) {
// namespaces bilgisini koru ama generator bilgisini temizle
}
if (isset($response->data['description'])) {
unset($response->data['description']);
}
// Versiyon bilgisini kaldır
if (isset($response->data['wp_version'])) {
unset($response->data['wp_version']);
}
return $response;
}
add_filter('rest_index', 'rest_api_versiyon_gizle');
5. Hepsini Bir Arada Kullanan Kapsamlı Fonksiyon
Yukarıdaki tüm yöntemleri temiz ve organize bir şekilde bir arada kullanan örnek:
<?php
/**
* WordPress Güvenlik Sertleştirme - Versiyon Gizleme
* Tüm versiyon açıklarını kapatır
*/
// 1. Meta generator'ı kaldır
remove_action('wp_head', 'wp_generator');
// 2. Feed generator'ı temizle
add_filter('the_generator', '__return_empty_string');
// 3. Tüm URL'lerden versiyon parametresini kaldır
function guvenlik_versiyon_url_temizle($src) {
global $wp_version;
// Sadece WordPress versiyonuyla eşleşen parametreleri kaldır
if (strpos($src, 'ver=' . $wp_version) !== false) {
$src = remove_query_arg('ver', $src);
} elseif (strpos($src, '?ver=') !== false || strpos($src, '&ver=') !== false) {
$src = remove_query_arg('ver', $src);
}
return $src;
}
add_filter('style_loader_src', 'guvenlik_versiyon_url_temizle', 9999);
add_filter('script_loader_src', 'guvenlik_versiyon_url_temizle', 9999);
// 4. REST API versiyon bilgisini gizle
add_filter('rest_index', function($response) {
if (isset($response->data['wp_version'])) {
unset($response->data['wp_version']);
}
return $response;
});
// 5. Login sayfası generator'ını kaldır
add_action('login_head', function() {
remove_action('wp_head', 'wp_generator');
});
// 6. X-Powered-By header'ını temizle (PHP versiyon bilgisi)
if (function_exists('header_remove')) {
add_action('init', function() {
header_remove('X-Powered-By');
});
}
Gerçek Dünya Senaryosu: E-ticaret Sitesi Güvenlik Sertleştirme
Diyelim ki bir WooCommerce mağazanız var ve düzenli güvenlik denetimleri yapıyorsunuz. Bir penetrasyon test uzmanı size rapor sundu ve sitenizin kaynak kodunda WordPress versiyonu açıkça görünüyor. Bu durumda ne yapmalısınız?
Önce mevcut durumu kontrol edin:
# Sitenizin kaynak kodunda versiyon var mı kontrol et
curl -s https://siteniz.com | grep -i "generator"
# Hangi dosyalarda ver= parametresi var
curl -s https://siteniz.com | grep -o 'ver=[^"&]*' | sort -u
# REST API'den versiyon bilgisi geliyor mu
curl -s https://siteniz.com/wp-json/ | python3 -m json.tool | grep -i version
Bu komutların çıktısında versiyon bilgisi görüyorsanız, yukarıdaki kod bloğunu functions.php‘ye ekleyin. Ardından kontrol edin:
# Değişiklikten sonra tekrar kontrol et
curl -s https://siteniz.com | grep -i "generator"
# Bu komut artık hiçbir şey döndürmemeli
# Script/style URL'lerini kontrol et
curl -s https://siteniz.com | grep -o '?ver=[^"]*'
# Bu da boş dönmeli
readme.html ve Diğer Hassas Dosyaları Kaldırma
functions.php tek başına yeterli değil. WordPress kurulumunda bulunan readme.html dosyası versiyon bilgisini açıkça içerir. Bu dosyayı sunucu tarafında kaldırmanız veya erişimi engellemeniz gerekir.
# readme.html dosyasını sil
rm /var/www/html/readme.html
# license.txt dosyasını da sil (isteğe bağlı)
rm /var/www/html/license.txt
# Eğer silmek istemiyorsanız, .htaccess ile erişimi engelle
echo "Options -Indexes" >> /var/www/html/.htaccess
Nginx kullanıyorsanız, site konfigürasyonunuza ekleyin:
# Nginx konfigürasyonu düzenle
nano /etc/nginx/sites-available/siteniz.com
# Şu bloğu server {} içine ekle:
# location ~* /readme.html$ {
# deny all;
# return 404;
# }
# location ~* /license.txt$ {
# deny all;
# return 404;
# }
# Konfigürasyonu test et
nginx -t
# Nginx'i yeniden yükle
systemctl reload nginx
Apache için .htaccess yöntemi:
# .htaccess dosyasını düzenle
nano /var/www/html/.htaccess
# Şu satırları ekle:
# <FilesMatch "^(readme|license|wp-config-sample)..*$">
# Order Allow,Deny
# Deny from all
# </FilesMatch>
WP-CLI ile Toplu Kontrol ve Yönetim
Birden fazla WordPress sitenizi yönetiyorsanız, WP-CLI ile bu işlemleri otomatize edebilirsiniz:
#!/bin/bash
# wp-versiyon-kontrol.sh
# Birden fazla sitede versiyon bilgisi sızıntısını kontrol et
SITELER=(
"/var/www/html/site1"
"/var/www/html/site2"
"/var/www/html/site3"
)
for SITE in "${SITELER[@]}"; do
echo "=== Kontrol ediliyor: $SITE ==="
# WordPress versiyonu öğren
WP_VER=$(wp --path="$SITE" core version 2>/dev/null)
echo "WordPress Versiyonu: $WP_VER"
# Ana sayfada versiyon var mı kontrol et
SITE_URL=$(wp --path="$SITE" option get siteurl 2>/dev/null)
GENERATOR=$(curl -s "$SITE_URL" | grep -i "generator" | head -1)
if [ -z "$GENERATOR" ]; then
echo "TAMAM: Generator etiketi bulunamadı"
else
echo "UYARI: Generator etiketi bulundu: $GENERATOR"
fi
# readme.html var mı
if [ -f "$SITE/readme.html" ]; then
echo "UYARI: readme.html mevcut, kaldırılmalı"
else
echo "TAMAM: readme.html mevcut değil"
fi
echo ""
done
Bu scripti düzenli aralıklarla çalıştırmak için cron job ekleyin:
# Crontab'ı düzenle
crontab -e
# Her gece saat 02:00'de çalıştır
0 2 * * * /bin/bash /root/scripts/wp-versiyon-kontrol.sh >> /var/log/wp-guvenlik.log 2>&1
Child Theme ile Güvenli Uygulama
Değişikliklerinizin tema güncellemelerinden etkilenmemesi için child theme oluşturun:
# Child theme dizini oluştur
mkdir /var/www/html/wp-content/themes/aktif-tema-child
# style.css oluştur
cat > /var/www/html/wp-content/themes/aktif-tema-child/style.css << 'EOF'
/*
Theme Name: Aktif Tema Child
Template: aktif-tema
Version: 1.0
*/
EOF
# functions.php oluştur
cat > /var/www/html/wp-content/themes/aktif-tema-child/functions.php << 'EOF'
<?php
// Ana temayı yükle
add_action('wp_enqueue_scripts', function() {
wp_enqueue_style(
'parent-style',
get_template_directory_uri() . '/style.css'
);
});
// Versiyon gizleme kodlarını buraya ekle
remove_action('wp_head', 'wp_generator');
add_filter('the_generator', '__return_empty_string');
// Diğer güvenlik fonksiyonları...
EOF
# Doğru izinleri ayarla
chown -R www-data:www-data /var/www/html/wp-content/themes/aktif-tema-child
chmod 755 /var/www/html/wp-content/themes/aktif-tema-child
chmod 644 /var/www/html/wp-content/themes/aktif-tema-child/functions.php
Ek Güvenlik Önlemleri
Versiyon gizlemenin yanında functions.php‘ye ekleyebileceğiniz birkaç ek güvenlik önlemi daha var:
<?php
// WordPress admin bilgilerini URL'de gösterme
remove_action('wp_head', 'rsd_link');
remove_action('wp_head', 'wlwmanifest_link');
remove_action('wp_head', 'wp_shortlink_wp_head');
// XML-RPC'yi devre dışı bırak (brute force saldırılarına karşı)
add_filter('xmlrpc_enabled', '__return_false');
// Kullanıcı adlarını REST API'den gizle
add_filter('rest_endpoints', function($endpoints) {
if (isset($endpoints['/wp/v2/users'])) {
unset($endpoints['/wp/v2/users']);
}
if (isset($endpoints['/wp/v2/users/(?P<id>[d]+)'])) {
unset($endpoints['/wp/v2/users/(?P<id>[d]+)']);
}
return $endpoints;
});
// Hata mesajlarını gizle (login sayfasında)
add_filter('login_errors', function() {
return 'Giriş bilgileri hatalı.';
});
Değişikliklerin Doğrulanması
Her şeyi yaptıktan sonra mutlaka doğrulama yapın. Birkaç farklı araç kullanabilirsiniz:
# Temel kontroller
echo "=== Generator Etiketi Kontrolü ==="
curl -s https://siteniz.com | grep -i generator || echo "Temiz!"
echo "=== Feed Generator Kontrolü ==="
curl -s https://siteniz.com/feed/ | grep -i generator || echo "Temiz!"
echo "=== REST API Versiyon Kontrolü ==="
curl -s https://siteniz.com/wp-json/ | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('wp_version', 'Versiyon bilgisi bulunamadı'))"
echo "=== readme.html Erişim Kontrolü ==="
HTTP_CODE=$(curl -o /dev/null -s -w "%{http_code}" https://siteniz.com/readme.html)
if [ "$HTTP_CODE" = "404" ] || [ "$HTTP_CODE" = "403" ]; then
echo "Tamam! HTTP $HTTP_CODE"
else
echo "Uyarı! readme.html erişilebilir: HTTP $HTTP_CODE"
fi
Ayrıca online araçlarla da kontrol edebilirsiniz:
- WPScan: WordPress güvenlik tarayıcısı, versiyon tespiti yapabilir
- Sucuri SiteCheck: Ücretsiz online güvenlik tarayıcısı
- Qualys SSL Labs: Header güvenlik kontrolü için
Sonuç
WordPress versiyon bilgisini gizlemek başlı başına sizi güvende tutmaz, ancak saldırganların işini zorlaştıran ve otomatik tarayıcıları engelleyen önemli bir adımdır. Bu yazıda öğrendiklerinizi özetlersek:
remove_action('wp_head', 'wp_generator')ile meta generator etiketini kaldırırsınızadd_filter('the_generator', '__return_empty_string')ile feed’lerden temizlersiniz- Script ve style URL’lerinden
?ver=parametresini filtrelersiniz - REST API response’undan versiyon bilgisini çıkarırsınız
- Sunucu tarafında
readme.htmlvelicense.txtdosyalarını kaldırır veya erişimini engellersiniz - WP-CLI ile bu kontrolleri otomatize edersiniz
Tüm bu işlemleri child theme üzerinde yapmanız, WordPress veya tema güncellemelerinde değişikliklerinizin korunmasını sağlar. Güvenlik katmanlı bir yaklaşım gerektirir; versiyon gizleme bu katmanlardan sadece biridir. Düzenli güncellemeler, güçlü parolalar, iki faktörlü kimlik doğrulama ve düzenli yedekleme ile birlikte uygulandığında gerçek anlamda sağlam bir güvenlik altyapısı elde edersiniz.
