WordPress Kullanıcı Adı Açıklamasını Gizleme
WordPress sitenizi kurarken güvenlik genellikle ikinci plana atılır. “Önce site çalışsın, sonra güvenliğe bakarız” mantığıyla kurulan sitelerin büyük çoğunluğu, farkında olmadan saldırganlara kapı aralıyor. Bu kapıların en sessiz ama en tehlikelisi ise kullanıcı adı açıklamasıdır.
WordPress, varsayılan olarak kullanıcı adlarını birkaç farklı yoldan dışarıya sızdırır. Bir saldırgan sitenizin admin kullanıcı adını öğrendiğinde, brute force saldırısının yarısını zaten tamamlamış demektir. Geriye sadece şifreyi bulmak kalır. Bu yazıda WordPress’in kullanıcı adını nasıl sızdırdığını, bunu nasıl tespit edeceğinizi ve functions.php üzerinden nasıl tamamen kapatacağınızı ele alacağız.
WordPress Kullanıcı Adını Neden ve Nasıl Sızdırır?
WordPress’in kullanıcı adı açıklaması tek bir noktadan kaynaklanmıyor. Birden fazla vektör var ve bunların hepsini bilmeden sadece birini kapatmak yeterli olmuyor.
Yazar arşiv sayfaları: https://siteniz.com/?author=1 adresine gittiğinizde WordPress sizi otomatik olarak https://siteniz.com/author/kullanici-adi/ adresine yönlendiriyor. Bu yönlendirme URL’sinde kullanıcı adı açıkça görünüyor.
REST API: https://siteniz.com/wp-json/wp/v2/users endpoint’i varsayılan olarak tüm kullanıcıları ve detaylarını JSON formatında döndürüyor. Bu adrese tarayıcınızdan gittiğinizde isim, kullanıcı adı, avatar URL’si gibi bilgiler sergileniyor.
XML-RPC: Eski ama hala aktif olan bu protokol de kullanıcı bilgilerine erişim sağlayabiliyor.
oEmbed: Bazı WordPress sürümlerinde oEmbed yanıtlarında yazar bilgisi sızıyor.
Yazı meta verileri: author meta tagları HTML kaynak kodunda görünebiliyor.
Şimdi bu açıklıkları tek tek nasıl kapatacağımıza bakalım.
functions.php’ye Neden Dokunuyoruz?
Plugin kullanmak yerine functions.php tercih etmemizin birkaç pratik sebebi var. Her şeyden önce plugin yüklemek için yönetici paneline erişim gerekirken, functions.php doğrudan sunucu üzerinden düzenlenebilir. Ayrıca her ek plugin, olası bir güvenlik açığı kaynağı oluyor. Basit bir fonksiyonellik için plugin kullanmak, sorunu çözmek için yeni sorunlar yaratmak anlamına gelebilir.
functions.php dosyanızı düzenlemeden önce her zaman yedek alın. FTP ya da cPanel üzerinden dosyayı indirin, sonra düzenlemeye başlayın. Hata yaparsanız siteniz tamamen çöküyor, bu yüzden bu adımı atlamayın.
1. Yazar Yönlendirmesini Engelleme
İlk ve en kritik adım, ?author=N sorgusunu engellemek. Aşağıdaki kod bu yönlendirmeyi tamamen bloke ediyor.
// functions.php
function gizle_yazar_yonlendirmesi() {
if ( isset( $_GET['author'] ) ) {
wp_die(
'Bu sayfaya erişim yasaktır.',
'403 Yasak',
array( 'response' => 403 )
);
}
}
add_action( 'template_redirect', 'gizle_yazar_yonlendirmesi' );
Bu kod çalıştığında ?author=1, ?author=2 gibi sorgular 403 hatası döndürüyor. Saldırgan kullanıcı adını bu yöntemle öğrenemiyor. Kodu functions.php dosyanıza yapıştırdıktan sonra https://siteniz.com/?author=1 adresine giderek test edin. 403 sayfası görüyorsanız kod çalışıyor demektir.
2. REST API’den Kullanıcı Bilgilerini Kaldırma
REST API çok daha büyük bir açık. Sadece wp-json/wp/v2/users değil, bazı sorguların yanıtlarında da kullanıcı bilgisi sızıyor. Aşağıdaki kod bu endpoint’e erişimi tamamen kısıtlıyor.
// functions.php - REST API kullanici endpoint'ini kapat
function rest_api_kullanici_gizle( $result ) {
if ( ! empty( $result->data['status'] ) ) {
return $result;
}
$current_route = $GLOBALS['wp']->query_vars['rest_route'] ?? '';
if ( strpos( $current_route, '/wp/v2/users' ) === 0 ) {
if ( ! is_user_logged_in() ) {
return new WP_Error(
'rest_forbidden',
'Kullanıcı listesine erişim yasaktır.',
array( 'status' => 401 )
);
}
}
return $result;
}
add_filter( 'rest_pre_dispatch', 'rest_api_kullanici_gizle', 10, 3 );
Bu yaklaşımın güzel yanı, giriş yapmış kullanıcıların (editörler, adminler) API üzerinden çalışabilmesine izin verirken dışarıdan gelen anonim istekleri engelliyor. WooCommerce ya da Gutenberg kullanan sitelerde tam REST API kapatması ciddi sorunlara yol açabildiği için bu seçici yaklaşım çok daha güvenli.
Eğer sitenizde hiç REST API kullanmıyorsanız tümünü kapatabilirsiniz:
// functions.php - Giris yapilmamis kullanicilar icin REST API'yi tamamen kapat
function rest_api_sadece_giris_yapilmis( $access ) {
if ( ! is_user_logged_in() ) {
return new WP_Error(
'rest_not_logged_in',
'REST API erişimi için giriş yapmanız gerekiyor.',
array( 'status' => 401 )
);
}
return $access;
}
add_filter( 'rest_authentication_errors', 'rest_api_sadece_giris_yapilmis' );
Dikkat: Bu kodu WooCommerce ya da Elementor kullanan sitelere uygulamadan önce iyi test edin. Bu araçların bazı özellikleri REST API’ye bağımlı.
3. Yazar Arşiv Sayfalarını Yönetme
Kullanıcı adı yönlendirmesini engellediniz ama yazar arşiv sayfaları hala çalışıyorsa (/author/admin/ gibi), kullanıcı adı yine görünüyor demektir. Bunun için iki seçeneğiniz var:
Seçenek A – Yazar arşivlerini tamamen devre dışı bırakma:
// functions.php - Yazar arsiv sayfalarini kapat
function yazar_arsivi_kapat() {
if ( is_author() ) {
global $wp_query;
$wp_query->set_404();
status_header( 404 );
nocache_headers();
include get_query_template( '404' );
exit;
}
}
add_action( 'template_redirect', 'yazar_arsivi_kapat' );
Seçenek B – Yazar arşivlerini ana sayfaya yönlendirme:
// functions.php - Yazar arsivini ana sayfaya yonlendir
function yazar_arsivi_yonlendir() {
if ( is_author() ) {
wp_redirect( home_url(), 301 );
exit;
}
}
add_action( 'template_redirect', 'yazar_arsivi_yonlendir' );
Tek yazarlı bloglarda genellikle Seçenek A tercih edilir. Çok yazarlı sitelerde ise yazar sayfaları SEO açısından değerli olabildiği için Seçenek B daha mantıklı; en azından URL’deki kullanıcı adını değiştirmek gerekiyor.
4. Oturum Açma Hata Mesajlarını Gizleme
Bu konuyu es geçen sysadminlerin sayısı şaşırtıcı derecede yüksek. WordPress varsayılan olarak şu hataları veriyor: “Bu kullanıcı adı kayıtlı değil” ya da “Bu kullanıcı adı için şifre hatalı.” Bu mesajlar saldırgana doğrudan ipucu veriyor. Kullanıcı adının var olup olmadığını bile söylüyor.
// functions.php - Oturum acma hata mesajlarini genericlestir
function giris_hata_mesajini_gizle( $error ) {
$hata_mesaji = 'Kullanıcı adı veya şifre hatalı. <a href="%s">Şifrenizi mi unuttunuz?</a>';
return sprintf( $hata_mesaji, wp_lostpassword_url() );
}
add_filter( 'login_errors', 'giris_hata_mesajini_gizle' );
Bu değişiklikten sonra kullanıcı adı doğru ama şifre yanlış olsa da, kullanıcı adı hiç yoksa da aynı mesaj görünüyor. Brute force saldırısı yapan bir script artık kullanıcı adının var olup olmadığını tespit edemiyor.
5. HTML Kaynak Kodundan Yazar Bilgisini Temizleme
WordPress, bazı temalarda yazının HTML’ine yazar bilgisini gömiyor. gibi taglar kaynak kodda görünebiliyor. Bunu kaldırmak için:
// functions.php - HTML meta taglarindan yazar bilgisini kaldir
function meta_yazar_kaldir() {
remove_action( 'wp_head', 'wp_generator' );
}
add_action( 'init', 'meta_yazar_kaldir' );
// Yazar slug'ini kullanici adindan degistir
function yazar_slug_degistir( $link, $author_id ) {
$user = get_user_by( 'id', $author_id );
if ( $user ) {
$display_name = sanitize_title( $user->display_name );
$link = str_replace( $user->user_login, $display_name, $link );
}
return $link;
}
add_filter( 'author_link', 'yazar_slug_degistir', 10, 2 );
Bu kod yazar bağlantılarındaki gerçek kullanıcı adını, görünen adla (display_name) değiştiriyor. Yani yazar URL’si /author/admin/ yerine /author/site-yoneticisi/ gibi görünüyor. Kullanıcı panelinde “Görünen Ad” alanını düzgün doldurduğunuzdan emin olun.
6. sitemap.xml’den Kullanıcı Bilgilerini Temizleme
Yoast SEO, RankMath veya WordPress’in kendi sitemap özelliği kullanıcı bilgilerini sitemap’e ekleyebiliyor. Bu da ayrı bir sızıntı noktası.
// functions.php - Yoast SEO sitemap'ten yazar sayfalarini cikar
function yoast_sitemap_yazar_cikar( $excluded_post_types ) {
$excluded_post_types[] = 'author';
return $excluded_post_types;
}
add_filter( 'wpseo_sitemap_exclude_post_type', 'yoast_sitemap_yazar_cikar' );
// Rankmath icin yazar sitemap'ini devre disi birak
add_filter( 'rank_math/sitemap/include_author_sitemap', '__return_false' );
Yoast kullanıyorsanız ayrıca Yoast > Genel > Özellikler bölümünden “Kullanıcı Sitemap’i” seçeneğini de devre dışı bırakın. Plugin ayarları ile kod birbirini desteklesin.
Gerçek Dünya Senaryosu: WooCommerce Sitesinde Uygulama
Bir müşterinin WooCommerce sitesinde bu açıklıkları kapattığımızda yaşadığımız durumu paylaşayım. Site orta ölçekli bir e-ticaret sitesiydi, günlük birkaç yüz sipariş alıyordu. Sunucu loglarına baktığımızda günde ortalama 300-400 kez ?author=1 ve wp-json/wp/v2/users isteklerinin geldiğini gördük. Bunların tamamına yakını farklı IP’lerden otomatik tarama araçlarıydı.
WooCommerce siteleri için dikkat edilmesi gereken önemli nokta şu: WooCommerce’in kendi REST API endpoint’leri var ve bunlar sipariş, ürün, müşteri yönetimi için kritik. Yanlış bir filtreleme WooCommerce’i tamamen bozabilir. Bu yüzden kullandığımız yaklaşım şu şekildeydi:
// functions.php - WooCommerce ile uyumlu kullanici API gizleme
function woocommerce_uyumlu_kullanici_gizle( $result, $server, $request ) {
$route = $request->get_route();
// Sadece /wp/v2/users rotasini hedef al
if ( preg_match( '#^/wp/v2/users#', $route ) ) {
if ( ! is_user_logged_in() ) {
return new WP_Error(
'rest_forbidden',
'Yetkisiz erişim.',
array( 'status' => 403 )
);
}
// Giris yapmis ama admin degilse de engelle
if ( ! current_user_can( 'list_users' ) ) {
return new WP_Error(
'rest_forbidden',
'Bu kaynağa erişim yetkiniz yok.',
array( 'status' => 403 )
);
}
}
return $result;
}
add_filter( 'rest_pre_dispatch', 'woocommerce_uyumlu_kullanici_gizle', 10, 3 );
Bu kod WooCommerce endpoint’lerine dokunmuyor, sadece /wp/v2/users rotasını kilitliyor. Üstelik sadece list_users yetkisine sahip kullanıcılara (adminler) izin veriyor.
Güvenlik Testleri: Açıkları Kapattınız mı?
Tüm bu değişiklikleri yaptıktan sonra test etmeden geçmeyin. Aşağıdaki adımları sırayla kontrol edin:
Manuel test listesi:
https://siteniz.com/?author=1adresine gidin: 403 ya da ana sayfaya yönlendirme görmelisinizhttps://siteniz.com/wp-json/wp/v2/usersadresine gidin: 401/403 hatası görmelisinizhttps://siteniz.com/author/admin/adresine gidin: 404 ya da ana sayfa görmelisiniz- Yanlış kullanıcı adıyla giriş yapmayı deneyin: Genel hata mesajı görmelisiniz
- Doğru kullanıcı adı yanlış şifreyle deneyin: Aynı genel hata mesajını görmelisiniz
WPScan ile test:
Sunucunuzda WPScan kuruluysa şu komutla hızlı bir kullanıcı enumeration testi yapabilirsiniz:
wpscan --url https://siteniz.com --enumerate u
Eğer “No users found” ya da “User enumeration is not possible” çıktısı görüyorsanız başarılı oldunuz demektir. Hala kullanıcı adları listeleniyorsa hangi vektörden sızdığını bulmanız gerekiyor.
Tüm Fonksiyonları Tek Dosyada Toplama
Tüm bu kodları functions.php dosyasına dağıtmak yerine düzenli tutmak için bir güvenlik bölümü oluşturun:
// functions.php
// ========================================
// GUVENLIK: Kullanici Adi Gizleme
// ========================================
// 1. Yazar yonlendirmesini engelle
function gizle_yazar_yonlendirmesi() {
if ( isset( $_GET['author'] ) ) {
wp_die( 'Erişim yasaktır.', '403 Yasak', array( 'response' => 403 ) );
}
}
add_action( 'template_redirect', 'gizle_yazar_yonlendirmesi' );
// 2. REST API kullanici endpoint'ini kapat
function rest_api_kullanici_gizle( $result, $server, $request ) {
if ( preg_match( '#^/wp/v2/users#', $request->get_route() ) && ! is_user_logged_in() ) {
return new WP_Error( 'rest_forbidden', 'Yetkisiz erişim.', array( 'status' => 403 ) );
}
return $result;
}
add_filter( 'rest_pre_dispatch', 'rest_api_kullanici_gizle', 10, 3 );
// 3. Yazar arsivini kapat
function yazar_arsivi_kapat() {
if ( is_author() ) {
global $wp_query;
$wp_query->set_404();
status_header( 404 );
exit;
}
}
add_action( 'template_redirect', 'yazar_arsivi_kapat' );
// 4. Giris hata mesajini gizle
function giris_hata_mesajini_gizle() {
return 'Kullanıcı adı veya şifre hatalı.';
}
add_filter( 'login_errors', 'giris_hata_mesajini_gizle' );
// 5. Yazar slug'ini gercek kullanici adindan ayir
function yazar_slug_degistir( $link, $author_id ) {
$user = get_user_by( 'id', $author_id );
if ( $user ) {
$display_name = sanitize_title( $user->display_name );
$link = str_replace( $user->user_login, $display_name, $link );
}
return $link;
}
add_filter( 'author_link', 'yazar_slug_degistir', 10, 2 );
// ========================================
// GUVENLIK SONU
// ========================================
Bu yapıyı kullanarak tüm güvenlik fonksiyonlarınızı bir arada görüp yönetebilirsiniz.
Ek Önlem: wp-login.php’yi Koruma
Kullanıcı adını gizlemek tek başına yeterli değil. wp-login.php dosyasına erişimi de kısıtlamalısınız. Bunu .htaccess ile yapabilirsiniz:
# .htaccess - wp-login.php'yi belirli IP'lerle kisitla
<Files wp-login.php>
Order Deny,Allow
Deny from All
Allow from YOUR.OFFICE.IP.ADDRESS
Allow from YOUR.HOME.IP.ADDRESS
</Files>
Ya da Nginx kullanıyorsanız:
# nginx.conf - wp-login.php IP kisitlamasi
location = /wp-login.php {
allow YOUR.OFFICE.IP.ADDRESS;
allow YOUR.HOME.IP.ADDRESS;
deny all;
}
Dinamik IP kullanıyorsanız bu yöntem pratik olmayabilir. Alternatif olarak wp-login.php adresini değiştiren bir plugin kullanmayı düşünebilirsiniz, ama bu noktada functions.php yetersiz kalıyor ve plugin kaçınılmaz oluyor.
Sık Yapılan Hatalar
“Kullanıcı adımı admin bırakmayacağım, bu yeterli”: Kullanıcı adını gizlemeden sadece değiştirmek yarım önlem. Saldırganlar hala yeni kullanıcı adını bulabilir. Her iki şeyi de yapın.
“REST API’yi tamamen kapattım, sorun çözüldü”: Eğer Gutenberg, WooCommerce veya sayfa kurucusu kullanıyorsanız bu karar sitenizi bozar. Seçici filtreleme her zaman daha güvenli.
“Sadece functions.php yeterli”: Bu yazıdaki önlemler iyi bir başlangıç ama tek katmanlı güvenlik yeterli değil. İki faktörlü doğrulama, başarısız giriş denemesi kilitleme ve düzenli log analizi de şart.
“Test etmeden geçtim”: Her değişiklikten sonra test yapmak, sorunları erken yakalamanın tek yolu. Özellikle WooCommerce sitelerinde bir fonksiyon tüm alışveriş sepeti akışını bozabilir.
Sonuç
WordPress kullanıcı adı açıklaması küçük görünebilir ama bir brute force saldırısının en kritik adımını kolaylaştırıyor. Saldırganın işini zorlaştırmak güvenliğin temel prensibi; burada da aynı mantık geçerli.
Bu yazıda ele aldığımız yedi farklı kod bloğu ile şu noktaları kapattınız:
?author=Nsorgusu artık çalışmıyor- REST API kullanıcı endpoint’i anonim isteklere kapalı
- Yazar arşiv sayfaları ya devre dışı ya da yönlendirilmiş durumda
- Oturum açma hata mesajları kullanıcı adının var olup olmadığını ele vermiyor
- Yazar URL slug’ları gerçek kullanıcı adından bağımsız
- Sitemap’ten yazar bilgileri temizlenmiş
- WooCommerce uyumluluğu korunmuş
Tüm bu önlemleri uyguladıktan sonra sunucu loglarınızı birkaç gün izleyin. ?author=1 ve wp-json/wp/v2/users isteklerinin nasıl 403 alıp geri döndüğünü görmek tatmin edici. Saldırı bitmez ama en azından boş elleri geri döndürüyorsunuz.
Son olarak, functions.php değişikliklerini tema güncellemelerinden korunmak için çocuk tema (child theme) üzerinden yapın. Ana temanız güncellediğinde tüm bu kodları kaybetmek istemezsiniz.
