Ein Blog über Code, Hardware und Co

Wordpress und Webentwicklung

WordPress-Rest API Zugriff einschränken [Ohne Plugin]

Zuletzt aktualisiert am 14. Januar 2023.

Oder: WordPress-Rest-API nur für eingeloggte User, oder Admins.

Die WordPress-REST API ist seit WordPress 4.4 keine über ein zusätzliches Plugin realisierte Funktion mehr, sondern fester Bestandteil des WordPress-Cores.
Anders als oft behauptet, ist die WordPress-API für sich genommen KEIN Sicherheitsrisiko und erst recht keine Sicherheitslücke. Trotzdem kann es durchaus Sinn ergeben, den Zugriff einzuschränken.

Was ist die WordPress-REST API?

Die WordPress Rest-API ist, wie der Name sagt, ein Application Programming Interface. Die WordPress Rest-API kommuniziert mit Hilfe des weit verbreiteten JSON-Format, indem es sowohl Requests, als auch Responses als JSON-Strings erwartet bzw. ausgibt.

Es ist grundsätzlich eine tolle Sache, dass WordPress eine REST-API integriert hat. So können auch ohne ein WordPress-Frontend Daten ausgelesen und eingetragen werden. Besonders für sogenannte “Headless”-Installationen von WordPress ist das von Vorteil, aber auch externe Anwendungen wie z.B. Apps oder Dienstleister können so besser und vor allem Formalisiert an eine WordPress-Instanz angebunden werden.

Ein weiterer Vorteil ist, dass ein API feste Routen bietet und kein direkter Datenbankzugriff gewährt werden muss.

Ein Nachteil ist, dass zwar das normale “Rollenmanagement” und Rechtesystem von WordPress auch bei der API gilt, jedoch standardmäßig nur die Cookiebasierte Authentifizierung mittels

Wieso ist die WordPress REST-API kein Sicherheitsproblem?

Die WordPress REST-API ist eine Funktionalität des WordPress-Cores. Und dieser WordPress-Core läuft – häufig auch in seiner Standardconfig – auf Millionen von Hosts und Webseiten. Eine Sicherheitslücke wäre hier wahrlich eine mittlere Katastrophe, würde aber schnell.
Es gibt wohl kaum Code, der von mehr Augen reviewt wird, als der WordPress-Core (der übrigens öffentlich über GitHub (bzw. Subversion) einsehbar ist).
Die WordPress-API liefert nur Daten, die über das.

Achtung: Jedes Plugin kann beliebige Routen für die API ergänzen. Diese Routen sind nicht Bestandteil des WordPress-Cores und können selbstverständlich auch Sicherheitslücken aufweisen.

Wieso ist das Einschränken des Zugriffs manchmal trotzdem eine gute Idee?[Stichwort: Datenschutz, Bruteforce]

Auch wenn dike API in der Regel kein direktes Sicherheitsproblem darstellt, so kann sie doch Daten gesammelt offenlegen, die vielleicht in dieser aggregierten Form nicht für die Öffentlichkeit bestimmt sind. Dabei handelt es sich besonders um den im Netz viel diskutierten API-Endpoint “/wp-json/wp/v2/users/”.

Um zu überprüfen, ob bei dir die Usernamen deiner User ausgegeben werden, rufe also die folgende URL (mit deiner Domain) auf:

www.deinedomain.de/wp-json/wp/v2/users/

Hier werden standardmäßig alle Nutzer samt Usernamen ausgegeben. Wenn auf der Webseite Klarnamen kann es hier zu einem Datenschutzproblem kommen. Und auch sonst kann die Auflistung der Benutzernamen für strukturiertes Bruteforcing, also das Ausprobieren unterschiedlicher Passwörter zu den jeweiligen Nutzern, genutzt werden.
Hat auch nur ein Account ein schwaches Passwort, so kann der Account schnell übernommen werden.

Lösungen: WordPress-API Zugriff einschränken

Variante 1: WordPress-API komplett deaktivieren

Die Methode “Holzhammer” ist sicherlich das komplette Deaktivieren der WordPress-REST-Api. Das geht über verschiedene Plugins wie z.B.:

Oder auch über die functions.php deines Themes, indem du folgenden Code (folgende Filter) dort ergänzt:

add_filter('rest_enabled', '_return_false');
add_filter('rest_jsonp_enabled', '_return_false');
Achtung: Das komplette Deaktivieren der WordPress-API empfiehlt sich aus meiner Sicht nicht, da viele Plugins, z.B. auch der weit verbreitete Gutenberg-Editor (Block Editor), ohne eine aktivierte API nicht funktionieren. Zudem stellt die API mit ihren Standardrouten in der Regel kein Sicherheitsrisiko dar.

