WordPress XML-RPC: Devre dışı bırakmanın 3 yolu & xmlrpc.php saldırılarını tespit etme | Jetpack istisnası

Satış ortaklığı bildirimi v3.1
Satış ortaklığı bildirimi v3.2 (yalnızca mobil)

WordPress web sitenizin erişim günlüğünde aynı IP'den yüzlerce xmlrpc.php isteği art arda geliyorsa bu, WordPress XML-RPC'yi hedef alan bir şifre deneme saldırısıdır. Birden fazla WordPress sitesi çalıştıran Nginx + Apache yapısındaki bir sunucunun bir günlük erişim günlüğündeki 8.624 kaydı sınıflandırdım, devre dışı bırakmanın üç yolunu kendim uygulayıp yanıt kodlarını kontrol ettim ve PHP çalıştırmalarını da azaltmak için hangi katmanda engellemek gerektiğini derledim.

XML-RPC, HTTP üzerinden XML belgeleri alıp vererek WordPress işlevlerini uzaktan çağıran bir protokoldür; WordPress 3.5'ten beri ayarlar ekranında açıp kapatma seçeneği olmadığı için kurulumdan hemen sonra açık olarak çalışır.

1️⃣ xmlrpc.php'nin görevi ve kullanıldığı yerler

REST API çıktıktan sonra [xmlrpc.php] artık kullanılmayan bir dosya gibi görünse de Jetpack siteyi bugün hâlâ bu dosya üzerinden WordPress.com'a bağlar. Jetpack'in resmî belgeleri XML-RPC bağlantısına dayandığını açıkça belirtir; XML-RPC'yi varsayılan olarak engelleyen hostinglerde Jetpack bağlantısı hiç kurulamaz. Bugün bile ofiste bir faks numarasını tutmaya benzer.

WordPress 7.1 itibarıyla bu dosyanın kabul ettiği yöntem sayısı 77'dir: yazıları, ortamı ve yorumları yöneten wp ailesinden 50, eski blog protokollerinden (MetaWeblog, MovableType, Blogger) 23, pingback için 2 ve test amaçlı demo için 2.

wp ailesi istek gövdesindeki kullanıcı adı ve şifreyle giriş yaptığı için giriş ekranından geçmez. Yazı yazma ve düzenleme, ortam yükleme ve yorum yönetiminin hepsi bu ailededir; eski blog protokollerinin 23 yöntemi ise diğer blog araçlarıyla aynı şekilde yazı alıp vermek için korunmuştur.

demo.sayHello, WordPress XML-RPC'de bulunan bir test çağrısıdır. Gönderildiğinde yalnızca [Hello!] kelimesini döndürür; giriş gerektirmediği için XML-RPC'nin çalışıp çalışmadığını kontrol etmekte kullanılır. Eşi olan demo.addTwoNumbers iki sayıyı toplayıp sonucu döndürür.

Hepsi yalnızca POST ile gönderilen XML gövdesine yanıt verir; adresi tarayıcıda açarsanız [XML-RPC server accepts POST requests only.] iletisiyle birlikte 405 döner.

Pingback'ler de bu dosyanın işidir. Bir yazı yayımladığınızda metinde bağlantı verdiğiniz sitelerin xmlrpc.php dosyasına pingback gönderilir; alıcı sunucu gönderen adresi kendisi açarak bağlantının gerçekten var olup olmadığını kontrol eder.

🧭 xmlrpc.php'ye gelen istekler ve işlenişi
wp-admin güvenliğiAçıklama diyagramı
📨 Gönderen
↓
Giriş noktası
xmlrpc.php
Yalnızca POST ile gönderilen XML gövdesini işler
405 · XML-RPC server accepts POST requests only.
77 yöntem
wp.*yazılar · ortam · yorumlar, 50
metaWeblog · mt · bloggereski blog protokolleri, 23
pingback.*pingback, 2
demo.*çalışmayı kontrol eden test çağrıları, 2
Sonuç
WordPress.com bağlantısını korur
İstek gövdesindeki kullanıcı adı ve şifreyi kontrol eder → yazı yazar, düzenler
Sunucu gönderen adresi kendisi açıp bağlantıyı kontrol eder
Giriş olmadan: Hello! Yanıt
İşlem yok
Jetpack, WordPress.com ile bağlantısını bu dosya üzerinden sürdürdüğü için dosyayı engellerseniz bağlantı kopar.
Harici yayın araçları istek gövdesine koydukları kullanıcı adı ve şifreyle giriş yapar ve giriş ekranından geçmez.
Yazıda bağlantı verilen sitenin xmlrpc.php dosyasına pingback gönderilir; alıcı sunucu gönderen adresi kendisi açarak bağlantıyı kontrol eder.
demo.sayHello, XML-RPC'nin çalışıp çalışmadığını kontrol eden bir test çağrısıdır; giriş olmadan tek kelimeyle, [Hello!] diye yanıt verir.
Adresi tarayıcıda açarsanız [XML-RPC server accepts POST requests only.] iletisiyle birlikte 405 döner.

