WordPress dünyanın en yaygın içerik yönetim sistemi olduğu için aynı zamanda otomatik saldırıların da bir numaralı hedefidir. Bir siteyi yayına aldıktan yalnızca birkaç saat sonra, henüz kimse adresi bilmezken bile giriş kayıtlarında yüzlerce başarısız oturum denemesi görmeye başlarsınız. Bunların neredeyse tamamı gerçek bir insan değil, internetteki her wp-login.php adresini tarayan botlardır. Amaçları basittir: yönetici parolanızı deneme yanılmayla bulup sitenizin kontrolünü ele geçirmek. Bu saldırı biçimine kaba kuvvet, yani brute force denir ve WordPress'in en zayıf noktalarından birini, sınırsız giriş denemesine izin veren varsayılan davranışını hedef alır.
Bu yazıda önce brute force saldırılarının wp-login.php üzerinden nasıl yürütüldüğünü ve bunu kayıtlardan nasıl fark edebileceğinizi anlatacağım. Ardından Limit Login Attempts Reloaded gibi eklentilerle deneme sayısı ve kilitlenme süresini nasıl ayarlayacağınızı, giriş ekranına CAPTCHA eklemenin neden önemli olduğunu ve işi bir üst seviyeye taşımak isteyenler için sunucu tarafında Fail2ban entegrasyonunu adım adım göstereceğim. Amaç, tek bir eklentiye güvenmek yerine birbirini tamamlayan katmanlı bir savunma kurmanızı sağlamak; çünkü kıdemli bir sistem yöneticisi olarak yıllarca gözlemlediğim şey, gerçek koruma sağlayanın tek bir büyülü ayar değil, üst üste dizilmiş küçük engeller olduğudur.
wp-login.php Neden Saldırıların Baş Hedefi?#
Her WordPress kurulumunda oturum açma ekranı öngörülebilir bir adreste bulunur: siteadi.com/wp-login.php veya siteadi.com/wp-admin. Bu tahmin edilebilirlik saldırganların işini kolaylaştırır. Bir bot, tek yapması gereken bu sayfaya kullanıcı adı ve parola çiftlerini POST isteğiyle art arda göndermektir. WordPress varsayılan haliyle kaç kez yanlış denendiğini saymaz; yani saldırgan istediği kadar tahmin yapabilir. Saniyede onlarca isteği, dünyanın dört bir yanındaki binlerce ele geçirilmiş cihazdan (bir botnet üzerinden) dağıtarak gönderdiklerinde, "admin" kullanıcı adına sahip ve zayıf parolalı bir site birkaç saat içinde düşebilir.
Saldırının bir de sinsi bir varyasyonu vardır. XML-RPC arayüzü (xmlrpc.php), tek bir istekte birden fazla giriş denemesini paketlemeye izin verdiği için saldırganlar bunu wp-login.php yerine kullanabilir. Böylece daha az istekle çok daha fazla parola denerler ve giriş sayfasına bakan bazı korumaları atlatırlar. Bu yüzden sadece giriş formunu korumak yetmez; kullanmıyorsanız XML-RPC'yi de kapatmak gerekir. Konunun genel çerçevesini WordPress güvenliği rehberimizde daha geniş ele alıyoruz; burada odağımız özel olarak giriş katmanı olacak.
Brute Force Saldırısını Kayıtlardan Fark Etmek#
Bir saldırının varlığını anlamanın en somut yolu sunucu erişim kayıtlarına bakmaktır. Paylaşımlı hosting kullanıyorsanız cPanel içindeki "Ham Erişim Kayıtları" bölümünden, kendi sunucunuzu yönetiyorsanız doğrudan web sunucusu log dosyasından bu izleri görebilirsiniz. wp-login.php adresine kısa sürede gelen yığın halindeki POST istekleri en belirgin işarettir.
Apache tabanlı bir sunucuda son bir dakikada hangi IP'lerin giriş sayfasını kaç kez zorladığını şöyle özetleyebilirsiniz:
grep "wp-login.php" /var/log/apache2/access.log \
| grep "POST" \
| awk '{print $1}' \
| sort | uniq -c \
| sort -rn | head -20
Çıktının başında tek bir IP'nin yüzlerce satırla belirmesi, o adresin makine hızında parola denediğinin açık kanıtıdır. Gerçek bir kullanıcı dakikada bir veya iki kez giriş dener; 300 kez denemez. Aynı analizi Nginx için /var/log/nginx/access.log üzerinde yapabilirsiniz. Bu tabloyu görmek, hangi savunma ayarlarını sıkılaştıracağınıza da yön verir: saldırı tek bir IP'den geliyorsa engellemek kolaydır, ama binlerce farklı IP'ye dağılmışsa deneme sınırlama ve CAPTCHA gibi kullanıcı odaklı önlemler öne çıkar.
Limit Login Attempts Reloaded ile Deneme Sınırlama#
Sınırsız denemeyi durdurmanın en pratik yolu, başarısız girişleri sayan ve belirli bir eşiği aşan IP'yi geçici olarak kilitleyen bir eklenti kullanmaktır. Bu alanda en çok tercih edilen çözüm Limit Login Attempts Reloaded'dir; ücretsizdir, hafiftir ve kurulumu birkaç dakika sürer. Mantığı basittir: bir IP adresi izin verilen sayıda yanlış parola girerse, o IP belirli bir süre boyunca giriş yapmaktan menedilir. Bot her denemede duvara toslar ve saatte yapabileceği deneme sayısı yüzlerceden bir avuca düşer.
Kurulum için WordPress yönetim panelinde Eklentiler > Yeni Ekle yolunu izleyin, "Limit Login Attempts Reloaded" araması yapın, kurup etkinleştirin. Ardından Ayarlar > Limit Login Attempts ekranındaki şu değerleri gözden geçirin:
- Allowed retries (İzin verilen deneme): Bir kilit döngüsünde tanınan yanlış deneme sayısı. Genellikle 3 veya 4 idealdir.
- Minutes lockout (Kilit süresi): Eşik aşıldığında IP'nin kaç dakika kilitleneceği. 20 ile 60 dakika arası dengeli bir aralıktır.
- Lockouts increase (Uzayan kilit): Belirlenen sayıda kilitten sonra ceza süresini saatlere/günlere çıkarır. Israrcı botları caydırmak için mutlaka açın.
- Trusted IP Origins: Sitenin IP'yi doğru okuması için kritik ayardır. Cloudflare gibi bir ara katman kullanıyorsanız gerçek ziyaretçi IP'sinin başlığını (
X-Forwarded-For) doğru kaynaktan almasını sağlamalısınız; aksi halde tüm trafiği tek IP gibi görüp yanlış kişileri kilitler. - GDPR compliance: IP kayıtlarını KVKK/GDPR uyumlu tutmak için bu seçeneği etkinleştirmenizi öneririm.
Bir de sık atlanan bir nokta var: bu eklentiler oturum açma formunu korur ama saldırgan XML-RPC üzerinden denerse aynı sayacın devreye girdiğinden emin olmalısınız. Limit Login Attempts Reloaded güncel sürümlerinde XML-RPC girişlerini de sayar; yine de kullanmıyorsanız o arayüzü tamamen kapatmak en temiz çözümdür.
Kilit Süresi ve Deneme Sayısı Nasıl Ayarlanmalı?#
Deneme sınırlamada en çok sorulan soru "kaç deneme, kaç dakika?" olur. Doğru cevap sitenin türüne göre değişir. Fazla katı bir ayar, parolasını unutan gerçek müşterileri sürekli kilitleyip destek yükü yaratır; fazla gevşek bir ayar ise botlara yeterince alan tanır. Aşağıdaki tablo farklı site profilleri için başlangıç değerleri olarak kullanabileceğiniz dengeli öneriler sunar.
| Site profili | İzin verilen deneme | İlk kilit süresi | Uzayan kilit | Notlar |
|---|---|---|---|---|
| Kişisel blog / kurumsal tanıtım | 4 | 20 dakika | 24 saat | Tek yöneticili, düşük risk; rahat ayar |
| Üyelikli / çok yazarlı site | 3 | 30 dakika | 24 saat | Müşteri kilitlenmesine dikkat, parola sıfırlama akışı hazır olsun |
| E-ticaret (WooCommerce) | 3 | 60 dakika | 48 saat | Yüksek hedef; CAPTCHA ile birlikte kullanın |
| Yalnızca yönetici girişi (public üye yok) | 2 | 60 dakika | 7 gün | En sıkı; girişi IP kısıtlamayla birleştirin |
Bu değerleri sabit kanun gibi görmeyin; sitenizin giriş kayıtlarını birkaç hafta izleyip gerçek kullanıcıların ne sıklıkla yanlış giriş yaptığını gözlemleyerek ince ayar yapın. Genel kural şudur: gerçek bir kullanıcı üç denemede parolasını ya hatırlar ya da sıfırlama akışına yönelir; dördüncü, beşinci denemeyi yapan neredeyse her zaman bir bottur. Kilit süresini de gereğinden uzun tutmayın — amaç saldırının hızını kırmaktır, kalıcı ceza kesmek değil. Israrcı IP'lerin süresini uzatan "lockouts increase" mekanizması bu dengeyi sizin yerinize otomatik kurar.
Giriş Ekranına CAPTCHA Eklemek#
Deneme sınırlama tek başına güçlü bir önlemdir ama bir açığı vardır: saldırgan on binlerce farklı IP'ye dağılmış bir botnet kullanıyorsa, her IP eşiğe ulaşmadan birkaç deneme yapıp çekilir ve toplu ölçekte yine bolca tahmin gerçekleşir. İşte burada CAPTCHA devreye girer. CAPTCHA, formu gönderen tarafın gerçek bir tarayıcı ve büyük olasılıkla bir insan olduğunu doğrular; ham HTTP isteğiyle formu POST eden basit botları en baştan eler. Böylece deneme sınırlama ile CAPTCHA birbirinin açığını kapatır.
Bugün en dengeli seçenek, kullanıcıya bulmaca çözdürmeden arka planda doğrulama yapan Cloudflare Turnstile veya hCaptcha'dır; klasik reCAPTCHA da yaygındır. WordPress tarafında bu doğrulayıcıları giriş formuna eklemek için çoğu güvenlik eklentisinin (Limit Login Attempts Reloaded'in premium sürümü, WPS Hide Login yanında kullanılan CAPTCHA eklentileri veya bütünleşik güvenlik paketleri) hazır entegrasyonu vardır. Yönetici olmayan hiçbir ziyaretçinin giriş yapmadığı bir sitede ise CAPTCHA'yı sadece wp-login.php sayfasında göstermek yeterli olur ve gerçek kullanıcı deneyimini neredeyse hiç etkilemez.
CAPTCHA'nın kritik ama çoğu zaman gözden kaçan noktası, doğrulamanın sunucu tarafında yapılması gerektiğidir: tarayıcıda widget göstermek tek başına anlamsızdır, sunucunun gönderilen token'ı sağlayıcının API'sine sorup onaylatması şarttır. Bu konunun tüm ayrıntısını ve sağlayıcı karşılaştırmasını CAPTCHA ve bot koruması yazımızda bulabilirsiniz. Trafiği daha web sunucusuna ulaşmadan filtrelemek isterseniz, bir web uygulama güvenlik duvarı (WAF) katmanı giriş sayfasına gelen kaba kuvvet desenlerini eklenti bile devreye girmeden engelleyebilir.
Sunucu Tarafında Fail2ban ile Koruma#
Eklentiler PHP seviyesinde, yani istek WordPress'e ulaştıktan sonra çalışır. Bu, her başarısız denemenin yine de PHP'yi çalıştırıp veritabanını meşgul ettiği anlamına gelir; yoğun bir saldırıda bu tek başına sunucuyu zorlar. Bir üst savunma katmanı, saldırgan IP'yi doğrudan güvenlik duvarında engelleyerek isteğin web sunucusuna bile varmasını önlemektir. Bunun standart aracı Fail2ban'dır: log dosyalarını izler, tanımladığınız desene uyan satırları görünce ilgili IP'yi iptables/nftables üzerinden belirli bir süre banlar. Kendi VDS veya sunucunuzu yönetiyorsanız bu, brute force'a karşı en verimli katmandır çünkü engelleme WordPress'in çok altında, ağ seviyesinde gerçekleşir.
Fail2ban'ın WordPress girişlerini görebilmesi için başarısız denemelerin log dosyasına yazılması gerekir. Bunu ya WP fail2ban gibi bir eklentiyle (girişleri syslog'a yazar) ya da doğrudan web sunucusunun erişim kaydındaki wp-login.php POST desenini yakalayarak sağlarsınız. Erişim kaydı üzerinden çalışan bir filtre örneği:
# /etc/fail2ban/filter.d/wordpress-login.conf
[Definition]
failregex = ^<HOST> .* "POST /wp-login\.php HTTP/.*" 200
^<HOST> .* "POST /xmlrpc\.php HTTP/.*" 200
ignoreregex =
Bu filtreyi devreye alan jail tanımı şöyle görünür:
# /etc/fail2ban/jail.d/wordpress.conf
[wordpress-login]
enabled = true
port = http,https
filter = wordpress-login
logpath = /var/log/apache2/access.log
maxretry = 5
findtime = 300
bantime = 3600
Bu yapılandırma "300 saniye içinde aynı IP wp-login.php'ye 5 kez POST atarsa, o IP'yi 1 saat banla" der. bantime = -1 verirseniz ban kalıcı olur. Kaydı yükleyip durumu şu komutlarla kontrol edersiniz:
sudo systemctl restart fail2ban
sudo fail2ban-client status wordpress-login
sudo fail2ban-client set wordpress-login unbanip 203.0.113.45
Fail2ban'ın genel kurulumunu ve mantığını daha ayrıntılı görmek için Fail2ban kurulumu rehberimize göz atabilirsiniz. Bir uyarı: Cloudflare gibi bir proxy arkasındaysanız, log'daki <HOST> gerçek ziyaretçi yerine Cloudflare IP'sini gösterir. Bu durumda ya gerçek IP'yi log formatına eklemeli (X-Forwarded-For) ya da banı Cloudflare API'si üzerinden uygulayan bir action kullanmalısınız; aksi halde yanlışlıkla Cloudflare'i banlayıp tüm siteyi erişilmez kılabilirsiniz.
Katmanlı Savunma: Girişi Tamamen Sağlamlaştırmak#
Deneme sınırlama, CAPTCHA ve Fail2ban brute force'un hızını kırar; ama gerçekten sağlam bir giriş için bunları birkaç ek önlemle taçlandırmak gerekir. Bu önlemler saldırının başarı olasılığını neredeyse sıfıra indirir.
Web sunucusu seviyesinde en etkili tedbir, giriş sayfasına oran sınırlama (rate limiting) uygulamaktır. Nginx kullanıyorsanız wp-login.php için özel bir limit tanımlayarak saniyedeki istek sayısını kısabilirsiniz:
# http bloğunda
limit_req_zone $binary_remote_addr zone=wplogin:10m rate=2r/m;
# server bloğunda
location = /wp-login.php {
limit_req zone=wplogin burst=4 nodelay;
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
}
Bu ayar aynı IP'nin giriş sayfasına dakikada ikiden fazla istek göndermesini engeller; gerçek kullanıcıyı etkilemez ama botu boğar. Apache/htaccess kullanan paylaşımlı hosting müşterileri ise, sadece kendi IP'lerinden girişe izin verecek şekilde wp-login.php'yi kısıtlayabilir:
# .htaccess — wp-login.php'yi belirli IP'lere aç
<Files wp-login.php>
Require ip 203.0.113.10
Require ip 198.51.100.0/24
</Files>
Bunun dışında hayata geçirmenizi güçlü biçimde önerdiğim üç önlem daha var. Birincisi, yönetici hesabınızda iki faktörlü doğrulama (2FA) kullanmak: parolanız ele geçse bile ikinci faktör olmadan giriş yapılamaz ve bu, brute force'u pratikte anlamsız kılar. İkincisi, "admin" gibi tahmin edilebilir kullanıcı adlarından kaçınıp uzun ve benzersiz bir parola belirlemek. Üçüncüsü, kullanmadığınız xmlrpc.php arayüzünü kapatmak. Tüm bu bakım işlerini kendiniz yürütmek istemiyorsanız, düzenli güncelleme, izleme ve sertleştirmeyi bizim üstlendiğimiz WordPress bakım hizmetimiz ya da yönetimli WordPress hosting paketlerimiz devreye girer; giriş katmanı dahil güvenliği sizin adınıza kurar ve sürekli izleriz.
Sıkça Sorulan Sorular#
Giriş denemesi sınırlama eklentisi sitemi yavaşlatır mı?#
Hayır, kayda değer bir yavaşlama yaşamazsınız. Limit Login Attempts Reloaded gibi eklentiler yalnızca oturum açma isteği geldiğinde çalışır ve küçük bir veritabanı sorgusu yapar; sitenizin normal sayfa yüklemelerine hiçbir yük bindirmez. Aksine, botların sayısız denemesini erken keserek sunucunuzun gereksiz PHP ve veritabanı işlemleriyle boğulmasını önler ve çoğu durumda genel performansı iyileştirir.
Kendimi yanlışlıkla kilitlersem ne yaparım?#
Panik yapmanıza gerek yok; birkaç yolunuz var. En pratiği, kilit süresinin dolmasını beklemek veya farklı bir ağdan (örneğin mobil veri) giriş yapıp eklenti ayarlarından kendi IP'nizin kilidini kaldırmaktır. Kalıcı çözüm için IP'nizi eklentinin "güvenilir/beyaz liste" alanına ekleyin. Tümüyle dışarıda kaldıysanız, FTP veya dosya yöneticisiyle eklentinin klasörünü geçici olarak yeniden adlandırarak devre dışı bırakabilir, giriş yaptıktan sonra geri alabilirsiniz.
Fail2ban mı yoksa eklenti mi kullanmalıyım?#
İdeali ikisini birlikte kullanmaktır, çünkü farklı katmanlarda çalışırlar. Eklenti WordPress seviyesinde davranır ve teknik bilgi gerektirmeden panelden yönetilir; paylaşımlı hosting için genellikle tek seçenektir. Fail2ban ise sunucu seviyesinde, isteği WordPress'e ulaşmadan engeller ve yoğun saldırılarda çok daha verimlidir ama kök erişimi olan bir VDS veya sunucu ister. Kendi sunucunuzu yönetiyorsanız her ikisini de kurun; paylaşımlı hostingteyseniz sağlam bir eklenti ve CAPTCHA kombinasyonu yeterli koruma sağlar.
xmlrpc.php'yi kapatmak zorunda mıyım?#
Zorunlu değil ama çoğu site için şiddetle önerilir. XML-RPC arayüzü tek istekte çok sayıda giriş denemesini paketleyebildiği için brute force saldırganlarının sevdiği bir kapıdır. Jetpack, mobil WordPress uygulaması veya bazı uzak yayınlama araçları kullanmıyorsanız bu arayüze ihtiyacınız yoktur ve kapatmak saldırı yüzeyinizi belirgin biçimde küçültür. Bir güvenlik eklentisinin tek tıkla kapatma seçeneğiyle ya da sunucu yapılandırmasıyla engelleyebilirsiniz.
Giriş sayfasının adresini değiştirmek yeterli bir koruma mı?#
Tek başına yeterli değildir; bunu bir ek katman olarak görün. WPS Hide Login gibi bir eklentiyle wp-login.php adresini gizlemek, adresi rastgele tarayan botların büyük kısmını uzak tutar ve saldırı gürültüsünü azaltır. Ancak bu bir "güvenlik yanılsaması" olabilir: hedefli bir saldırgan gerçek adresi keşfedebilir. Bu yüzden adres gizlemeyi mutlaka deneme sınırlama, CAPTCHA ve güçlü parola gibi asıl önlemlerle birlikte kullanın; onların yerine değil.
Cloudflare kullanıyorum, yine de bu önlemlere gerek var mı?#
Evet. Cloudflare değerli bir ilk katmandır ve kaba kuvvet trafiğinin bir kısmını kenarda süzer, ancak tüm giriş denemelerini otomatik olarak durdurmaz. Ayrıca Cloudflare arkasındayken IP tabanlı önlemleriniz (eklenti ve Fail2ban) gerçek ziyaretçi IP'sini doğru okuyacak şekilde yapılandırılmazsa yanlış çalışır. Cloudflare'i, altındaki WordPress ve sunucu katmanı önlemlerini tamamlayan bir kalkan olarak düşünün; onun yerine geçen bir çözüm olarak değil.
Kapanış#
WordPress'i brute force saldırılarına karşı korumanın sırrı tek bir sihirli ayarda değil, üst üste dizilmiş küçük engellerdedir: giriş denemelerini sınırlayın, giriş ekranına CAPTCHA ekleyin, sunucu seviyesinde Fail2ban ile saldırgan IP'leri banlayın, iki faktörlü doğrulamayı açın ve kullanmadığınız xmlrpc.php gibi kapıları kapatın. Bu katmanların her biri saldırının hızını ve başarı olasılığını düşürür; birlikte çalıştıklarında ise sitenizi otomatik saldırıların erişemeyeceği bir hedef haline getirirler. En kritik nokta, bu önlemleri saldırı gelmeden önce, kurulumun ilk gününde devreye almanızdır.
Bu sertleştirme adımlarını kendiniz kurmak yerine güvenli bir zeminden başlamak isterseniz, güvenlik katmanları önceden yapılandırılmış WordPress hosting paketlerimiz ile ücretsiz SSL ve WAF korumamız işinizi büyük ölçüde kolaylaştırır. Kendi sunucusunu yönetmeyi tercih edenler için yönetimli sunucu hizmetimizde Fail2ban ve güvenlik duvarı kurulumunu biz üstleniriz; mevcut sitenizi taşımak isterseniz de ücretsiz site taşıma ekibimiz devreye girer. Sitenizin güvenliğini şansa bırakmayın; katmanlı savunmayı bugün kurun.