Schütze deine wp-config.php

Die Zeiten ändern sich.

Dieser Beitrag scheint älter als 16 Jahre zu sein – eine lange Zeit im Internet. Der Inhalt ist vielleicht veraltet.

WP
Ronald Huereca erklärt in einem Artikel auf Devlounge, wie man dafür sorgt, dass die wp-config.php der WordPress-Installation nicht für Hacker einfach erreichbar ist um so die Möglichkeit eines Hackerangriffs auf das eigene Blog zu erschweren.

Die wp-config.php ist der Schlüssel zur Datenbank und damit stehen einem Eindringen in die Datenbank nur wenige Handgriffe bevor und schon liegt die DB offen, Damit kann ein „Bösewicht“ die Daten verändern oder gar alle Daten löschen. Also liegt es nahe, diese Datei vor fremden Zugriff zu schützen. Wie und und mit welchen Mitteln man dies machen kann, das erklärt der Artikel auf zwei unterschiedliche Wegen.

Ich habe die jeweiligen Code-Schnippsel im Anschluss nochmal hinterlegt, da ich die Idee für sinnvoll und machbar, auch für den „Laien“, erachte, so dass man auch mit deutschen Sprachkenntnissen der Idee folgen und umsetzen kann.

.htaccess erweitern

Ronald erklärt zwei unterschiedliche Ansätze. Im ersten Schritt sichert er den Zugriff via .htaccess, was schnell und einfach erledigt ist.


# protect wpconfig.php
<files wp-config.php>
Order deny,allow
deny from all
</files>

Damit könnte eine .htaccess für WordPress folgenden Aufbau und Inhalt haben, wobei ich gleich einige mehr Regeln integriert habe, kleine Erläuterungen dazu im Syntax.


<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /

# www2nowww
RewriteCond %{HTTP_HOST} ^([^.]+)\.bueltge\.de$ [NC]
RewriteRule ^(.*)$ https://bueltge.de/$1 [R=301,L]

# Hinzufuegn von Slash 
RewriteCond %{REQUEST_URI} ^/[^\.]+[^/]$
RewriteRule ^(.*)$ http://%{HTTP_HOST}/$1/ [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# Schutz der wp-config.php
<files wp-config.php>
Order deny,allow
deny from all
</files>

# Datei zum Regeln von IP-Bereichen
Order deny,allow
Allow from all
# Sperre folgende IPs
deny from 83.246.96.42
deny from 82.103.133.221
deny from 74.86.15.2

Auslagern der wp-config.php

Die zweite Idee geht davon aus, dass die Datei an einen Ort des Servers verschoben wird, der nicht öffentlich zugänglich ist. Ein Beispiel soll es verdeutlichen: die Datei liegt im Normalfall im absoluten Pfad /home/deinname/public_html/, dies ändert sich nun, denn die Datei wird eine Ebene tiefer abgelegt /home/deinname/. Dies ist nicht bei allen Webhostern so, so dass die Möglichkeit nicht bei allen WordPress-Installationen möglich ist.

Die klassische wp-config.php enthält folgenden Syntax.


<?php
// ** MySQL settings ** //
define('DB_NAME', 'wpbeta');    // The name of the database
define('DB_USER', 'root');     // Your MySQL username
define('DB_PASSWORD', ''); // ...and password
define('DB_HOST', 'localhost');    // 99% chance you won't need to change this value
define('DB_CHARSET', 'utf8');
define('DB_COLLATE', '');

// You can have multiple installations in one database if you give each a unique prefix
$table_prefix  = 'wp_';   // Only numbers, letters, and underscores please!

// Change this to localize WordPress.  A corresponding MO file for the
// chosen language must be installed to wp-content/languages.
// For example, install de.mo to wp-content/languages and set WPLANG to 'de'
// to enable German language support.
define ('WPLANG', 'de_DE');

/* That's all, stop editing! Happy blogging. */

define('ABSPATH', dirname(__FILE__).'/');
require_once(ABSPATH.'wp-settings.php');
?>

Mit diesen Daten erstellt ihr eine neue Datei config.php.


<?php
// ** MySQL settings ** //
define('DB_NAME', 'wpbeta');    // The name of the database
define('DB_USER', 'root');     // Your MySQL username
define('DB_PASSWORD', ''); // ...and password
define('DB_HOST', 'localhost');    // 99% chance you won't need to change this value

// You can have multiple installations in one database if you give each a unique prefix
$table_prefix  = 'wp_';   // Only numbers, letters, and underscores please!
?>

Diese Datei wird nun per FTP in das nicht öffentliche Verzeichnis des Servers kopiert, in unserem Beispiel ist das /home/deinname/

Die originale wp-config.php wird nun verändert. Dabei werden die Datenbank-Verbindungsdaten mit Hilfe der include-Anweisung eingebunden.


<?php
include('/home/deinname/config.php');

