WordPress XML-RPC: 3 Wege zum Deaktivieren & xmlrpc.php-Angriffe erkennen | Jetpack-Ausnahme

Affiliate-Hinweis v3.1
Affiliate-Hinweis v3.2 (mobil)

Zeigt das Zugriffslog deiner WordPress-Website Hunderte xmlrpc.php-Anfragen hintereinander von derselben IP, ist das ein Passwortangriff auf WordPress XML-RPC. Ich habe die 8.624 Log-Einträge eines Tages auf einem Nginx + Apache-Server mit mehreren WordPress-Websites ausgewertet, die drei Wege zum Deaktivieren selbst angewendet und die Antwortcodes geprüft – um zu klären, auf welcher Ebene man sperren muss, damit auch die PHP-Ausführung wegfällt.

XML-RPC ist ein Protokoll, das XML-Dokumente über HTTP austauscht, um WordPress-Funktionen aus der Ferne aufzurufen. Seit WordPress 3.5 gibt es dafür keinen Schalter mehr in den Einstellungen, es läuft also ab der Installation eingeschaltet.

1️⃣ Was xmlrpc.php macht und wer es nutzt

Seit es die REST API gibt, hält man [xmlrpc.php] leicht für eine Datei, die niemand mehr nutzt – doch Jetpack verbindet deine Website bis heute über diese Datei mit WordPress.com. Die offizielle Jetpack-Dokumentation nennt die XML-RPC-Verbindung ausdrücklich als Voraussetzung, und bei Hostern, die XML-RPC standardmäßig sperren, scheitert schon die Jetpack-Verbindung. Das ist wie das eine Faxgerät, das im Büro immer noch steht.

Stand WordPress 7.1 nimmt diese Datei 77 Methoden an: 50 aus der wp-Familie für Beiträge, Medien und Kommentare, 23 aus den alten Blog-Protokollen (MetaWeblog, MovableType, Blogger), 2 für Pingbacks und 2 demo-Methoden zum Testen.

Die wp-Familie meldet sich mit Benutzername und Passwort aus dem Anfragetext an und kommt deshalb nie an der Login-Seite vorbei. Beiträge schreiben und bearbeiten, Medien hochladen, Kommentare verwalten – all das gehört zu dieser Familie; die 23 Methoden der alten Blog-Protokolle sind geblieben, damit andere Blog-Tools auf dieselbe Weise Beiträge austauschen können.

demo.sayHello ist ein Testaufruf, der in WordPress XML-RPC eingebaut ist. Schickst du ihn, kommt nur ein Wort zurück, [Hello!]; da kein Login nötig ist, prüft man damit, ob XML-RPC läuft. Sein Gegenstück demo.addTwoNumbers addiert zwei Zahlen und gibt die Summe zurück.

Alle antworten nur auf einen per POST gesendeten XML-Text; öffnest du die Adresse im Browser, kommt ein 405 mit der Meldung [XML-RPC server accepts POST requests only.] zurück.

Auch Pingbacks laufen über diese Datei. Veröffentlichst du einen Beitrag, geht ein Pingback an die xmlrpc.php jeder im Text verlinkten Website, und der empfangende Server öffnet die Absenderadresse selbst, um zu prüfen, ob der Link wirklich existiert.

🧭 Anfragen an xmlrpc.php und ihre Verarbeitung
📨 Absender
↓
Eingang
xmlrpc.php
Verarbeitet nur per POST gesendeten XML-Text
405 · XML-RPC server accepts POST requests only.
77 Methoden
wp.*Beiträge · Medien · Kommentare, 50
metaWeblog · mt · bloggeralte Blog-Protokolle, 23
pingback.*Pingbacks, 2
demo.*Testaufrufe zur Funktionsprüfung, 2
Ergebnis
Hält die Verbindung zu WordPress.com
Prüft Benutzername und Passwort im Anfragetext → Beiträge schreiben und bearbeiten
Der Server öffnet die Absenderadresse selbst und prüft den Link
Ohne Login: Hello! Antwort
Keine Verarbeitung
Jetpack hält die Verbindung zu WordPress.com über diese Datei – sperrst du die Datei, bricht die Verbindung ab.
Externe Publishing-Tools melden sich mit Benutzername und Passwort im Anfragetext an, ohne die Login-Seite zu durchlaufen.
Ein Pingback geht an die xmlrpc.php der im Beitrag verlinkten Website, und der empfangende Server öffnet die Absenderadresse selbst, um den Link zu prüfen.
demo.sayHello ist ein Testaufruf, der prüft, ob XML-RPC läuft; er antwortet ohne Login mit dem einen Wort [Hello!].
Öffnest du die Adresse im Browser, kommt ein 405 mit der Meldung [XML-RPC server accepts POST requests only.] zurück.

