WordPress XMLRPC Angriff

Hallo,

diesmal etwas in eigener Sache. Und zwar war mein Blog in letzter Zeit öfters down und ich habe mich gefragt, was da los ist.Der Server ging irgendwann in die Knie und warf beim Laden der Seite eine 502 – Bad Gateway Fehler.

Analyse des Angriffs

Im Log des Webservers tauchen folgende Meldungen auf:


/var/log/nginx/access.log

xx.xxx.xx.xxx - - [22/Jan/2015:03:36:59 +0100] "POST /xmlrpc.php HTTP/1.0" 403 529 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"
xx.xxx.xx.xxx - - [22/Jan/2015:02:57:50 +0100] "POST /wp-login.php HTTP/1.1" 200 1326 "http://warpdrive-on.de/wp-login.php" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:19.0) Gecko/20100101 Firefox/19.0"

Nach kurzer google-Recherche stellte sich heraus, dass es in den letzten WordPress Versionen eine Sicherheitslücke gibt, und zwar die xmlrpc-Schnittstelle. Darüber können Blogeinträge über externe Programme hinzugefügt werden.

Schließen der Sicherhheitslücke

Da ich diese Möglichkeit sowieso nicht benutze, entschied ich, den Zugriff auf die Datei xmlrpc.php direkt im Webserver zu sperren.

Dies kann im nginx-Webserver in der virtual Host-Konfiguration mit folgendem Eintrag eingestellt werden:


/etc/nginx/sites-enabled/default

location /xmlrpc.php {
deny all;
}

Bot-Zugriffe mit fail2ban blockieren

Damit war das Problem erst einmal behoben. Da ich aber trotzdem noch zahlreiche Seitenaufrufe hatte (die Zahlen hatten nichts mit der Realität zu tun 🙂 ), dachte ich mir, wenn ich grad dabei bin sperre ich diese vermeindlichen Bots auch noch aus. Dazu gibt es die Möglichkeit, diese mit der Software Fail2ban zu blocken.

Als erstes legt man idealerweise im Nginx conf.d Verzeichnis eine Datei bots.map an.


/etc/nginx/conf.d/bots.map

map $http_user_agent $is_bot {
default 0;

~Sogou 1;
~Abonti 1;
~Pixray 1;
~Python 1;
~Spinn3r 1;
~libwww-perl 1;
~Wget 1;
~Curl 1;
~Ezooms 1;
~mShots 1;
~SemrushBot 1;
~Exabot 1;
~ZmEu 1;
~iCjobs 1;
~QuerySeekerSpider 1;
~Baiduspider 1;
~AhrefsBot 1;
~CareerBot 1;
~coccoc 1;
~MJ12bot 1;
~SeznamBot 1;
~spbot 1;
~ShowyouBot 1;
~adressendeutschland 1;
~PagesInventory 1;
~aboutWebSearch 1;
~Java 1;
~JCE 1;
~bitlybot 1;
~WeSEE 1;
~updown_tester 1;
~200PleaseBot 1;
~Nutch 1;
~HTTP_Request 1;
~AnyOther 1;
~Crawler 1;
~BLEXBot 1;
~yacybot 1;
~Cliqzbot 1;
}

Durch das Nginx-Module map wird entschieden, ob ein spezifizierter User-Agent als Bot definiert wird (die Variable $is_bot also als Wert 1 enthält) oder nicht.

Anschließend bindet man man die Datei als Include in die Nginx.conf ein:


/etc/nginx/nginx.conf

http {

include /etc/nginx/conf.d/bots.map;

}

Dann wird noch in der vhost konfiguration abgefragt, ob die is_bot Variable gesetzt ist und wenn ja, wird der Zugriff gesperrt.


/etc/nginx/sites-enabled/default

server {
...

if ( $is_bot ) {
return 444;

}

}

Um hier eine dauerhafte Lösung zu schaffen, sollten bereits abgewiesene Bots dauerhaft gesperrt werden. Dazu wird in Fail2ban eine Ressource angelegt, die das Access-Log des Webservers überwacht und schaut, ob der Statuscode 444 auftaucht. Diese IP-Adressen würden dann blockiert werden.

Zuerst legt man also eine neue Filter-Regel an. Im Verzeichnis /etc/fail2ban/filter.d/ eine Datei nginx-bots.conf angelegt.


/etc/fail2ban/filter.d/nginx-bots.conf

# Fail2Ban configuration file
#
# List of bad requests
#
# Server: Nginx
# Author: Sergej Müller
#

[Definition]

# Option: failregex
# Notes : Detection of 444 requests.
# Values: TEXT
#

failregex = ^ - .+ 444 0 ".+"$

# Option: ignoreregex
# Notes : Regex to ignore.
# Values: TEXT
#

ignoreregex =

Damit die Filterregel auch geladen wird, muss folgendes in der Datei /etc/fail2ban/jail.conf angehängt werden:


/etc/fail2ban/jail.conf

[nginx-bots]

enabled = true
port = http
filter = nginx-bots
logpath = /var/log/nginx/access.log
maxretry = 0
findtime = 86400
bantime = -1


Anschließend sowohl nginx als auch Fail2ban durchstarten und der Anti-Bot-Schutz ist aktiv.