// Change this to localize WordPress.  A corresponding MO file for the
// chosen language must be installed to wp-content/languages.
// For example, install de.mo to wp-content/languages and set WPLANG to 'de'
// to enable German language support.
define ('WPLANG', 'de_DE');

/* That's all, stop editing! Happy blogging. */

define('ABSPATH', dirname(__FILE__).'/');
require_once(ABSPATH.'wp-settings.php');
?>

Damit stehen WordPress die Daten für die Datenbank zur Verfügung und die Datei kann nicht einfach als Text angezeigt werden, denn sie liegt in einem nicht öffentlichen Bereich.

Von Frank Bültge

bueltge.de [by:ltge.de] wird von Frank Bültge geführt, administriert und gestaltet. Alle Inhalte sind persönlich von mir ausgewählt und erstellt, nach bestem Gewissen und Können, was die Möglichkeit von Fehlern nicht ausschließt.

63 Kommentare

  1. Habe den Artikel im Original und die verwandten Berichte auch mit grossem Interesse gelesen, zumindest die .htaccess-Variante wird hier demnächst ausprobiert werden, etwas mehr Sicherheit kann nicht schaden.

  2. Diese Variante habe ich schon länger drin, genau seit dem ich WP 2.4beta gefahren habe. Nun bin ich wieder auf 2.3.1 und noch immer funktioniert es tadellos. Der Zugriff liefert Forbidden.

  3. Pingback: u1amo01
  4. Vielen Dank für diesen nützlichen Tip! Zwei Fragen eines interessierten Laien – 1. wo kommt der Codeschnipsel hin? Ich habe ihn ganz am Anfang in die htaccess kopiert, gesichert und wieder hochgeladen. Das Blog läuft noch 🙂 2. wie kann ich prüfen, ob „forbidden“ funktioniert?

  5. Aber ist die wp-config.php denn echt so gefärdet?
    Ich frage nur weil ich garnicht wusste das man eine PHP Datei direkt aufrufen und die Daten lesen kann. Eigentlich wird doch alles geparst oder? Den Eintrag mit der htaccess werde ich dann wohl auch benutzen…

    Muss ich den Codeschnipsel einfach unter die vorherigen Daten in der htaccess packen? Oder gibts da auch was zu beachten?

  6. Den Syntax einfach an den bestehenden Inhalt kopieren, eine Leerzeile für die Übersicht ist angenehm

    Aufrufen der Datei sollte zu einem forbidden führen, statt einer leeren Seite.

    @Jared: Mit Hilfe von Code (PHP o. JS) kann man den Inhalt auch von php-Dateien als txt lesen.

  7. Thx Frank. Die .htaccess-Methode habe ich gleich umgesetzt. Versuchter Zugriff auf die Datei liefert bei mir ebenfalls ein „Forbidden“.

  8. Hi,
    ich habe schon eine htaccess Datei, die folgendermassen beginnt und endet
    # BEGIN WordPress

    ……
    ……

    # END WordPress

    wohin schreibe ich den von Di angegebenen code. Wie sieht das Ergebniss dann aus? Kannst Due bitte ein Beipiel geben?
    Frage deshalb so genau, weil ich des Programmierens nicht mächtig bin. Liebe Grüße
    Jochen

  9. Ohne mich weit aus dem Fenster lehnen zu wollen:
    Aber was soll der Aufwand denn?
    Bei der normalen wp-config.php kommt doch überhaupt kein Output beim Aufruf zustande, wie soll da was geklaut werden?
    Ich mein klar, sicher ist sicher.
    Aber doch etwas mit Kanonen auf Spatzen geschossen, oder nicht?

    Aber ich lasse mich gerne eines besseren belehren.

  10. mal ein einfaches Bsp., auf die schnelle eine php-Datei auslesen:

    <?php
    $file = '.../wp-config.php';
    if (!$file) {
    	echo("

    Error: unable to load URL file into $file. Process aborted.

    "); exit(); } $file = file_get_contents($file); highlight_string($file); ?>
  11. @Frank (19. November 2007 um 12:24):
    Wenn man mit PHP eine PHP-Datei einliest, dann bekommt man als Ergebnis die HTML-Ausgabe der PHP-Datei, nicht den PHP-Code. Das habe ich gerade ausprobiert. 😉

  12. @Marco: mit dem Beispiel-Syntax bekomme ich jeden Zeile, 1:1 wie die PHP-Datei. Allerdings habe ich solche Spielereien bisher nur lokal betrieben.
    show_source z.B. liefert html, wenn der Server so eingestellt ist. Den Inhalt einer PHP-Datei kann man aber auch als txt auslesen.

  13. Das hat meine wp-config so gut geschützt, dass ich interner Servererror 500 bekam. *lach* Erst als die htaccess wieder original war konnte ich wieder zugreifen auf meine installation. 😀

  14. Ähm Frank, korrigier mich, wenn ich falsch liege:

    Lokal kann ich Dateien immer auslesen, weil da nicht der Apache zwischendurch die htaccess prüft und per Remote (http://, was den Apache ja dazu bringt die htaccess zu prüfen) wird php so der Server richtig eingestellt ist IMMER geparst. Demnach hab ich mit JS (=JavaScript) keinerlei Chancen die Datei auszulesen.

    Das Problem, welches auch die „Hacker“ beschrieben haben war folgendes:
    1. Jemand stolpert eher zufällig über einen Blog.
    2. Der Server gibt aus irgend einem Grund (Fehlkonfiguration, Schluckauf, Probleme PHP zu starten, …) die Datei nicht zum Parsen an PHP weiter
    3. Der Besucher bekommt anstelle des Blogs den Quellcode der index.php
    4. Der Besucher kennt WordPress und ruft die wp-config.php auf
    5. Diese wird auch nicht geparsed sondern so auf die Reise geschickt
    6. Zugangsdaten zu MySQL hat jetzt jemand anders
    7. Der MySQL User war nicht nur für Lokalhost eingerichtet.

    Faktum Akut ist also: Wer Schreibberechtigung auf irgendeiner php-Datei hat, der kann die wp-config.php auch auslesen (und demnach auch die verschobene) wer diesen Zugriff nicht hat – der kanns nur bei Fehlkonfiguration des Servers – und dann geht noch vieeeel mehr 😉

    Bei diesem Beispiel halte ich folgende Dinge für äußerst bedenklich:
    a) Der Server gibt Quellcodes raus => Das ist eigentlich das letzte was bei nem Produktivsystem passieren darf
    b) Der MySQL-User wurde für alle Verbindungen von Außen (Hosts/IPs) eingerichtet – würde ich bei Produktivsystemen wirklich 5x drüber nachdenken, ob das nötig ist. In aller Regel reicht es den User für Localhost einzurichten – dann kann man mit dem User und dem Passwort nur noch was anfangen, wenn man selber ein Hosting Packet auf dem Server hat bzw. die URL zu phpMyAdmin oder eine SQL-Injection Lücke kennt… wobei bei letztem in aller Regel kein User/Passwort benötigt werden…

    Eigentlich schützt man sich also davor, dass bei einem Fehlverhalten des Servers relevante Daten weitergereicht werden. Das ist zwar löblich (und ich mache das auch) aber eigentlich sollte man sich lieber davor schützen, dass der Server so nen Mist macht. (Ist halt nur nicht immer möglich, is mir auch klar)

    Gruß
    Alex

  15. Hallo Alex,
    ich danke für die kurzen und treffenden Auskünfte zum Problem und Apache-Hintergründe.

    Grundsätzlich hast du recht, nur dass in den meisten Fällen der Server gehostet wird und man (oft sicher auch gut so) keinen Einfluss darauf hat. Die andere Tür sind die Fehler in der Applikation, die schnell mit einem Plugin ins System geholt sind.
    Klar, die Sicherung der wp-config.php ist nur für einen ganz kleinen Teil von möglichen Türen ein Schutz, aber für sehr wenig Aufwand schließt man wieder eine.
    * Ich habe nochmal nach dem Artikel, wie man php-Code aus einer Datei ausliest gesucht, aber ohne Erfolg. Hatte den Artikel vor langer Zeit mal gelesen, dachte eigentlich bei gulli, aber ohne Erfolg.
    Das Beispiel klappt nur lokal, aber es soll nur mal zeigen, dass wenn der Apache nicht sauber eingerichtet ist, was geht.
    LG Frank

  16. Hallo, ich finde diesen Artikel sehr interessant. Da ich bei einem Blog in rumänischer Sprache mitarbeite (www.cnet.ro), der über WP läuft und in dem macnhmal auch darüber berichtet wird, würde ich ihn gern ins Rumänische übersetzen. Ich weiß nur nicht so recht, ob dies den im Impressum genannten CC 2.5 entspricht. Würde mich auf einer Antwort freuen. Vielen Dank im voraus.

  17. Hallo Frank,
    vielen Dank für den Tip. Ich bin in php nicht ganz so tief drin, aber in Deinem Beispiel nicht ein (hoffentlich nimmt er das so) zuviel drin? Also die wp-config.php beginnt ja damit, dann kommt der include für die config.php, aber in der steht doch auch nochmal am Anfang. Beißt sich das irgendwie?
    Grüße Martin

  18. Hatte es befürchtet. also noch ein Versuch:
    Ich bin in PHP nicht ganz so tief drin, aber in Deinem Beispiel nicht ein <?php> (hoffentlich nimmt er das so) zuviel drin? Also die wp-config.php beginnt ja damit, dann kommt der include für die config.php, aber in der steht doch auch nochmal <?php> am Anfang. Gibt das dann nicht zwei <?php> hintereinander? Unten wird ja nur eines zugemacht.

Kommentare sind geschlossen.