So sperrst du Brute-Force-Angriffe über xmlrpc.php in WordPress
Zuletzt aktualisiert:
xmlrpc.php ist die alte Fernschnittstelle von WordPress. Kaum eine Website braucht sie noch, und jede WordPress-Website im Internet wird über sie angegriffen. Ihre Methode system.multicall führt viele Aufrufe in einer einzigen Anfrage aus, sodass ein einziger POST Hunderte Passwörter durchprobieren kann. Deshalb sehen Login-Begrenzer, die Anfragen an wp-login.php zählen, den Angriff nicht. Die Methode pingback.ping wird benutzt, um deine Website Anfragen an fremde Websites schicken zu lassen.
Hier erfährst du, wie du den Angriff in den Access-Logs erkennst, wie du xmlrpc.php in nginx, Apache oder in WordPress selbst sperrst, was du tust, wenn du Jetpack nutzt, und wie du die Datei mit einem Ratenlimit oder fail2ban schützt, wenn sie offen bleiben muss. Die Befehle gelten für Debian und Ubuntu sowie für die RHEL-Familie; example.com steht für deine Website.
Einen XML-RPC-Angriff in den Access-Logs erkennen
Zähl die POST-Anfragen an xmlrpc.php pro Adresse. Eine normale Website sieht ein paar am Tag, von Jetpack oder einer App. Hunderte von einer Adresse oder ein steter Strom von vielen ist ein Angriff.
sudo sh -c "grep -hI 'POST /xmlrpc.php' /var/log/nginx/*access*.log /var/log/apache2/*access*.log \
/var/log/httpd/*access_log /usr/local/apache/domlogs/* /var/log/apache2/domlogs/* 2>/dev/null" \
| awk '{print $1}' | sort | uniq -c | sort -rn | head -20Der Befehl liest die üblichen Orte: nginx, Apache unter Debian und Ubuntu, httpd in der RHEL-Familie und die Logs pro Domain von cPanel. Die Anfragen pro Stunde zeigen, wann es angefangen hat:
sudo sh -c "grep -hI 'POST /xmlrpc.php' /var/log/nginx/access.log /var/log/apache2/access.log /var/log/httpd/access_log 2>/dev/null" \
| awk '{print substr($4, 2, 14)}' | uniq -c | tail -n 24- Der Status ist auch bei einem falschen Passwort
200: XML-RPC meldet den Fehler in der Antwort. Lies200nicht als erfolgreiche Anmeldung. - Große Antworten, die sich von einer Adresse alle paar Sekunden wiederholen, sind typischerweise
system.multicall: eine Antwort für viele Passwortversuche. - Das Log zeigt nicht, welche Methode aufgerufen wurde: Der Body der Anfrage wird nicht protokolliert. Brute Force und Pingback-Missbrauch sehen hier gleich aus.
Ob XML-RPC auf einer Website antwortet, findest du von jedem Rechner aus heraus, indem du nach der Liste der Methoden fragst. Eine Liste von Methoden heißt, es ist an; ein 403 heißt, es ist gesperrt.
curl -s -X POST -H 'Content-Type: text/xml' \
-d '<?xml version="1.0"?><methodCall><methodName>system.listMethods</methodName></methodCall>' \
https://example.com/xmlrpc.php | head -c 400; echoxmlrpc.php in nginx oder Apache sperren
Die Sperre im Webserver ist die günstigste Variante: Die Anfrage wird abgewiesen, bevor PHP und WordPress geladen werden. In nginx fügst du das in den server-Block jeder WordPress-Website ein:
# In the site's server { } block, before the "location ~ \.php$" block
location = /xmlrpc.php {
deny all;
}sudo nginx -t && sudo systemctl reload nginxIn Apache 2.4 kommt das in die .htaccess der Website (kein Reload nötig; LiteSpeed liest sie auch) oder in ihren <VirtualHost>:
# In the site's .htaccess or <VirtualHost>
<Files "xmlrpc.php">
Require all denied
</Files>sudo apachectl configtest && sudo systemctl reload apache2sudo apachectl configtest && sudo systemctl reload httpdAchtung: Die Sperre von xmlrpc.php legt lahm, was die Datei noch nutzt: Jetpack (siehe unten), Pingbacks und einige ältere Apps und Publishing-Tools. Wenn du unsicher bist, such zuerst in den Logs aus Schritt 1 nach legitimen Aufrufern.
XML-RPC in WordPress selbst abschalten
Wo du die Webserver-Konfiguration nicht ändern kannst, erledigt das ein Must-use-Plugin aus WordPress heraus. Must-use-Plugins werden bei jeder Anfrage geladen und lassen sich im Admin-Bereich nicht versehentlich deaktivieren. Ersetze den Pfad durch den deiner Website:
sudo mkdir -p /var/www/example.com/wp-content/mu-plugins
sudo tee /var/www/example.com/wp-content/mu-plugins/disable-xmlrpc.php > /dev/null <<'EOF'
<?php
// Turns off the XML-RPC methods that need a login, and pingbacks.
add_filter( 'xmlrpc_enabled', '__return_false' );
add_filter( 'xmlrpc_methods', function ( $methods ) {
unset( $methods['pingback.ping'], $methods['pingback.extensions.getPingbacks'] );
return $methods;
} );
EOFHinweis: Der Filter xmlrpc_enabled schaltet nur die Methoden ab, die eine Anmeldung brauchen, wie die WordPress-Referenz sagt; der zweite Filter entfernt die Pingback-Methoden. PHP läuft trotzdem bei jeder Anfrage, deshalb ist die Webserver-Sperre oben bei einem schweren Angriff leichter.
Plugins tun dasselbe: eigene „Disable XML-RPC“-Plugins, und Sicherheits-Plugins wie Wordfence und Solid Security haben eine Option dafür (Stand November 2026). Ein Plugin ist bei einem Update leicht versehentlich abgeschaltet; das Must-use-Plugin und die Webserver-Regel nicht.
Jetpack am Laufen halten
Jetpack spricht über xmlrpc.php mit deiner Website, eine Sperre für alle trennt also die Jetpack-Verbindung. Jetpack veröffentlicht die Adressbereiche seiner Server auf seiner Allowlist-Seite: Lass diese zu und sperr alle anderen. In nginx muss die Location die Anfrage dann auch an PHP weitergeben:
location = /xmlrpc.php {
# Jetpack's ranges, from its allowlist page (check it for changes)
allow 122.248.245.244/32;
allow 54.217.201.243/32;
allow 54.232.116.4/32;
allow 192.0.64.0/18;
allow 195.234.108.0/22;
deny all;
# then the same lines as in your "location ~ \.php$" block, for example:
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/run/php/php-fpm.sock;
}Kopier die PHP-Zeilen aus dem eigenen location ~ \.php$-Block der Website: Der Socket-Pfad unterscheidet sich je nach System. In Apache lässt Require ip allein nur diese Bereiche zu:
<Files "xmlrpc.php">
Require ip 122.248.245.244/32 54.217.201.243/32 54.232.116.4/32 192.0.64.0/18 195.234.108.0/22
</Files>Hinweis: Bereiche so, wie Jetpack sie im November 2026 auflistet. Sie können sich ändern: Schau ab und zu auf die Seite. Hinter Cloudflare oder einem anderen Proxy sehen diese Regeln die Adresse des Proxys, solange die echte Besucheradresse nicht zuerst wiederhergestellt wird (nginx real_ip, Apache mod_remoteip).
xmlrpc.php begrenzen, wenn es offen bleiben muss
Braucht eine App oder ein Dienst XML-RPC, dessen Adressen du nicht auflisten kannst, begrenz, wie oft jede Adresse die Datei aufrufen darf. In nginx definierst du eine Zone im http-Kontext und nutzt sie für xmlrpc.php: hier 6 Anfragen pro Minute und Adresse, mit einem Burst von 5, und darüber 429.
# /etc/nginx/conf.d/xmlrpc-limit.conf (read inside the http { } block)
limit_req_zone $binary_remote_addr zone=xmlrpc:10m rate=6r/m;# In the site's server { } block
location = /xmlrpc.php {
limit_req zone=xmlrpc burst=5 nodelay;
limit_req_status 429;
# then the same lines as in your "location ~ \.php$" block, for example:
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/run/php/php-fpm.sock;
}sudo nginx -t && sudo systemctl reload nginxHinweis: Ein Ratenlimit zählt Anfragen, keine Passwörter: Eine einzige system.multicall-Anfrage innerhalb des Limits kann immer noch Hunderte Versuche enthalten. Kombiniere es mit starken Passwörtern oder sperr die Adressen mit fail2ban. Apache hat nichts Vergleichbares eingebaut; nimm fail2ban unten.
XML-RPC-Angreifer mit fail2ban sperren
fail2ban liest das Access-Log und sperrt eine Adresse in der Firewall, es funktioniert also mit nginx und Apache gleichermaßen. Installier es wie in SSH-Brute-Force-Angriffe stoppen (Repositories von Debian und Ubuntu, EPEL in der RHEL-Familie). Leg dann einen Filter für POST-Anfragen an xmlrpc.php an:
sudo tee /etc/fail2ban/filter.d/wordpress-xmlrpc.conf > /dev/null <<'EOF'
[Definition]
failregex = ^<HOST> \S+ \S+ \[[^]]+\] "POST /xmlrpc\.php
ignoreregex =
EOFUnd ein Jail: 5 Anfragen in 60 Sekunden, eine Sperre von einer Stunde. Trag deine eigene Adresse in ignoreip ein und, wenn du Jetpack nutzt, dessen Bereiche. Für Apache setzt du logpath auf /var/log/apache2/*access.log unter Debian und Ubuntu oder auf /var/log/httpd/*access_log in der RHEL-Familie.
sudo tee /etc/fail2ban/jail.d/wordpress-xmlrpc.local > /dev/null <<'EOF'
[wordpress-xmlrpc]
enabled = true
port = http,https
filter = wordpress-xmlrpc
logpath = /var/log/nginx/access.log
maxretry = 5
findtime = 60
bantime = 3600
ignoreip = 127.0.0.1/8 ::1 192.0.2.10
EOFTeste den Filter am echten Log, bevor du ihn aktivierst: fail2ban-regex zeigt, wie viele Zeilen passen. Starte dann fail2ban neu und prüf das Jail.
sudo fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/wordpress-xmlrpc.conf
sudo systemctl restart fail2ban
sudo fail2ban-client status wordpress-xmlrpcAchtung: Hinter Cloudflare oder einem anderen Proxy zeigt das Access-Log die Adresse des Proxys: fail2ban würde den Proxy sperren und die Website für viele Besucher offline nehmen. Stell zuerst die echte Adresse im Log wieder her oder sperr am Proxy.
Wie InfraFence mit XML-RPC-Angriffen umgeht
Die Web-Firewall von InfraFence liest die Access-Logs von nginx, Apache und LiteSpeed, ab Agent 1.0.42 auch die von Traefik, Caddy, HAProxy und Webservern in Containern. Hinter Cloudflare nimmt sie die Besucheradresse aus CF-Connecting-IP, und das nur aus den Adressbereichen von Cloudflare.
- Je 5 POST-Anfragen an
xmlrpc.phpvon einer Adresse auf einer Website innerhalb einer Minute bringen dem Wert dieser Adresse 25 Punkte. Ein anhaltender Angriff bringt sie immer wieder. - Der Wert sammelt auch die anderen Angriffe der Adresse, etwa Brute Force auf
wp-login.php, Plugin-Scans oder Exploit-Versuche, und sinkt um 5 Punkte pro Minute, sodass eine einzelne seltsame Anfrage verblasst. - Bei 80 Punkten wird die Adresse in der Firewall gesperrt und das Ereignis als kritisch gemeldet. Schwellen und Punkte lassen sich pro Server ändern, und der Überwachungsmodus meldet, ohne zu sperren.
Siehe Web-Firewall für die Regeln und den Wert. Was sie nicht tut: Sie zählt Anfragen und sieht daher nicht, wie viele Passwörter eine system.multicall-Anfrage enthält; sie ändert deine Konfiguration von nginx, Apache oder WordPress nicht, xmlrpc.php bleibt also offen, bis du es wie oben sperrst; und sie hat keine eingebaute Ausnahme für Jetpack: Wenn die Server von Jetpack so oft aufrufen, dass sie Punkte sammeln, setz ihre Bereiche auf die Whitelist. Die Sperre entsteht aus dem Log, die auslösende Anfrage wurde also bereits beantwortet.
Fragen
- Kann ich xmlrpc.php gefahrlos abschalten?
- Für die meisten Websites ja: Der Block-Editor und der Admin-Bereich nutzen die REST-API, nicht XML-RPC. Prüf vorher, ob du Jetpack, Pingbacks, eine App oder ein Publishing-Tool nutzt, das noch darauf angewiesen ist.
- Warum zeigen die Angriffe Status 200?
- XML-RPC antwortet mit
200und meldet die fehlgeschlagene Anmeldung in der Antwort. Der Statuscode sagt nichts darüber, ob ein Passwort funktioniert hat. - Mein Login-Begrenzer-Plugin stoppt das nicht. Warum?
- Viele Begrenzer zählen Versuche an
wp-login.php. Einesystem.multicall-Anfrage überxmlrpc.phpenthält Hunderte Versuche in einer Anfrage und geht an ihnen vorbei. Sperr oder begrenzxmlrpc.phpselbst.
Kostenlos auf 1 Server testen
Starter ist für einen Server kostenlos, mit vollem Schutz und automatischen Sperren. Ohne Kreditkarte.
Installiere den Agenten als root, mit deinem Token anstelle von <TOKEN>:
curl -fsSL https://github.com/infrafence/infrafence-agent/releases/latest/download/install.sh | sudo bash -s -- --token <TOKEN>Das Token erstellst du im Dashboard unter Server › Server hinzufügen.