2️⃣ xmlrpc.php-Angriffe im Zugriffslog

Passwortversuche laufen nicht über die Login-Seite, sondern über [xmlrpc.php]. Im Zugriffslog eines Nginx + Apache-Servers mit mehreren WordPress-Websites gab es am 14. Oktober zwischen 0 und 20 Uhr 8.624 POST-Anfragen an /xmlrpc.php von 72 IPs, und 19 dieser IPs schickten genau 300 Stück.

Eine IP schickte zwischen 14:09 und 14:37 Uhr in 28 Minuten 300 Anfragen, im gleichmäßigen Abstand von 5–6 Sekunden bis zum Schluss. 8.524 Anfragen trugen Jetpack oder WordPress.com im User-Agent, und dieselbe IP wechselte zwischen mehreren Werten, die das echte Jetpack-Format nachahmten, etwa [Jetpack by WordPress.com (Jetpack 13.0; WordPress 6.3)].

Bis 14 Uhr an diesem Tag schickte die XML-RPC-Aus-Einstellung des Sicherheits-Plugins diese Anfragen mit 302 zur Startseite; ab 14 Uhr, nach der Sperre in Nginx, endeten sie mit 403. Ein 302 heißt, dass PHP bei jeder Anfrage lief, auch wenn der Body 0 Byte hatte; ein 403 ist eine Antwort, die PHP nie erreicht hat.

🧭 Ein xmlrpc.php-Angriff in einer Zugriffslog-Zeile
Erklär-Diagramm
🛡️ Serverzustand
Eine Zugriffslog-Zeile (Nginx access.log)
203.0.113.25IP[14/Oct/2026:14:09:04 +0900]Zeit"POST /xmlrpc.php HTTP/1.1"Anfrage302403Status0153Bytes"Jetpack by WordPress.com (Jetpack 13.0; WordPress 6.3)"User-Agent
PHP läuft · 302 zur StartseiteOhne PHP · Nginx-Standard-403-Seite
Hat das Sicherheits-Plugin XML-RPC abgeschaltet, steht im Log ein 302, der die Anfrage zur Startseite schickt. Der Body hat 0 Byte, aber für diesen 302 läuft PHP.
Bei einer Sperre in Nginx stehen im Log 403 und die 153 Byte der Standard-Fehlerseite, PHP läuft nicht.
Anfragen derselben IP
14:09:0414:37:20
300 in 28 Minuten, alle 5–6 s
POST 8.624 von 0 bis 20 Uhr72 IPs19 IPs mit je 3008.524 mit gefälschtem Jetpack/WordPress.com-UA

3️⃣ system.multicall und Passwortversuche

Oft heißt es, mit [system.multicall] teste eine Anfrage Hunderte Passwörter – doch sobald innerhalb einer Anfrage ein Login fehlschlägt, prüft WordPress die Passwörter der übrigen Aufrufe nicht mehr. Nur der erste Aufruf durchläuft wp_authenticate, die folgenden bekommen ungeprüft denselben Fehler [Incorrect username or password.].

Da trotzdem für jeden Aufruf eine Antwort zurückkommt, bringt eine Anfrage mit 100 falschen Passwörtern 100 Fehler in einer 23 KB großen Antwort – in 0,12 Sekunden. Steht das richtige Passwort in derselben Anfrage weiter hinten, wird es wegen des vorherigen Fehlschlags mit abgelehnt; steht es vorn, gelingt nur dieser Aufruf. Das Passwort wird einmal verglichen, aber das Parsen des XML und das Laden von WordPress wiederholen sich bei jeder Anfrage – die Serverlast dieses Angriffs entsteht also durch die Zahl der Anfragen, nicht durch die Login-Prüfung.

