WordPress’te XML-RPC’yi Devre Dışı Bırakma
WordPress sitenize baktığınızda, arka planda sessizce çalışan ve sitenizi ciddi risklere açık bırakabilecek bir özellik var: XML-RPC. Pek çok site sahibi bu özelliğin ne olduğunu bilmeden yıllarca sitesini açık tutuyor. Bu yazıda XML-RPC’nin ne olduğunu, neden devre dışı bırakmanız gerektiğini ve bunu yapmanın birden fazla yolunu ele alacağız.
XML-RPC Nedir ve Neden Tehlikelidir?
XML-RPC, WordPress’in uzak uygulamalarla HTTP üzerinden iletişim kurmasını sağlayan bir protokoldür. Yani teorik olarak telefonunuzdan, masaüstü uygulamanızdan ya da başka bir servisten WordPress sitenizi yönetmenize imkan tanır. WordPress 3.5 sürümünden itibaren varsayılan olarak aktif gelir.
Peki sorun ne?
- Brute force saldırılarına kapı açar: Bir saldırgan tek bir XML-RPC isteğiyle
system.multicallmetodunu kullanarak yüzlerce kullanıcı adı/şifre kombinasyonunu deneyebilir. Normal giriş sayfasındaki gibi bir deneme sınırı yoktur. - DDoS amplifikasyonu: XML-RPC üzerinden pingback özelliği, sitenizi başka sitelere yönelik DDoS saldırılarında bir araç haline getirebilir.
- Kimlik doğrulama bypass riskleri: Tarihsel olarak XML-RPC üzerinden birçok güvenlik açığı keşfedilmiştir.
- Gereksiz saldırı yüzeyi: Eğer Jetpack, Windows Live Writer ya da XML-RPC gerektiren harici bir uygulama kullanmıyorsanız, bu özelliği açık tutmanın hiçbir mantıklı gerekçesi yoktur.
Sunucu loglarınıza bakın, büyük ihtimalle şöyle satırlar göreceksiniz:
grep "xmlrpc.php" /var/log/nginx/access.log | tail -20
Bu komutun çıktısında onlarca, belki yüzlerce farklı IP’den /xmlrpc.php dosyasına yapılan POST isteklerini görmeniz çok muhtemeldir. İşte bu, gerçek dünyadaki saldırı trafiğidir.
Yöntem 1: functions.php ile XML-RPC’yi Devre Dışı Bırakma
En temiz ve tema/plugin bağımsız yol, WordPress’in kendi filtre sistemini kullanmaktır. Bu kodu temanızın functions.php dosyasına ekleyebilirsiniz. Ancak daha sağlıklı bir yaklaşım, bir child theme ya da site genelinde çalışan bir mu-plugin (must-use plugin) kullanmaktır.
Temel XML-RPC Devre Dışı Bırakma
<?php
// XML-RPC'yi tamamen devre dışı bırak
add_filter('xmlrpc_enabled', '__return_false');
Bu tek satır, WordPress’in XML-RPC isteklerine yanıt vermesini engeller. Ancak dikkat edin: xmlrpc.php dosyası hala fiziksel olarak sunucuda durur ve istekler dosyaya ulaşır, sadece WordPress tarafında işlenmez. Daha güçlü bir koruma için sunucu seviyesinde de engelleme yapmanız gerekir.
XML-RPC Metodlarını Filtreleme
Eğer XML-RPC’yi tamamen kapatmak istemiyorsanız (örneğin Jetpack kullanıyorsanız) ama pingback saldırılarını engellemek istiyorsanız, şu yöntemi kullanabilirsiniz:
<?php
// Sadece pingback metodunu devre dışı bırak
add_filter('xmlrpc_methods', function($methods) {
// Pingback metodlarını kaldır
unset($methods['pingback.ping']);
unset($methods['pingback.extensions.getPingbacks']);
return $methods;
});
Bu yaklaşım daha ince ayarlıdır. Jetpack’in çalışmasına izin verirken zararlı pingback isteklerini engeller.
Kapsamlı functions.php Çözümü
Aşağıdaki kod bloğu, XML-RPC’ye karşı çok katmanlı bir koruma sağlar:
<?php
/**
* XML-RPC Güvenlik Katmanı
* Tüm XML-RPC trafiğini engeller ve loglama yapar
*/
// 1. WordPress filtreleri üzerinden XML-RPC'yi kapat
add_filter('xmlrpc_enabled', '__return_false');
// 2. XML-RPC metodlarını temizle
add_filter('xmlrpc_methods', function($methods) {
return [];
});
// 3. WordPress başlamadan önce XML-RPC isteğini yakala
add_action('init', function() {
if (defined('XMLRPC_REQUEST') && XMLRPC_REQUEST) {
// İsteği loglayabiliriz (opsiyonel)
$ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
error_log("XML-RPC erişim girişimi engellendi. IP: {$ip}");
// 403 döndür ve çık
wp_die(
'XML-RPC servisi devre dışı bırakılmıştır.',
'Erişim Engellendi',
['response' => 403]
);
}
});
// 4. HTTP header'larından X-Pingback'i kaldır
add_filter('wp_headers', function($headers) {
unset($headers['X-Pingback']);
return $headers;
});
// 5. HTML head'den RSD linkini kaldır
remove_action('wp_head', 'rsd_link');
Bu kodda her adımın ne yaptığını açıklayayım:
- Filtre 1: WordPress’in XML-RPC’yi aktif olarak işlemesini engeller
- Filtre 2: Tüm kayıtlı XML-RPC metodlarını boşaltır
- Action init: XMLRPC_REQUEST sabiti tanımlıysa isteği loglar ve 403 döner
- Filtre 4: HTTP response header’larından
X-Pingbacksatırını kaldırır, böylece sitenizin XML-RPC endpoint’ini reklam etmesi önlenir - remove_action 5: HTML kaynak kodundan otomatik keşif linkini temizler
Yöntem 2: Nginx Seviyesinde Engelleme
Sunucuya erişiminiz varsa (ki sysadmin olarak genellikle vardır), en performanslı çözüm sunucu yapılandırmasında engelleme yapmaktır. Bu sayede istek WordPress’e hiç ulaşmaz, PHP bile çalışmaz.
# /etc/nginx/sites-available/siteniz.conf dosyasına ekleyin
# server bloğunun içine
location = /xmlrpc.php {
deny all;
access_log off;
log_not_found off;
return 444;
}
444 kodu Nginx’e özgüdür ve bağlantıyı hiçbir yanıt göndermeden kapatır. Botlar için tam anlamıyla bir “kara delik” etkisi yaratır. access_log off ve log_not_found off direktifleri de log dosyalarınızın gereksiz XML-RPC istekleriyle dolmasını önler.
Değişiklikten sonra:
nginx -t && systemctl reload nginx
Yöntem 3: Apache .htaccess ile Engelleme
Apache kullanan bir ortamdaysanız .htaccess üzerinden de engelleme yapabilirsiniz:
# WordPress kök dizinindeki .htaccess dosyasına ekleyin
# # BEGIN WordPress bloğunun ÜSTÜNE ekleyin
<Files xmlrpc.php>
Order Deny,Allow
Deny from all
ErrorDocument 403 "XML-RPC Disabled"
</Files>
Veya daha modern Apache sözdizimi ile:
<Files xmlrpc.php>
Require all denied
</Files>
Yöntem 4: Must-Use Plugin Olarak Ekleme
functions.php dosyasını düzenleme yerine bir mu-plugin oluşturmak daha güvenli bir yaklaşımdır. Çünkü tema değişse bile mu-plugin’ler çalışmaya devam eder:
# Dosyayı oluşturun
touch /var/www/html/wp-content/mu-plugins/disable-xmlrpc.php
Dosyanın içeriği:
<?php
/**
* Plugin Name: Disable XML-RPC
* Description: XML-RPC'yi güvenlik gerekçesiyle devre dışı bırakır
* Version: 1.0
* Author: SysAdmin
*/
// Yetkisiz erişim kontrolü
if (!defined('ABSPATH')) {
exit;
}
// XML-RPC'yi devre dışı bırak
add_filter('xmlrpc_enabled', '__return_false');
// Tüm metodları temizle
add_filter('xmlrpc_methods', '__return_empty_array');
// X-Pingback header'ını kaldır
add_filter('wp_headers', function(array $headers): array {
unset($headers['X-Pingback']);
return $headers;
});
// RSD link'ini head'den kaldır
add_action('init', function(): void {
remove_action('wp_head', 'rsd_link');
remove_action('wp_head', 'wlwmanifest_link');
});
// Doğrudan XML-RPC isteği gelirse engelle
add_action('xmlrpc_call', function(string $method): void {
$ip = sanitize_text_field($_SERVER['REMOTE_ADDR'] ?? 'bilinmiyor');
error_log(sprintf(
'[XML-RPC Engellendi] Metod: %s | IP: %s | Zaman: %s',
$method,
$ip,
current_time('mysql')
));
wp_die('Bu servis devre dışı bırakılmıştır.', 403);
});
Bu dosyayı oluşturduktan sonra WordPress yönetim panelinde Eklentiler menüsünde göremezsiniz ama arka planda çalışır. Bu mu-plugin’lerin özelliğidir.
Engellemenin Çalıştığını Test Etme
Herhangi bir yöntemi uyguladıktan sonra gerçekten çalışıp çalışmadığını test etmelisiniz. Komut satırından basit bir test:
# cURL ile XML-RPC endpoint'ini test et
curl -v -X POST https://siteniz.com/xmlrpc.php
-H "Content-Type: text/xml"
-d '<?xml version="1.0"?><methodCall><methodName>system.listMethods</methodName><params></params></methodCall>'
Eğer engelleme çalışıyorsa şu sonuçlardan birini görmelisiniz:
- 403 Forbidden (WordPress veya Apache/Nginx seviyesinde engellendi)
- Connection refused veya boş yanıt (Nginx 444 ile engellendi)
- WordPress’in kendi hata mesajı (filters çalıştı)
Başarılı bir engelleme çıktısı şöyle görünür:
* Connected to siteniz.com (1.2.3.4) port 443 (#0)
< HTTP/2 403
< content-type: text/html
<
Access Denied
Eğer hala XML-RPC metodlarının listesini içeren bir XML yanıtı alıyorsanız, engelleme çalışmıyor demektir.
Gerçek Dünya Senaryosu: Sunucu Altında Kalma Vakası
Bir müşterimin sitesinde yaşananları anlatayım. Küçük bir e-ticaret sitesi, günde birkaç yüz ziyaretçisi olan orta ölçekli bir WooCommerce kurulumu. Bir gün site yavaşlamaya başladı, birkaç saat sonra tamamen erişilemez hale geldi.
Sunucuya bağlandım ve ilk kontrol:
tail -f /var/log/nginx/access.log | grep xmlrpc
Saniyede düzinelerce istek geliyordu. Hepsi farklı IP’lerden, hepsi /xmlrpc.php hedefli. Klasik bir brute force dağıtık saldırısıydı. Botnet, system.multicall metodunu kullanarak her istekte yüzlerce şifre kombinasyonu deniyordu.
İlk müdahale:
# Nginx konfigürasyonuna anında ekleme
echo 'location = /xmlrpc.php { deny all; return 444; }' >> /etc/nginx/conf.d/block-xmlrpc.conf
nginx -t && systemctl reload nginx
Trafik anında düştü. Sonra WordPress seviyesinde de filtreleri ekledik ve kalıcı çözümü oturtttuk. O günden bu yana o sitede XML-RPC kaynaklı tek bir incident yaşanmadı.
Jetpack Kullananlar İçin Özel Durum
Jetpack, bazı özellikler için XML-RPC kullanır. Eğer Jetpack aktifse şu yaklaşımı benimseyin:
<?php
// Jetpack'i koruyarak diğer XML-RPC trafiğini engelle
add_filter('xmlrpc_methods', function(array $methods): array {
// Jetpack'in ihtiyaç duyduğu metodları tut
$allowed_methods = [
'jetpack.remoteRegister',
'jetpack.remoteProvision',
'jetpack.jsonAPI',
];
// Pingback ve diğer tehlikeli metodları kaldır
$methods_to_remove = [
'pingback.ping',
'pingback.extensions.getPingbacks',
'demo.addTwoNumbers',
'demo.sayHello',
];
foreach ($methods_to_remove as $method) {
unset($methods[$method]);
}
return $methods;
});
Ancak dürüst olmak gerekirse, Jetpack’in yeni versiyonları artık XML-RPC yerine REST API kullanıyor. Jetpack bağlantı durumunuzu kontrol edin ve mümkünse tamamen kapatın.
Ekstra Güvenlik: Fail2ban ile Otomatik IP Engelleme
XML-RPC’yi kapatsanız bile kalan log gürültüsünü temizlemek için Fail2ban kullanabilirsiniz:
# /etc/fail2ban/filter.d/wordpress-xmlrpc.conf
[Definition]
failregex = ^<HOST> .* "POST /xmlrpc.php
ignoreregex =
# /etc/fail2ban/jail.local
[wordpress-xmlrpc]
enabled = true
filter = wordpress-xmlrpc
logpath = /var/log/nginx/access.log
maxretry = 3
bantime = 86400
findtime = 600
systemctl restart fail2ban
fail2ban-client status wordpress-xmlrpc
Bu yapılandırmayla 10 dakika içinde 3 kez /xmlrpc.php‘e istek atan IP’ler 24 saat boyunca tamamen engellenir.
Yapılandırmayı Doğrulamak İçin Kontrol Listesi
Uyguladığınız çözümü doğrulamak için şu kontrolleri yapın:
- cURL testi: Yukarıda gösterilen cURL komutuyla 403 veya bağlantı reddi alıyorsunuz
- Log kontrolü: Nginx/Apache loglarında XML-RPC isteklerinin azaldığını görüyorsunuz
- Header kontrolü:
curl -I https://siteniz.comçıktısındaX-Pingbacksatırı yok - Kaynak kodu: Sitenizin HTML kaynağında
<link rel="EditURI"ve<link rel="wlwmanifest"satırları yok - Pingback ayarı: WordPress Ayarlar > Tartışma sayfasında pingback’ler devre dışı
# Header kontrolü için
curl -sI https://siteniz.com | grep -i pingback
# Çıktı boş olmalı
Sonuç
XML-RPC, WordPress’in eski bir özelliği olup modern kullanım senaryolarında neredeyse hiç gereksinim duyulmaz. Buna karşın saldırganlar için popüler bir giriş noktası olmaya devam etmektedir. functions.php filtreleri, sunucu seviyesinde engelleme ve opsiyonel olarak Fail2ban kombinasyonu, sitenizi bu saldırılara karşı katmanlı biçimde korur.
Önerim her zaman şu sırayla ilerlemektir: Önce Nginx veya Apache seviyesinde engelle, ardından WordPress filtreleriyle arka planda savun. Bu çift katmanlı yaklaşım, hem performans hem de güvenlik açısından en optimum sonucu verir.
Eğer yönettiğiniz birden fazla WordPress sitesi varsa, bu yapılandırmaları bir Ansible playbook veya özel bir mu-plugin paketi haline getirip tüm sitelere otomatik dağıtmayı düşünebilirsiniz. Bir kez kurulumu doğru yapın, binlerce sitede tutarlı güvenlik sağlayın.
