Zielsetzung

Die Dateien aus dem wp-admin Verzeichnis sind aus dem Web erreichbar. Viele Dateien müssen dies auch bleiben, damit die Anwendung funktionstüchtig bleibt. Weiterhin ist zu vermeiden, dass Bot’s Zugriff auf die Loginroutinen wp-login.php erhalten, bzw. nicht mit der bekannten Adresse angesteuert werden können, um Angriffe zu vermeiden.

Problemstellung

Die Admin URL lässt sich nicht ohne weiteres mittels einfachem Rewrite überschreiben ohne das danach die Anwendung nicht mehr funktionstüchtig ist. Auch der wp-login.php erfordert einige Maßnahmen um die Funktion nach dem URL Rewrite wiederherzustellen.

Lösungsweg

Mittels eines Rewrites werden die beiden Ziel-URI so umstellen, dass 1. niemand mehr die Zugangsinformationen zum Admin hat und Bot’s nicht mehr auf das Login crawlen können. Dazu müssen wir beachten, dass das Sitzungscookie für die Administration den korrekten Pfad hat und das Scripte, Styles und andere Assets weierhin geladen werden können.

Weiterhin müssen wir dem System bekannt machen, dass sich die URL’s generell geändert haben. Was bei der Verwendung der dafür vorgesehenen Standard-URL-Ermittlung, wie sie von WordPress vorgegeben werden, die Funktionalität erhalten soll.

Umsetzung

Mod Rewrite Module von Apache

Zunächst definiere ich hier, dass /wp-admin/ zukünfigt unter /backend/ erreichbar sein soll und das /wp-login.php schlicht über /login aufrufbar sein soll.

Um diese Änderung dem System bekannt zu machen verwende ich einige Rewrite direktiven (wie dies von den wohl meisten System unterstützt wird).

Datei: /wordpress/.htaccess

# BEGIN of our changes
<IfModule mod_rewrite.c>
    RewriteCond %{REQUEST_URI} ^.*?/?backend/?.*$
    RewriteRule ^(.*?/?)backend(/?.*)$ $1wp-admin$2 [L,E=IS_BACKEND:1,END]
    
    RewriteCond %{REQUEST_URI} ^/wordpress/wp-admin/load-styles.php$ [OR]
    RewriteCond %{REQUEST_URI} ^/wordpress/wp-admin/load-scripts.php$ [OR]
    RewriteCond %{REQUEST_URI} ^/wordpress/wp-admin/admin-ajax.php$
    RewriteRule ^.* - [L,E=IS_BACKEND:1,END]
    
    RewriteCond %{ENV:REDIRECT_IS_BACKEND} !^1$    
    RewriteCond %{REQUEST_URI} ^.*?/?wp-admin/?.*$
    RewriteRule ^.* - [F,L]
    
    RewriteCond %{REQUEST_URI} ^.*?/login\??.*$
    RewriteRule ^(.*?/?)login(\??.*)$ $1wp-login.php$2 [L,E=IS_LOGIN:1]
    
    RewriteCond %{ENV:REDIRECT_IS_LOGIN} !^1$
    RewriteCond %{SCRIPT_FILENAME} ^.*?/wp-login.php$
    RewriteRule ^.* - [F,L]
</IfModule>
# END of our changes