2️⃣ Erişim günlüğünde xmlrpc.php saldırıları

Şifre deneme saldırıları giriş ekranından geçmeden [xmlrpc.php] üzerinden gelir. Birden fazla WordPress sitesi çalıştıran Nginx + Apache yapısındaki bir sunucunun 14 Ekim 00:00–20:00 arası erişim günlüğünde POST /xmlrpc.php isteği 8.624, IP sayısı 72'ydi; bunlardan 19 IP tam 300'er istek gönderdi.

Bir IP 14:09'dan 14:37'ye kadar 28 dakikada 300 istek gönderdi ve 5–6 saniyelik aralık sonuna kadar sabit kaldı. 8.524 istek User-Agent'ta Jetpack ya da WordPress.com yazarak geldi; aynı IP, [Jetpack by WordPress.com (Jetpack 13.0; WordPress 6.3)] gibi gerçek Jetpack biçimini taklit eden birkaç değeri dönüşümlü kullandı.

Aynı gün saat 14:00'e kadar güvenlik eklentisinin XML-RPC'yi kapatma ayarı bu istekleri 302 ile ana sayfaya geri yolladı; 14:00'ten sonra Nginx'te engellendiğinde ise 403 ile bitti. 302, gövde 0 bayt olsa bile her istekte PHP'nin çalıştığını gösterir; 403 ise PHP'den geçmemiş bir yanıttır.

🧭 Erişim günlüğünün tek satırında xmlrpc.php saldırısı
Açıklama diyagramı
🛡️ Sunucu durumu
Erişim günlüğünden tek satır (Nginx access.log)
203.0.113.25IP[14/Oct/2026:14:09:04 +0900]Zaman"POST /xmlrpc.php HTTP/1.1"İstek302403Durum0153Bayt"Jetpack by WordPress.com (Jetpack 13.0; WordPress 6.3)"User-Agent
PHP çalışır · ana sayfaya 302PHP'ye uğramaz · Nginx varsayılan 403 sayfası
Güvenlik eklentisi XML-RPC'yi kapattığında isteği ana sayfaya geri yollayan 302 kaydedilir. Gövde 0 bayttır ama bu 302'yi üretmek için PHP çalışır.
Nginx'te engellediğinizde 403 ve 153 baytlık varsayılan hata sayfası kaydedilir, PHP çalışmaz.
Aynı IP'den gelen istekler
14:09:0414:37:20
28 dakikada 300 istek, 5–6 sn arayla
00:00–20:00 arası 8.624 POST72 IP300'er istek gönderen 19 IPJetpack·WordPress.com taklidi UA ile 8.524

3️⃣ system.multicall ve şifre deneme

[system.multicall] ile tek istekte yüzlerce şifrenin denendiğini söyleyen açıklamalar çoktur; ancak WordPress bir istek içinde giriş bir kez başarısız olursa kalan çağrıların şifrelerini karşılaştırmaz. Yalnızca ilk çağrı wp_authenticate'ten geçer, sonraki çağrılar kontrol edilmeden aynı hatayla, [Incorrect username or password.] ile yanıtlanır.

Her çağrı için yanıt yine de döndüğünden, 100 yanlış şifre taşıyan tek bir istek 0,12 saniyede 23 KB'lık bir yanıtla 100 hata alır. Aynı istekte doğru şifre sonra gelirse önceki çağrının başarısızlığı yüzünden o da reddedilir; başa konursa yalnızca o çağrı başarılı olur. Şifre karşılaştırması bir kez yapılır, ama XML ayrıştırma ve WordPress'in yüklenmesi her istekte tekrarlanır; bu yüzden bu saldırının sunucu yükü giriş kontrolünden değil, doğrudan istek sayısından kaynaklanır.

4️⃣ XML-RPC'yi devre dışı bırakmanın 3 yolu ve yanıt kodları

XML-RPC'yi eklentide kapatsanız da [xmlrpc.php] istekleri PHP'ye kadar gelir. Filtreyle kapalıyken 100 çağrılık bir istek gönderdiğimde yine HTTP 200 ile 100 hata (24 KB) döndü. İsteği hangi katmanın reddettiğine göre yöntem üçe ayrılır ve her birinin yanıt kodu farklıdır.

1. xmlrpc_enabled filtresiyle kodla kapatma

Temanın functions.php dosyasına [xmlrpc_enabled] filtresini false döndüren tek satırlık bir add_filter eklemeniz yeterlidir. Bu durumda giriş gerektiren çağrılar [XML-RPC services are disabled on this site.] hatası ve HTTP 405 ile reddedilir; ancak giriş gerektirmeyen test çağrısı demo.sayHello hâlâ 200 ile yanıt verir.

