Tek bir basit istek yeterli: curl -s https://example.com/wp-json/wp/v2/users. Eğer JSON çıktısı slug ve name ile doluysa, sitenizin tüm yazarlarının ve yöneticilerinin kullanıcı adları şu anda herkese açık. Saldırganın tahmin etmesine gerek yok; listeyi alır ve sonra sadece gerçek isimler üzerinde şifreyi dener. Bu, WordPress'teki çoğu credential stuffing saldırısının başlangıç noktasıdır.
Çoğu kişinin ilk tepkisi tüm REST API'yi kapatmaktır. Bu işe yarar, ancak bedelini sonra ödersiniz: Gutenberg blok düzenleyicisi yazıyı kaydetmek için aynı API'yi kullanır, form ve mağaza eklentileri de aynı şekilde. Site görünüşte sağlıklı açılır ve sonra taslak kaydetme veya sipariş kaydında belirsiz bir hata verir. Yani amaç, hassas endpoint'leri kapatmaktır, tüm hizmeti öldürmek değil.
WordPress REST API neden kullanıcı listesini sızdırıyor
Bu davranış bir hata değil; varsayılan tasarımdır. /wp-json/wp/v2/users yolu, istemci tabanlı arayüzler oluşturmak için tasarlanmıştır ve varsayılan olarak yalnızca en az bir yayınlanmış yazısı olan kullanıcıları döndürür. Sorun şu ki, birçok sitede yönetici aynı zamanda yazardır, dolayısıyla yöneticinin kullanıcı adı da aynı listede görünür.
Temiz çözüm, bu endpoint'i misafir kullanıcılar için filtrelemektir. Bu kodu alt tema functions.php dosyasına veya bir mu-plugin'e koyun:
add_filter( 'rest_endpoints', function( $endpoints ) {
if ( ! is_user_logged_in() ) {
unset( $endpoints['/wp/v2/users'] );
unset( $endpoints['/wp/v2/users/(?P<id>[\d]+)'] );
}
return $endpoints;
} );
Bu değişiklikten sonra, ilk curl komutu {"code":"rest_no_route","message":"No route was found..."} döndürmelidir. Hâlâ listeyi görüyorsanız, sayfa önbelleği veya object önbelleği hâlâ eski sürümü sunuyor demektir; önbelleği temizleyin ve tekrar test edin.
Burada hata yapıyorlar
Yaygın hata, yalnızca /wp/v2/users yolunu kapatıp ?author=1 yolunu unutmaktır. WordPress, https://example.com/?author=1 ile sizi yazar arşivine yönlendirir ve nihai URL'de author_name sızar. İşareti de şudur: REST API testiniz geçer ama harici tarama araçları hâlâ kullanıcı adını bulur. Bu yolu kapatmak için yazar arşivi yönlendirmesini devre dışı bırakın veya bir rewrite kuralıyla ana sayfaya yönlendirin.
Hassas endpoint'leri sınırlama ve rate limit
Kullanıcı listesini kapatmak yeterli değil. İki endpoint daha kontrol edilmelidir: bazı ayarlarda taslak içeriği sızdırabilen /wp/v2/posts ve WordPress çekirdeğinde bulunmayan ancak JWT ve uygulama eklentilerinin eklediği kimlik doğrulama yolu.
İstek hızını sınırlamak için iki yolunuz var. Sunucuya erişiminiz varsa, Nginx'te bunu server bloğunun içine koyun:
limit_req_zone $binary_remote_addr zone=wpapi:10m rate=20r/m;
location /wp-json/ {
limit_req zone=wpapi burst=5 nodelay;
limit_req_status 429;
try_files $uri $uri/ /index.php?$args;
}
20r/m sayısı, her IP'den dakikada yirmi istek anlamına gelir. Normal siteler için bu sayı cömerttir; ancak sitenizin mobil uygulaması varsa veya blok düzenleyici sayfasını çok kullanıyorsa, bu sayı gerçek kullanıcılar için 429 hatasına neden olur. Bu durumda burst'ü artırın veya /wp-json/wp/v2/ yolunu sınırlamadan muaf tutun ve yalnızca kimlik doğrulama yollarında katı olun.
Sunucu yapılandırmasına erişiminiz yoksa, güvenlik eklentileri aynı işi PHP katmanında yapar, ancak dikkat edin: her istek hâlâ PHP'ye ulaşır ve işlem yükünü ödersiniz. Yüksek trafikli siteler için ağ kenarında sınırlama, PHP'de sınırlamadan daha iyidir. Siteniz hacim saldırılarının da hefisiyse, bu ayarları DDoS koruması ile birleştirmek, tek bir katmana güvenmekten daha mantıklıdır.
WordPress REST API'de kimlik doğrulama
WordPress varsayılan olarak REST kimlik doğrulaması için çerez ve nonce kullanır. Bu tarayıcı için iyidir, ancak harici uygulamalar için çalışmaz ve bu yüzden geliştiriciler Application Password veya JWT'ye yönelir.
Application Password'ü Kullanıcı → Profil yolundan etkinleştirin. Her şifre belirli bir cihaza bağlanır ve her an iptal edilebilir. Bunu JWT'ye tercih ederim, çünkü JWT'nin WordPress uygulamalarında genellikle ortak bir gizli anahtarı vardır ve bu sızarsa, süresi dolana kadar verilen token'ı iptal etmenin hiçbir yolu yoktur. Application Password'ü o anda silebilirsiniz.
Daha az uyulan nokta: her Application Password yalnızca bir hizmet için olmalıdır. Bir şifreyi yedekleme betiği ile mağaza eklentisi arasında paylaşırsanız, sızıntı anında hangi yolun sızdığını anlayamazsınız ve hepsini iptal etmek zorunda kalırsınız. Bu şifreleri ekipte yönetmek için, Ekiplerde şifre yönetimi yazısında anlatılan ilkeler burada da tam olarak geçerlidir.
Gerçekten kötüye kullanımı engelleyen güvenlik başlıkları
REST yanıtlarında üç başlık en büyük etkiye sahiptir:
X-Content-Type-Options: nosniff— tarayıcının JSON yanıtını HTML olarak yorumlamaması için.- Sınırlı
Content-Security-Policy— bir yerde XSS çalışırsa, kullanıcının çereziyle REST isteği gönderememesi için. *yerine belirliAccess-Control-Allow-Origin— diğer sitelerin kullanıcınızın tarayıcısından istek gönderememesi için.
Açık CORS başlığı tek başına bir güvenlik açığı değildir, ancak kimlik doğrulama çereziyle birleştiğinde tam bir CSRF'ye dönüşür. Bir eklenti bu başlığı açtıysa, öncelikle onu ele alın.
REST isteklerini izleme ve günlükleme
Günlük olmadan, birinin endpoint'lerinizi taradığını anlayamazsınız. Yapabileceğiniz en az şey, 401 ve 429 isteklerini IP ve yol ile günlüğe kaydetmektir. Nginx'te:
log_format apilog '$remote_addr $status $request_uri $http_user_agent';
access_log /var/log/nginx/wpapi.log apilog;
Sonra bir grep " 429 " /var/log/nginx/wpapi.log | awk '{print $1}' | sort | uniq -c | sort -rn | head ile en hızlı saldırganları görürsünüz. Bir IP birkaç dakika içinde yüzlerce kez 429 aldıysa, onu güvenlik duvarında kapatma zamanıdır. Bu günlükleri ana erişim günlüğünden ayrı tutun ve rotasyonları olduğundan emin olun, yoksa sunucu diskini doldururlar. Bu günlükleri saklama ve bozulmadan koruma ilkeleri, Denetim günlüğü nedir yazısında açıklananla aynıdır.
Hangi seçeneği seçmeliyim?
| Yaklaşım | Avantaj | Maliyet | Nerede seçerim |
|---|---|---|---|
| REST API'yi tamamen devre dışı bırakma | Küçük saldırı yüzeyi | Gutenberg ve eklentileri bozar | Statik ve blok düzenleyicisiz siteler |
| Endpoint'leri filtreleme | Siteyi bozmadan güvenlik | Kod bakımı gerektirir | Çoğu site için varsayılan tercihim |
| Nginx'te hız sınırlama | PHP'ye yük bindirmez | Sunucu erişimi gerektirir | Yüksek trafikli ve saldırı hedefi siteler |
Yalnızca bir şey yapabiliyorsanız, /wp/v2/users filtresini ve ?author= kapatmasını yapın. Bu ikisi, siteyi bozma riski en düşükken en yüksek getiriyi sağlar. Hız sınırlamayı, normal site trafiğini engellemediğinden emin olduktan sonra ekleyin.
Herhangi bir değişiklikten önce veritabanı ve dosyaların yedeğini alın ve uyguladıktan sonra curl ve gerçek bir tarayıcıyla test edin. Siteniz ServerNet altyapısında barındırılıyorsa ve bu katmanları ağ tarafından da güçlendirmek istiyorsanız, güvenlik hizmetleri mantıklı bir başlangıç noktasıdır. DNS kayıtlarını ve ağ yollarını hızlıca kontrol etmek için de DNS ve ağ kontrol araçları işi kolaylaştırır.
Sık sorulan sorular
WordPress REST API'yi tamamen devre dışı bırakmak daha mı güvenli?
Mutlaka değil. Tam devre dışı bırakma saldırı yüzeyini azaltır, ancak blok düzenleyici, form eklentileri ve birçok mağaza eklentisi aynı API'yi kullanır ve çalışmaz hale gelir. Çoğu durumda, kullanıcı listesi gibi hassas endpoint'leri filtrelemek daha iyi sonuç verir.
Sitemin WordPress REST API'sinin kullanıcı listesini sızdırdığını nasıl anlarım?
https://example.com/wp-json/wp/v2/users adresine basit bir istek gönderin. Yanıt JSON'u kullanıcı adlarını ve slug'ları içeriyorsa, listeniz herkese açıktır. ?author=1 yolunu da ayrıca test edin, çünkü biri kapalı diğeri açık olabilir.
REST API'de istek hızı sınırlaması kaç olmalı?
Normal siteler için her IP'den dakikada yirmi istek iyi bir başlangıç noktasıdır. Mobil uygulamanız veya blok düzenleyiciyi çok kullanan kullanıcılarınız varsa, bu sayı gerçek kullanıcılar için 429 hatasına neden olur ve burst'ü artırmanız veya okuma yollarını muaf tutmanız gerekir.
Application Password mı yoksa JWT mi daha güvenli?
Çoğu site için Application Password'ü tercih ederim, çünkü her şifre bir cihaza bağlanır ve her an iptal edilebilir. JWT'nin WordPress uygulamalarında genellikle ortak bir anahtarı vardır ve verilen token'ı iptal etmek kolay değildir.
Yorumlar 0
Henüz yorum yok — ilk siz olun!