Die Absicherung einer WordPress Installation
Nach der Installation von WordPress auf unserem Server, widmete ich mich gleich der Sicherheit selbiger.
Als Betreiber eines Blogs kann es nie schaden, sich auch über die Sicherheit ein paar Gedanken zu machen. Dies gilt verstärkt, wenn es sich um einen eigenen Root-Server handelt, der noch andere Dienste zur Verfügung stellt.
Beim Absichern der WordPress Installation habe ich mich hauptsächlich an zwei Artikeln orientiert. Sicherheit / WordPress absichern von Michael Weingärtner ist eine hervorragende Zusammenfassung verschiedener Sicherheitsmechanismen und ist auch sinnvoll kategorisiert. Leider beziehen sich einige der dort aufgezählten Maßnahmen auf ältere WordPress Installationen.
Sehr hilfreich ist ebenfalls der Artikel WordPress sicherer machen von Frank Bültge. Was mich jedoch, als jemand, der gelesenes sehr schnell umsetzen muss, hier gestört hat: An einigen Stellen wird sehr minutiös beschrieben, wie man eine Maßnahme umsetzt (und ich tipper es natürlich gleich ein), nur damit eine Bildschirmseite drunter geschrieben wird, dass gleiches auch ganz einfach mit Plugin xyz zu erledigen ist. Gna!
Beide Artikel sind trotzdem sehr lesenswert, was mich aber nicht hindert einen eigenen zu schreiben *g*
Die hier beschrieben Mittel erschweren vor allem die automatischen Angriffe auf bekannte Sicherheitslücken. Der Zustand einer absoluten Sicherheit ist eine Utopie und kann nicht erreicht werden. Man kann nur versuchen die Sicherheit zu erhöhen. Trotzdem sollte man immer wachsam bleiben und regelmäßig Logfiles etc. überprüfen.
ACHTUNG: Die hier gegebenen Tipps, sind abhängig von dem zugrundeliegenden System, blindes Ausführen der Befehle kann dafür sorgen, dass WordPress nicht mehr geht, Dein Klo verstopft, Dein Haus abbrennt oder die Welt untergeht. Daher bitte die gebührende Vorsicht walten lassen und /dev/brain aktivieren.
Alles klar? Here we go!
Admin User löschen
admin ist der voreingestellte Username der WordPress Installation. Automatische Brute-Force Passwortknacker müssen bei bekannten Usernamen nur noch das Passwort “ertesten”. Ändert man hingegen den Usernamen müssen Username und Passwort gefunden werden. Daher sollte der admin User durch einen anderen Account ersetzt werden. Auch beim Usernamen sollte darauf geachtet werden, dass er nicht einfach zu erraten ist. Vom admin User bereits geschriebene Artikel können an den neu angelegten User vererbt werden.
Änderungen in der Datenbank
Da WordPress eine frisch erstellte Datenbank verwendet und User-IDs sequentiell vergeben werden, sind die User-IDs der ersten User in der Datenbank wohlbekannt (admin hat immer die User_ID 1). Dieses Wissen kann von Hackern ausgenutzt werden, daher ändert man die User-IDs lieber. Am einfachsten geht dies mit dem WordPress Plugin Search and Replace: User-ID auswählen, bei Replace 1 eintragen, bei with einen beliebigen positiven Wert eintragen, fertig.
search and replace - change user-id

