Bei einem Projekt mit einer vor öffentlichen Zugriffen geschützten Website sollte auch die REST-API nur für eingeloggte User aktiv sein, um zu verhindern, dass darüber Inhalte abgefragt werden können.
Nachdem ich zunächst geprüft habe, ob sich irgendwie die Permission-Callbacks verändern lassen, bin ich auf den rest_authentication_errors
-Filter gestoßen, mit dem die Aufgabe relativ einfach zu lösen ist.
Der gesamte Code ist im folgenden Code-Block abgebildet:
add_filter( 'rest_authentication_errors', function( $result ) {
// Check if there already was an auth error and return it.
if ( is_wp_error( $result ) ) {
return $result;
}
// Check if user is not logged in.
if ( ! is_user_logged_in() ) {
return new WP_Error(
'rest_not_authenticated',
'You are not authenticated',
[ 'status' => 401 ]
);
}
return $result;
} );
Code-Sprache: PHP (php)
Zunächst wird geprüft, ob $result
vielleicht bereits von einer anderen Prüfung einen Fehler enthält. Ist das der Fall, wird direkt dieser Fehler zurückgegeben.
Falls bisher kein Fehler vorhanden war, testen wir mit ! is_user_logged_in()
, ob der Request von einem nicht angemeldeten User kommt, um in diesem Fall einen neuen WP_Error
zurückzugeben, der als zweiten Parameter die Fehlermeldung erhält und als dritten Parameter den HTTP-Status, der von den API-Methoden genutzt wird um den richtigen Fehler-Code auszugeben. Wenn der User eingeloggt ist, wird das $result
unverändert zurückgegeben.
Damit bekommt ein nicht eingeloggter User beim Aufrufen von beispielsweise example.com/wp-json/
einen 401-Fehler mit der Meldung You are not authenticated
, für einen eingeloggten User funktioniert aber alles wie gewohnt.
Manche plugins (zB Contact Form 7) brauchen die API allerdings also wäre es sinnvoll gewisse Namespaces zu erlauben.
Stimmt, je nach Anwendungsfall ist ein komplettes Deaktivieren etwas zu viel
Beinhaltet $result den Pfad oder gibts den nur global?
Das beinhaltet nur den Status, ob Fehler oder nicht, also keinen Pfad
Uh - sehr neugierig.
Ich merke, dass ich die REST-API noch nicht immer mit auf dem Schirm habe.
Während ich sorgsam drauf gucke, welche Daten über die grafische Oberfläche zugänglich sind, sind evtl. dieselben Daten öffentlich via REST-API einsehbar.
Für normale User nicht tragisch - aber wer üble Dinge im Sinn hat.
Bin gespannt, ob es Lösungen gibt, die feingliedriger die API "abstellen" können ohne Nebeneffekte.
Danke schonmal fürs Teilen!
Hi Sebastian,
sehr gerne, freut mich, dass es interessant ist!
Ja, da gibt es ein aktuelles Beispiel eines COVID-Testzentrums, dem genau das passiert ist, dass sensible Daten über die REST-API zugänglich waren (Link aus dem heutigen WP Letter): https://blog.wpscan.com/2021/04/09/covid-test-center-wordpress-leak.html
Es gibt Plugins, mit denen auch granular einzelne Endpunkte abgestellt werden können. Ich hatte damit bisher in erster Linie Probleme, weil dann irgendwas nicht mehr funktioniert hat und man erst auf die Idee kommen musste, dass da etwas deaktiviert ist (wenn man eine Installation nicht selbst aufgebaut hat sondern irgendwann anfäng damit zu arbeiten) 😀
Ja, ist irgendwie ein seltsames Thema.
Bei uns nutzt scheinbar nur Contact Form7 sie Rest-API ... um ein paar Formular-Daten zu posten? ... Sinn erschließt sich mir nicht so ganz.
Aber was da für alle potentiellen Angreifer mit aktiver API "rausposaunt" wird ... das ist schon irgendwie unbefriedigend bis extrem denkwürdig?!
Das (fehlende?!) Sicherheits-Konzept dahinter verstehe ich nicht so ganz!
Da müssen sich halt die Devs der Plugins Gedanken drum machen, WordPress selbst kann ja schlecht für Plugins da irgendwelche Sachen annehmen und Sichtbarkeiten anpassen oder so.
Guter Artikel! ... der zum Nachdenken auffordern sollte, ob WordPress mit seinen internen Daten nicht "sparsamer" umgehen sollte und interne Webseiten-Infos nicht besser über Mechanismen "preisgeben" sollte, die nur ausgewählten "Usern" zur Verfügung stehen, z. Bsp. installierten Plugins?!
"Web-Sicherheit im 21. Jahrhundert" würde ich jedenfalls anders definieren!
Hallo Florian, hab gerade deinen Code auf meiner Website eingebaut und erwartungsgemäß funktioniert das ganz einwandfrei. Dankeschön.
Einziger Wermutstropfen ist, dass ich die REST API im Rahmen des Supports gerne nutze, um nachzusehen, ob Anwender die Website- und WordPress-URL richtig gesetzt haben. Es kommt überraschend häufig vor, dass bei der Umstellung auf https nur eine URL geändert wurde, was dann im Block-Editor zu Fehlermeldungen über unerwartete Antworten der REST-API führt. Ohne die Möglichkeit, die URLs über die REST-API auszulesen, bleibt dann nur der klassische Weg: man muss die Benutzer:innen fragen. 😀
Hi Bego,
freut mich! 🙂
Wir müssen die Lösung ja nicht allzu breit streuen 😇 😄
Ich war davon ausgegangen, dass der Tipp von ganz vielen umgesetzt wird! Wäre ja grundsätzlich nicht verkehrt.
Das stimmt 🙂