4️⃣ 3 Wege, XML-RPC zu deaktivieren, und ihre Antwortcodes

Auch wenn ein Plugin XML-RPC abschaltet, erreichen Anfragen an [xmlrpc.php] weiterhin PHP. Mit gesetztem Filter habe ich eine Anfrage mit 100 Aufrufen geschickt – und trotzdem HTTP 200 mit 100 Fehlern (24 KB) bekommen. Je nachdem, auf welcher Ebene abgelehnt wird, gibt es drei Methoden, jede mit einem anderen Antwortcode.

1. Per Code über den Filter xmlrpc_enabled abschalten

Eine add_filter-Zeile in der functions.php des Themes, die den Filter [xmlrpc_enabled] auf false setzt, genügt. Aufrufe, die ein Login brauchen, werden dann mit dem Fehler [XML-RPC services are disabled on this site.] und HTTP 405 abgelehnt – der Testaufruf demo.sayHello, der kein Login braucht, antwortet aber weiterhin mit 200.

2. In den Plugin-Einstellungen abschalten: Perfmatters · Hide My WP

So deaktivierst du es über die Einstellung Disable XML-RPC in Plugins wie Perfmatters oder Hide My WP. Hide My WP arbeitet mit demselben Filter wie oben, die Antworten sind also gleich; Perfmatters beendet zusätzlich direkte Anfragen an [xmlrpc.php] mit 403 und entfernt Pingback-Header und Pingback-Link, sodass nach dem Abschalten GET und POST beide mit 403 antworten. Für diesen 403 läuft WordPress allerdings bis zur init-Phase, die Antwort dauert also 0,13–0,15 Sekunden – genauso lange wie im offenen Zustand – und die PHP-Last bleibt.

🔌 XML-RPC in den Plugin-Einstellungen abschalten
📍 Settings › Perfmatters › General › Core › Disable XML-RPC
Schalte den Schalter ein und klicke auf [Save Changes] – die Besucheransicht unten ändert sich.
Admin-Bereich
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
Setze das Häkchen und klicke auf [Save Settings] – die Besucheransicht unten ändert sich.
Admin-Bereich
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)
Ansicht für abgemeldete Besucher — Anfragen mit den gespeicherten Einstellungen
405
XML-RPC server accepts POST requests only.
GET-Anfragen bekommen bei jeder Einstellung einen 405.
200
Hello!
Es ist ein Testaufruf zur Funktionsprüfung und antwortet deshalb ohne Login.
200
faultCode 403 · Incorrect username or password.
Die Passwortprüfung läuft. Eine geänderte Login-URL ändert daran nichts.
403
Kein Body
Perfmatters beendet die Anfrage in der init-Phase mit 403. PHP läuft trotzdem.
403
Kein Body
Perfmatters beendet die Anfrage in der init-Phase mit 403. PHP läuft trotzdem.
403
Kein Body
Endet ohne Passwortprüfung mit 403. PHP läuft trotzdem.
200
Hello!
Es ist der Filteransatz, Aufrufe ohne Login antworten also weiterhin.
405
faultCode 405 · XML-RPC services are disabled on this site.
Nur Aufrufe, die ein Login brauchen, werden abgelehnt.

3. Auf dem Webserver sperren: Nginx · Apache

Ob Nginx oder Apache – die Anfrage wird vor PHP abgelehnt, WordPress läuft anders als bei den Plugin-Methoden gar nicht erst.

# Nginx — im server-Block, oberhalb der PHP-location
location = /xmlrpc.php {
    deny all;
}

Dieser location-Block kommt oberhalb der PHP-location, und Nginx lehnt Anfragen, die genau auf [xmlrpc.php] passen, sofort ab. Nach dem Eintragen die Konfiguration prüfen und neu laden, sonst greift sie nicht.

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

Ab dem Neuladen enden GET und POST mit 403, ohne PHP zu erreichen; der Antwort-Body ist die 153 Byte große Nginx-Standard-403-Seite, die Antwort dauert 0,02 Sekunden.

# Apache — .htaccess im Site-Root (Apache 2.4)
<Files xmlrpc.php>
    Require all denied
</Files>

Auf einem reinen Apache-Server trägst du die Files-Direktive oben in die .htaccess im Site-Root ein, und sie greift sofort; die Apache-Standard-403-Seite (199 Byte) kommt in denselben 0,02 Sekunden zurück.

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