2. Eklenti ayarlarıyla kapatma: Perfmatters · Hide My WP

Perfmatters ve Hide My WP gibi eklentilerdeki Disable XML-RPC ayarıyla devre dışı bırakma yöntemidir. Hide My WP yukarıdakiyle aynı filtre yöntemini kullandığı için yanıtları da aynıdır; Perfmatters ise aynı filtreye ek olarak [xmlrpc.php]'ye gelen doğrudan istekleri 403 ile bitirir, pingback başlığını ve pingback bağlantısını da kaldırır; bu yüzden kapattıktan sonra GET de POST da 403 ile yanıtlanır. Ancak bu 403'ü vermek için WordPress init aşamasına kadar çalıştığından yanıt, açıkken olduğu gibi 0,13–0,15 saniye sürer ve PHP yükü kalır.

🔌 Eklenti ayarlarından XML-RPC'yi kapatma
📍 Settings › Perfmatters › General › Core › Disable XML-RPC
Anahtarı açıp [Save Changes]'e basınca aşağıdaki ziyaretçi ekranı değişir.
Yönetim paneli
Settings saved.
perfmatters
⚙ GeneralVersion 2.6.8
Core
Disable Emojis?
Disable Dashicons?
Disable Embeds?
Disable XML-RPC?
Remove RSD Link?
Remove jQuery Migrate?
Hide WP Version?
Remove Shortlink?
Disable RSS Feeds?
Remove RSS Feed Links?
Disable Self Pingbacks?
Disable REST API?
Remove REST API Links?
Disable Google Maps?
Disable Password Meter?
Disable Comments?
Remove Comment URLs?
Add Blank Favicon?
Remove Global Styles?
Block Style Behavior?
Disable Heartbeat?
Heartbeat Frequency?
Limit Post Revisions?
Autosave Interval?
Login URL
Custom Login URL?
Disabled Behavior?
Message?
📍 Hide My WP › Settings › Cleanup › Disable XML RPC
İşaretleyip [Save Settings]'e basınca aşağıdaki ziyaretçi ekranı değişir.
Yönetim paneli
Hide My WP
Settings was updated successfully!
Cleanup
Minify HTML
Remove comments and whitespaces from HTML (Use with cache).
Minify style
Remove theme info and other comments from stylesheet. (Require new style name)(Use with cache!).
Replace \/ URLs
Choose if you see Javascript URLs (e.g. \/wp-content\/themes)
Feed Meta
Other Meta
Default Tagline
Remove Version
Body Classes
Menu Classes
Post Classes
Clean up other
Replace in AJAX
Change Nonce
Disable XML RPC
Internal CSS
Useful to paste internal CSS code (Require New Theme Path)
Internal JS
Useful to paste internal JS code (Require New Theme Path)
Oturumu kapalı ziyaretçi ekranı — kaydedilen ayarlarla istek
405
XML-RPC server accepts POST requests only.
GET istekleri her ayarda 405 alır.
200
Hello!
Çalışmayı kontrol eden bir test çağrısı olduğu için giriş olmadan yanıt verir.
200
faultCode 403 · Incorrect username or password.
Şifre karşılaştırması yapılır. Giriş adresini değiştirseniz de aynıdır.
403
Gövde yok
Perfmatters isteği init aşamasında 403 ile bitirir. PHP çalışır.
403
Gövde yok
Perfmatters isteği init aşamasında 403 ile bitirir. PHP çalışır.
403
Gövde yok
Şifre karşılaştırması olmadan 403 ile biter. PHP çalışır.
200
Hello!
Filtre yöntemi olduğundan giriş gerektirmeyen çağrılar yanıt vermeye devam eder.
405
faultCode 405 · XML-RPC services are disabled on this site.
Yalnızca giriş gerektiren çağrılar reddedilir.

3. Web sunucusunda engelleme: Nginx · Apache

Nginx de Apache de isteği PHP'den önce reddettiği için eklenti yöntemlerinin aksine WordPress hiç çalışmaz.

# Nginx — server bloğu içinde, PHP işleyen location bloğunun üstüne
location = /xmlrpc.php {
    deny all;
}

Bu location bloğu PHP işleyen location bloğunun üstüne konur ve Nginx [xmlrpc.php] ile tam eşleşen istekleri hemen reddeder. Ekledikten sonra ayarın uygulanması için yapılandırmayı test edip yeniden yüklemeniz gerekir.

nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
systemctl reload nginx

Yeniden yüklemeden sonra GET ve POST PHP'ye ulaşmadan 403 ile biter; yanıt gövdesi Nginx'in 153 baytlık varsayılan 403 sayfasıdır ve yanıt 0,02 saniye sürer.

