WordPress JSON-API Endpoints entfernen

Ich bin gerade dabei weiter Erfahrungen mit der WordPress JSON-API zu sammeln. Ich finde die Möglichkeiten, die einem die API bietet, genial.

Lediglich ein Punkt stört mich. Durch den API-Endpoint „wp-json/wp/v2/users“ können Nutzer-Namen ausgelesen werden. Aus meiner Sicht stellt das für viele Seiten ein Sicherheitsrisiko dar.

Dankbarer Weise sind E-Mail und Benutzername nicht (direkt) enthalten, sondern nur der Anzeigename. Gibt ein Nutzer allerdings keinen Anzeigenamen ein, dann nutzt Wordpress automatisch den Benutzernamen als Anzeigenamen. Benutzer können sich mit dem Benutzername und E-Mail im Backend anmelden. Wenn nun ein potentieller Angreifer bereits den Benutzernamen kennt, ist ein Wörterbuchangriff um einiges einfacher auszuführen.

Endpoint ausknipsen

Aus diesem Grund ist es also keine schlechte Idee den API-Endpoint zu entfernen, aber wie kann man das bewerkstelligen? Die Funktionen der REST-API machen es (aus gutem Grund) schwer einmal gesetzte Endpoints wieder zu entfernen. Denn, werden einzelne oder alle Endpoints gelöscht, so kann die Funktionalität von darauf aufbauenden Scripten nicht mehr sichergestellt werden.

Der folgende Code zeigt eine Lösung, die ich auf meinen Seiten nutze und einen Mittelweg darstellt. Sie entfernt den Endpoint nur für ungemeldete Benutzer.

class TM_PreventUserEndpoint {
	
	public static function init() {
		register_rest_field('user','prevent_user_endpoint',array(
			'get_callback' => array('TM_PreventUserEndpoint','preventEndpoint'),
			'update_callback' => null,
			'schema' => null
		));
	}
	
	public static function preventEndpoint() {
		if(!current_user_can('read')) {
			die();
		}
	}
}
add_action( 'rest_api_init', array('TM_PreventUserEndpoint','init'), 99);

Als erstes geben wir vor, ein neues Feld zum user-endpoint hinzufügen zu wollen (init-Funktion). Die Funktion die sich um das Feld kümmern soll, heißt in diesem Fall „preventEndpoint“. In „preventEndpoint“ wird mittels current_user_can überprüft ob der Benutzer einfache Leserechte hat. Ist dies nicht der Fall wird die PHP Ausführung hart beendet und es kommt zu keiner Ausgabe.

TIPP 1

Ich habe das Recht „read“ gewählt, weil dadurch alle Backend-Funktionalitäten unangetastet bleiben. Sollte im Administrationsbereich ein Script existieren das die User auslesen muss, kommt es zu keinen Problemen. Natürlich lassen sich auch höhere Rechte eintragen. Eine Auflistung aller Rollen und Standard-Rechte findet man in der WordPress-Doku.

TIPP 2

Um sicher vor Wörterbuchangriffen zu sein empfehle ich außerdem das Plugin Limit Login Attempts.