Der Befehl oben schickt den Testaufruf demo.sayHello per POST und prüft den Antwortcode; nach der Sperre auf dem Webserver kommt 403 zurück. Lässt du die Optionen [-o /dev/null] und [-w] weg, siehst du den Body: Kommt [Hello!], ist es offen – eine nur per Filter abgeschaltete Website antwortet aber genauso, deshalb musst du auch einen Login-Aufruf schicken, um den 405 zu sehen.

5️⃣ Wann du es nicht abschalten solltest – und die Alternativen

Die komplette Sperre auf dem Webserver wirkt am stärksten, passt aber nicht zu Websites, die über Jetpack mit WordPress.com verbunden sind. Jetpack ist auf die XML-RPC-Verbindung angewiesen, und bei Hostern, die XML-RPC standardmäßig sperren – etwa WP Engine – musst du nach Jetpacks Anleitung eine Ausnahme öffnen, bevor die Verbindung steht. Dasselbe gilt für Websites, die Pingbacks empfangen wollen.

Solche Websites grenzen es ein: Nur die von Jetpack veröffentlichte IP-Liste (jetpack.com/ips-v4.txt) wird erlaubt, alles andere abgelehnt. Im location-Block von Nginx kommt je IP-Bereich eine allow-Zeile, am Ende deny all.

Lässt es sich nicht komplett sperren, bleibt ein Limit pro Minute für Anfragen ohne Login. Die Einstellung ist dieselbe wie im Abschnitt zum Nginx-Rate-Limit im Beitrag wp-admin-Sicherheit ; gezählt werden nur Anfragen ohne Login-Cookie, eingeloggte Admin-Arbeit bleibt unberührt.

🔢 FAQ & empfohlene Inhalte

Auch wenn du sie löschst, kopiert das nächste WordPress-Core-Update die Datei aus dem Paket wieder an ihren Platz – beim nächsten Update ist sie also zurück. Statt die Datei zu löschen, bleibt eine Sperre der Adresse auf dem Webserver oder das Deaktivieren per Filter auch nach Updates bestehen.

Die REST API ist ein eigener Zugang über die Adresse [wp-json] und bleibt auch bei deaktiviertem XML-RPC offen. Der Block-Editor nutzt diesen Zugang, deshalb ist es richtig, ihn nicht komplett abzuschalten, sondern nur Anfragen ohne Login zu blockieren.

Sie prüfen es nicht, sie schicken einfach. Bei jeder WordPress-Website liegt die Datei unter demselben Pfad, Scanner wechseln also nur die Adresse und senden POST-Anfragen. Ein WordPress im Standardzustand verrät die Adresse von xmlrpc.php sogar selbst – über den [EditURI]-Link im head der Seite und den [X-Pingback]-Header bei Beiträgen, die Pingbacks annehmen.

🛡️ WordPress-Sicherheit: empfohlene Inhalte 8 Beiträge · 2 externe
🗂️ WordPress-Sicherheit
📋 wp-admin-Sicherheit 📄 Brute Force: 9 Methoden 📄 Hide My WP 📄 Sicherheits-Plugins: die besten 5
📄 XML-RPC deaktivieren 📄 REST API 📄 Pingbacks · Trackbacks 📄 wp-config.php-Sicherheit
📡 Nanaco Japan: Umgang mit xmlrpc.php-Angriffen 📡 サイトの主治医: xmlrpc.php deaktivieren und prüfen
Keine Suchergebnisse.

ℹ️ Affiliate-Hinweis
Die Inhalte dieser Website enthalten Affiliate-Links. Kauft ein Besucher über einen dieser Links ein Produkt oder eine Dienstleistung, erhält die Website vom Verkäufer eine Provision. Der Betrag, den der Käufer zahlt(bei Aktionsrabatten sinkt er ↓), steigt dadurch nicht. Angegebene Preise, Rabatte und Lagerbestände entsprechen dem Stand bei Erstellung und können abweichen; prüfe sie daher vor dem Kauf beim Verkäufer. Produkte werden nach eigenen Kriterien ausgewählt und bewertet, und Provisionen beeinflussen weder die Reihenfolge noch den Inhalt der Bewertungen.