Wer mag, kann das ganze auch per Hand über ein UPDATE auf wp_users, wp_usermeta, wp_posts, wp_links machen. Wie es genau geht ist in WordPress sicherer machen beschrieben.
Da wir gerade bei Tabellenbearbeitung sind, machen wir weiter mit den Präfixen der WordPress Datenbank. WordPress verwendet per default wp_ als Präfix. Hacker können dieses Wissen für SQL Injections Angriffe mißbrauchen, daher ändern wie den Präfix einfach.
Jetzt darf sich jeder freuen, der WordPress noch nicht installiert hat. Dann reicht es nämlich in der Datei wp-config.php die Zeile
$table_prefix = 'wp_';
abzuändern auf einen schönen zufälligen Wert. Mehrfaches Fallenlassen der Hand produziert so beispielsweise: “sw4u6l”. Klasse!
Hat man WordPress bereits installiert, ist es nicht ganz so einfach, aber zum Glück gibt es auch dafür ein Plugin. Den WP Prefix Changer von blogsecurity. Unter Plugins Prefix Changer auswählen und “Start Renaming” anklicken.
Ich habe es jedoch per Hand über die MySQL Konsole gemacht, wie genau das geht, steht ebenfalls in dem Artikel WordPress sicherer machen.
Ganz wichtig: jetzt noch in der wp_config.php den neuen Präfix setzen(s.o.)!
Zugriffsrechte auf Dateiebene
Generell sollte man darauf achten, dass eine Anwendung immer nur die Zugriffsrechte hat, die sie zur Funktion benötigt.
Aber Vorsicht: Änderungen an den Zugriffsrechten haben enormes Kaputtmachpotential! Daher vor dem blinden Kopieren der Befehle erstmal schaun, ob sie für das eigene System zutreffen.
Falls noch nicht geschehen sorgt man erstmal dafür, dass das WordPress Projekt einem User gehört, der der Gruppe des Webservers angehört. Bei Blog-Hosts sollte dies automatisch der Fall sein. Falls man den owner noch ändern muss, führt man im WordPressverzeichnis:
chown -R user:group *
aus. User und Group bitte entsprechende anpassen (zb. www-data:www-data). Dieser Befehl ändert rekursiv den Besitzer und die Gruppe aller Dateien und Verzeichnisse im aktuellen Verzeichnis.
Jetzt gehts ans Eingemachte. Jetzt ändern wir die Zugriffsrechte der Dateien und Verzeichnisse:
find . -type d -print0 | xargs -0 chmod 700 find . -type f -print0 | xargs -0 chmod 600
Der erste Befehl ändert die Rechte von allen Verzeichnissen so, dass nur noch der Besitzer sie lesen(4), schreiben(2) und ausführen(1) darf. Während der zweite Befehl die Rechte aller Dateien auf lesen und schreiben setzt. Das reicht WordPress im Allgemeinen.
Falls Du Dich auch an meine Installationsanleitung gehalten hast, so befindet sich in dem WordPressverzeichnis das Unterverzeichniss logs, von dem wir nun die Rechte wieder zurückändern sollten.
chown -R root:adm logs chmod 600 logs chmod 640 logs/*
Ausführen von PHP-Skripten per .htaccess unterbinden
Neben den Zugriffsrechten auf Dateisystemebene, kann man Zugriffsrechte auch für den Web-Server definieren. Unter anderem zu diesem Zweck können .htaccess Files benutzt werden.
Für diese Änderungen editiert man das .htaccess File im Hauptverzeichnis der WordPress Installation. Die eigenen Änderungen müssen außerhalb des Kommentarblocks von WordPress vorgenommen werden, sonst werden sie evtl. mal überschrieben.
Zuerst verbieten wir den direkten Aufruf von PHP Dateien, die in den Verzeichnissen wp-content und wp-include liegen, da diese normalerweise nie direkt aufgerufen werden. Es gibt hingegen einige Plugins, die dies tun wollen und die dementsprechend dann nicht mehr funktionieren. In einem solchen Fall würde ich nach einem anderen Plugin suchen. In dem Fall, dass es keine Alternative gibt und man das Plugin unbedingt braucht, muss man diese Zeilen dann wieder deaktivieren:
#Verbiete direkten Zugriff auf PHP-Skripte innerhalb von wp-includes und wp-content RewriteCond %{QUERY_STRING} !error RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(wp-includes|wp-content)/(.+)\.php\ HTTP/ RewriteRule .* - [F]
In allen mir bekannten Tutorials und Blogposts wird nur beschrieben, was diese Zeilen tun (s.o.) aber leider nicht wie. Daher hier mein Versuch einer Erklärung:
- Zeile eins: Eine Bedingung die zum Ausführen der RewriteRule erfüllt werden muss. In diesem Fall darf der Query String (in der URL alles was nach dem Fragezeichen kommt) nicht das Wort “error” enthalten. Der Sinn dieser Zeile ist mir noch unklar. Ich freu mich über erhellende Kommentare.
- Zeile zwei: Eine weitere Bedingung, die ebenfalls erfüllt sein muss, damit die RewriteRule ausgeführt wird. THE_REQUEST ist eine spezielle mod rewrite Variable, die die komplette HTTP Request Zeile enthält. Der für uns interessante Teil ist der Part zwischen den beiden Leerzeichen, auch Request-URI genannt: /(wp-includes|wp-content)/(.+)\.php\ Diese Bedingung trifft auf alle auf .php endenen Dateien aus den Unterverzeichnissen wp-include oder wp-content zu. Beispiel: /wp-content/plugins/hello.php oder auch wp-includes/version.php
Der Rest (^[A-Z]{3,9}\ und HTTP/) wird benötigt, weil hier (IHMO unnötigerweise) THE_REQUEST anstatt REQUEST_URI verwendet wurde. Auch hier bin ich für erhellende Kommentare warum dies so ist dankbar! - Zeile drei: Wird nur ausgeführt wenn beide Conditions erfüllt werden und produziert bei jeder Anfrage eine 403 Forbidden Fehlermeldung.
- Fazit: Wir verbieten PHP Dateien in den genannten Verzeichnissen per HTTP aufzurufen.
Aufrufbarkeit von Dateien anhand der Dateiendung über .htaccess
Über das .htaccess File lassen sich auch noch viele andere schöne Einschränkungen vornehmen.
Zum Beispiel kann man dem Webserver mitteilen, welche Art von Dateien er an welchem Ort öffnen darf. Damit lassen sich von vornherein unbeabsichtigte Zugriffe vermeiden.
Dazu kommt sowohl in wp-includes/ als auch in wp-content/ ein .htaccess File mit diesem Inhalt:
# Zugriff auf die genannten Dateitypen erlauben, Rest verbieten Order deny,allow Deny from all <Files ~ ".(xml|css|jpe?g|png|gif|js)$"> Allow from all </Files>
- Zeile eins: Zuerst werden alle Deny-Anweisungen interpretiert, anschließend alle Allow-Anweisungen. Die nachfolgenden Allow-Anweisungen haben höhere Priorität (überschreiben) als die vorhergehenden Deny-Anweisungen. Falls keine Regel zutrifft, gilt default: Allow
- Zeile zwei: Alles alles verbieten
- Zeile drei-fünf : Ok,ok, ein bisschen was dann doch zulassen. Dateien mit der aufgeführten Dateierweiterung dürfen ausgeführt werden.
Diese Regeln sind sehr restriktiv und könnten bewirken, dass einige WP-Funktionen und Plugins nicht mehr funktionieren. Bei mir waren daher folgende Anpassungen nötig:
<Files ~ ".(php|lock|xml|css|jpe?g|png|gif|js)$"> #angepasst für wp-content <Files ~ ".(html|htm|xml|css|jpe?g|png|gif|js)$"> #angepasst für wp-includes
Hier muss jeder selbst ausprobieren, welche Dateitypen man für seine WP-Installation benötigt.
Mind boggling fact: Per mod_rewrite verhindere ich den Aufruf von PHP Skripten aus wp-content(s.o.), während ich sie mit mod_access erlaube! Ist aber korrekt so. Mod_rewrite verbietet nämlich den Zugriff von außen, indem es auf Zugriffsversuche mit einer 403er Fehlermeldung reagiert, während mod_access den Zugriff auf PHP-Dateien für den Webserver erlaubt. Dh. von außen kommt keiner drauf, aber der Apache (und damit die WP-Plugins) dürfen weiterhin dort zugreifen.
wp-admin nur für bestimmte IPs über .htaccess
Falls man über eine statische IP verfügt, kann es sinnvoll sein, dass wp-admin/ Verzeichnis nur von dieser IP aus zugreifbar zu machen. Dadurch verliert man dann aber den Vorteil, von überall aus neue Artikel für seinen Blog schreiben zu können. Dazu folgendes in ein .htaccess im wp-admin Verzeichnis eintragen:
Order deny,allow Deny from all Allow from 257.257.257.257
- Zeile eins: Erst alle Deny Regeln, dann alle Allow Regeln (auch default)
- Zeile zwei: Alles verbieten
- Zeile drei: Diese IP erlauben (Bitte die eigene eintragen). Hier sind auch mehrere IPs oder Ranges erlaubt. Zb sinnvoll um Zugriffe aus einem Firmennetzwerk, oder von einen Provider aus zu erlauben
Zugriff auf die wp-config.php per .htaccess verbieten
Da in der wp-config.php sehr sensitive Daten, wie z.B. das DB-Passwort stehen, sollte man dieses File noch einmal gesondert absichern. Am besten verbieten wir einfach komplett den Zugriff auf diese Datei über:
#Verbietet Zugriff auf wp-config: Order deny,allow <Files wp-config.php> Deny from all </Files>
Dies kommt in das .htaccess File im WP-Wurzelverzeichnis. Die Syntax entspricht der der vorhergehenden Beispiele und ist inzwischen hoffentlich verständlich.
Plugins
Es gibt diverse Plugins die sich rund um das Thema Sicherheit drehen. Einige der hier beschrieben Punkte werden eventuell auch von manchen Plugins erledigt. Eine kurze Auflistung wichtiger Sicherheitsplugins hat Frank Bültge verfasst.
Speziell erwähnen möchte ich hier noch das Plugin den Dienst von blogsecurity.net, mit welchem man sein Blog auf bekannte Sicherheitslücken überprüfen kann. Ein hervorragendes Tool, dass einem die Absicherung des eigenen Blogs vereinfacht.
Gerade neu erschienen und noch in beta, die neue Version des Securityscanners.
Gesunder Menschenverstand
Dieser Punkt ist mit einem meiner ersten Punkte (nämlich /dev/brain aktivieren) eigentlich erledigt. Dennoch hier eine kurze Aufzählung allgemeiner Sicherheitshinweise:
- Sichere Passwörter wählen
- Regelmäßig Updates einspielen (WordPress, Themes, Plugins)
- Nicht benötigte Dinge deaktivieren (Themes, Plugins, User Accounts)
- Logfiles auswerten
- Regelmäßig Backups machen
Links:
Wer nach diesem kurzen und unvollständigen Einblick in die Absicherung einer WordPress Installation, immer noch wissbegierig ist, kann hier noch ein bisschen weiterlesen. Viele der Security-Links handeln die gleichen Themen ab wie hier, einige führen auch noch weiter.
Ich habe ebenfalls ein paar Links beigefügt die für das Verständnis der hier erwähnten Technologien wichtig sind.
BlogSecurity:
Blogsecurity.net
WordPress Sicherheitsscanner von Blogsecurity
Wie man WordPress sicher installiert auf Blogsecurity
WordPress Sicherheitsplugins von Frank Bültge
Sicherheit in WordPress (Teil 1) von insgesamt vier Teilen von Mathias Schmidt.
Hintergrundinfos:
CGI Variablen von NCSA HTTPd
Mod Rewrite Einführung auf Easy Mod Rewrite
Mod Rewrite Merkzettel von AskApache
Viele Mod Rewrite Anwendungsbeispiele von AskApache
Mod Rewrite Dokumentation von der Apache Software Foundation
Mod Access Dokumentation von der Apache Software Foundation
HTTP RFC vom w3c
Regex Tutorial von Jan Goyvaerts
(Timo Münster)
Tags: .htaccess, apache, blog, linux, mysql, php, security, wordpress


14. Februar, 2010 at 09:22
[...] uns « adysso auf der CeBIT ‘09 Die Absicherung einer WordPress Installation [...]