Deaktivieren der WordPress-REST-API über ein Plugin im Video:

Video 1: Deaktivieren der WP-Rest-API.

Variante 2: Komplette API erst nach Authentifizierung bereitstellen

Eine gute Variante, um den öffentlichen Zugriff auf die REST-API zu begrenzen, ist es, die API nur für eingeloggte Nutzer zur Verfügung zu stellen.

Tipp: Ohnehin sind die API-Rechte bereits an die Nutzerrollen geknüpft. Das Erstellen (POST), Updaten (POST) und Löschen (DELETE) von Beiträgen ist damit ohnehin nur eingeloggten Nutzern möglich.

Wir wollen nun also auch die GET-Requests nur für eingeloggte Nutzer verfügbar machen. Dafür fügen wir den folgenden Codeschnipsel (Filter) in der functions.php hinzu:

add_filter( 'rest_authentication_errors', function ( $error ) {

    if ( strtolower( $_SERVER[ 'REQUEST_METHOD' ] ) === 'get' && !is_wp_error( $error ) && $error !== true ) {

        if ( !is_user_logged_in()) {
            $error = new \WP_Error( 'User nicht eingeloggt.' );
        }

    }

    return $error;
}, 11 );

Auch GET-Requests sind so erst nach erfolgreichem Login möglich. Das ist mit der Standard-Login-Methode (cookiebasiert) bei WordPress jedoch leider vom Sessionmanagement her etwas mühselig.

Daher empfiehlt es sich bei der Nutzung der API ohnehin eine Authentifizierung mittels AUTH-Header z.B. als BASIC-AUTH oder – noch besser – mittels JSON Web Token zu realisieren.

Seit WordPress 5.6. sind z.B. Anwendungspasswörter (ehemals Application Passwords) in WordPress integriert, die die BASIC-AUTH-Authentigfizierung für die API ermöglich.

Für die Authentifizierung mittels JSON-Web-Token helfen z.B. die folgenden Plugins:

Variante 3: Einzelne Routen deaktivieren

Mit Hilfe des Filters “rest_endpoints” lasesn sich sogar einzelne Endpoints der API deaktivieren:

add_filter('rest_endpoints', function ($endpoints) {
  $deleteable_endpoints = array(
    'users',
    'posts',
    'settings'
  );

  foreach ($deleteable_endpoints as $endpoint) {
    $base = "/wp/v2/{$endpoint}";
    foreach ($endpoints as $this_endpoint => $object) {
      if (strpos($this_endpoint, $base) !== false) {
        unset($endpoints[$this_endpoint]);
      }
    }
  }

  return $endpoints;
});

Alternative Varianten

Durch die oben aufgeführten Methoden und die Filter “rest_authentication_errors” und “rest_endpoints” lassen sich nun theoretisch beliebige Konstrukte coden, die z.B. je nach Loginstatus oder je nach Nutzer (anhand der Nutzerid) unterschiedliche Endpoints aktivieren oder deaktivieren.

Prefix der API-Ändern

Zu guter Letzt noch ein Pseudo-Security-Tipp:
Über den Filter “rest_url_prefix” lässt sich der API-Prefix in der URL ändern. Dadurch wird der Pfad, unter dem die API Endpunkte erreichbar sind geändert.
Der Code für die functions.php sieht dann z.B. wie folgt aus (das Prefix wird von “wp-json” in “rest-api” geändert):

add_filter('rest_url_prefix', function () {
  return 'rest-api';
}); 

Die API ist damit dann unter www.deindomain.de/rest-api/wp/v2/ statt www.deindomain.de/wp-json/wp/v2/ erreichbar.

Das erhöht nicht die Sicherheit der API an sich freilich nicht, es wird lediglich das Grundrauschen durch Bots und Co, die nach offenen Standard-API-Endpunkten suchen, gemindert.

Fazit: Die Sicherheit der der WordPress-REST-API erhöhen

Zunächst lässt sich festhalten, dass die API an sich kein Sicherheitsproblem darstellt. Trotzdem kann es sinnvoll sein, den Zugriff einzuschränken. Das lässt sich über Plugins oder – feingranularer – über Code in der functions.php erreichen.

Quellen

  • https://developer.wordpress.org/rest-api/
  • https://github.com/WordPress/WordPress
  • https://it-talents.de/it-wissen/was-ist-eine-api/

Schreibe eine Antwort