# Apache — sitenin kök dizinindeki .htaccess (Apache 2.4)
<Files xmlrpc.php>
    Require all denied
</Files>

Yalnızca Apache kullanan sunucuda yukarıdaki Files yönergesini sitenin kök dizinindeki .htaccess dosyasına eklemeniz hemen etkili olur; Apache'nin varsayılan 403 sayfası (199 bayt) aynı 0,02 saniyede döner.

curl -s -o /dev/null -w '%{http_code}' -X POST https://example.com/xmlrpc.php -d '<methodCall><methodName>demo.sayHello</methodName></methodCall>'
403

Yukarıdaki komut test çağrısı demo.sayHello'yu POST ile gönderip yanıt kodunu kontrol eder; web sunucusunda engelledikten sonra 403 döner. [-o /dev/null] ve [-w] seçeneklerini çıkarıp gönderirseniz gövdeyi görürsünüz: [Hello!] gelirse açıktır. Yalnızca filtreyle kapatılan sitede de aynı yanıt geldiği için 405'i görmek için giriş çağrısı da göndermeniz gerekir.

5️⃣ Kapatılmaması gereken durumlar ve alternatifler

Web sunucusunda tamamen engellemek en büyük etkiyi sağlar, ancak Jetpack ile WordPress.com'a bağlı sitelere uymaz. Jetpack XML-RPC bağlantısına dayanır; WP Engine gibi XML-RPC'yi varsayılan olarak engelleyen hostinglerde bağlantının kurulması için Jetpack'in yönergelerine göre bir istisna açmanız gerekir. Pingback almak isteyen siteler için de durum aynıdır.

Bu tür siteler yalnızca Jetpack'in yayımladığı IP listesine (jetpack.com/ips-v4.txt) izin verip geri kalanını reddederek erişimi daraltır. Nginx'in location bloğuna her IP aralığı için bir allow satırı ekleyip sona deny all koymanız yeterlidir.

Tamamen engelleyemiyorsanız oturum açmamış isteklere dakika başına bir sınır koymak kalır. Ayar, wp-admin güvenliği yazısındaki Nginx hız sınırlama bölümüyle aynıdır; yalnızca giriş çerezi olmayan istekleri saydığı için oturum açmış yönetici işlerini etkilemez.

🔢 SSS & önerilen içerikler

Silseniz bile WordPress çekirdeğini güncellediğinizde paketteki dosya olduğu gibi yeniden kopyalanır, yani bir sonraki güncellemede geri gelir. Dosyayı silmek yerine o adresi web sunucusunda engellemek ya da filtreyle devre dışı bırakmak güncellemelerden sonra da kalıcıdır.

REST API, [wp-json] adresinden gelen ayrı bir kapıdır; bu yüzden XML-RPC'yi devre dışı bıraksanız da açık kalır. Blok düzenleyici bu kapıyı kullandığı için tamamen kapatmak yerine yalnızca oturumu kapalı istekleri engellemek doğrudur.

Kontrol etmeden gönderirler. WordPress'te bu dosya her sitede aynı yoldadır; bu yüzden tarayıcılar yalnızca alan adını değiştirerek POST gönderir. Varsayılan hâliyle WordPress, sayfa head bölümündeki [EditURI] bağlantısı ve pingback alan yazılardaki [X-Pingback] başlığıyla xmlrpc.php adresini kendisi açığa çıkarır.

🛡️ WordPress güvenliği önerilen içerikler 8 yazı · 2 dış kaynak
🗂️ WordPress güvenliği
📋 wp-admin güvenliği 📄 Kaba kuvvete karşı 9 yol 📄 Hide My WP 📄 En iyi 5 güvenlik eklentisi
📄 XML-RPC'yi devre dışı bırakma 📄 REST API 📄 Pingback · trackback 📄 wp-config.php güvenliği
📡 Nanaco Japan: xmlrpc.php saldırılarına karşı önlem 📡 サイトの主治医: xmlrpc.php'yi devre dışı bırakma ve kontrol
Arama sonucu yok.

ℹ️ Satış ortaklığı bildirimi
Bu sitenin içeriklerinde satış ortaklığı bağlantıları bulunur. Bir ziyaretçi bu bağlantılar üzerinden ürün veya hizmet satın alırsa bu site satıcıdan komisyon alır. Bu süreçte alıcının ödediği tutar (kampanya indirimlerinde tutar düşer↓) artmaz. Yayımlanan fiyat, indirim ve stok bilgileri yazının yazıldığı zamana aittir ve gerçek durumdan farklı olabilir; bu yüzden satın almadan önce son bilgiyi satıcıdan kontrol etmenizi rica ederiz. Ürünler kendi ölçütlerimize göre seçilir ve değerlendirilir; komisyon alınıp alınmaması tanıtım sırasını veya değerlendirme içeriğini etkilemez.