# BEGIN WordPress
# Die Anweisungen (Zeilen) zwischen `BEGIN WordPress` und `END WordPress` sind
# dynamisch generiert und sollten nur über WordPress-Filter geändert werden.
# Alle Änderungen an den Anweisungen zwischen diesen Markierungen werden überschrieben.

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /wordpress/
    RewriteRule ^index\.php$ - [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /wordpress/index.php [L]
</IfModule>

# END WordPress

Erläuterungen zu dieser Codesequenz


RewriteCond %{REQUEST_URI} ^.*?/?backend/?.*$

RewriteCond, leitet eine Bedingung ein die erfüllt sein muss. In diesem Fall möchten wir die Servervariable %{REQUEST_URI} ansprechen welche den Pfad und die Datei des Aufrufs beinhaltet – z.B. /meinUntervereichnis/backend/index.php

Der nachfolgende Reguläre Ausdruck sagt ungefähr aus prüfe alles was davor kommt /meinUnterverschnis/ wenn es denn vorhanden ist gefolgt von unserer neuen URL backend und allem weiteren was darauf folgt /index.php.

Regulärer Ausdruck:
^: Anfang des Strings
.*?: beliebige Zeichen oder gar keins
/?: ein / – muss aber nicht vorkommen (dafür sorgt das ? dahinter)
backend: eine Zeichenfolge die erwartet wird
$: Ende des Strings

RewriteRule ^(.*?/?)backend(/?.*)$ $1wp-admin$2 [L,E=IS_BACKEND:1,END]

RewriteRule, leitet die Weiterleitung ein, wenn unsere Bedingung zutreffend war. Wir also den administrativen Bereich über die neue URL aufrufen.

Regulärer Ausdruck:
(): Eingeschlossene Elemente werden im Speicher zur späteren Verwendung abgelegt. Die Nummering 1,2,… wird mit $1,$2,… in den nächsten Regulären Ausdruck integriert.

In diesem Fall soll der URL Aufruf /backend/ zu dem Verzeichnis /wp-admin/ weiterleiten.

Die in [] eingeschlossenen Direktiven an das Rewrite Modul des Apache steuern den Ablauf wie folgt:
L: Letzte Regel in diese Bedingung.
E: Setzt eine Environmentvariable, welche wir dann später brauchen.
END: Beendet weiteres Rewriting.

RewriteCond %{ENV:REDIRECT_IS_BACKEND} !^1$

Wir prüfen hier ob die zuvor in der RewriteRule gesetzte Umgebungsvariablen nicht den Wert 1 enthält.

RewriteCond %{REQUEST_URI} ^/wordpress/wp-admin/load-styles.php$ [OR]
RewriteCond %{REQUEST_URI} ^/wordpress/wp-admin/load-scripts.php$ [OR]
RewriteCond %{REQUEST_URI} ^/wordpress/wp-admin/admin-ajax.php$
RewriteRule ^.* - [L,E=IS_BACKEND:1,END]

Hierbei handelt es sich um mehrere Dateipfade die wir nicht blockieren können.

RewriteCond %{REQUEST_URI} ^.*?/?wp-admin/?.*$

Die URL des Browsers wurde aus dem WordPress Standard aufgerufen. Da wird dies blockieren wollen, matchen wir diesen Aufruf.

RewriteRule ^.* - [F,L]

Unsere Bedingungen für diese Regel sind definiert und alles was bis hierhin durch kommt, muss blockiert werden.
-: Es erfolgt kein Rewrite
F: Beende mit Forbidden (Zugriff nicht erlaubt)

In etwa equivalent verhält sich dies mit der Login URL.

Das setzen der Cookies (ADMIN_COOKIE_PATH)

Da sich durch das ändern der URL auch der Cookie Pfad ändert und nun auf eine nicht mehr erreichbare Seite verweist. Müssen wir diesen mit der neuen URL bekannt machen, damit der Administrationsbereich geladen werden kann.

Suchen oder ergänzen Sie in der Konfigurationsdatei folgende Konstante.

Datei: /wordpress/wp-config.php

define( 'ADMIN_COOKIE_PATH', '/wordpress/backend' );

Wobei es auch nur ‚/backend‘ sein kann, wenn Sie kein Unterverzeichnis verwenden. Es hängt ein bisschen von Ihrer Wahl ab, wie der Pfad definiert wird.

Damit kann das Cookie jetzt für die neue Domain gesetzt werden und wir können den Administrationsbereich wie gewohnt erreichen.

Es fehlt jetzt nur noch eine Codesequenz, um WordPress selbst mitzuteilen, dass sich die URL’s geändert haben. Dazu benötigen Sie im Idealfall ein eigenes Plugin, dass folgend programmiert ist. Die Grundlagen für das anlegen von Plugins werde ich hier jetzt nicht erläutern und möchte darum bitten via Google auf die Suche zu gehen, es gibt dort einige interessante Artikel dazu.

Ich bitte um Entschuldigung, wenn ich nicht den Coding Standard aus WordPress verwende – man hat in PHP sowieso schon das Problem, dass der Code waagerecht aus den Fugen gerät, dass muss man nicht noch mit zusäztlichen Leerzeichen befeuern.

Datei: /wp-content/plugins/my-url-plugin/my-url-plugin.php

if (!function_exists('add_filter')) {
    header('Status: 403 Forbidden');
    header('HTTP/1.1 403 Forbidden');
    exit();
}

add_filter('script_loader_src','my_url_plugin_url');
add_filter('style_loader_src', 'my_url_plugin_url');
add_filter('site_url', 'my_url_plugin_url');
add_filter('login_url', 'my_url_plugin_url');
add_filter('admin_url', 'my_url_plugin_url');
function my_url_plugin_url($url)
{
    return str_replace(
        ['wp-login.php', '/wp-admin/'],
        ['login', '/backend/'],
        $url
    );
}

In der Regel sollten diese Einstellungen für den Standard in WordPress kein Problem darstellen, Schwieriger wäre es z.B. das Plugin Verzeichnis abzusichern, da hier nie bekannt sein kann, in welcher Form der Programmierer sein Plugin umgesetzt hat. Was es gerade zu unmöglich macht, das Plugin Verzeichnis sinnvoll abzusichern. Verwendet der Programmierer keine URL’s in Standardform, funktionieren auch die URL Rewrites nicht. Daher bleibt dieser, eigentlich sehr wichtige Punkt an Sicherheit, vorerst wohl offen.

WordPress aktualisiert auch in regelmäßigen Abständen die .htacess Datei. Unter verschiedenen Umständen wird diese neu generiert. Eintragungen innerhalb des # WordPress Blocks werden dann überschrieben.

Für die Lösung an diesem Problem habe ich ein WordPress Modul geschrieben, dass einem die Aufgabe des überprüfens auf aktualisierung abnimmt.

wordpress-und-sumediaSumedia Urlify – sumedia-urlify
@github: https://github.com/sumedia-wordpress/urlify
@wordpress: https://de.wordpress.org/plugins/sumedia-urlify/

Ändern von WordPress Admin-URL und Login.