Verwenden von WP 4.8.2
Was ist der beste Weg, um die anfordernde URL zu überprüfen, wenn eine Anfrage mit der Rest-API verarbeitet wird?
Beispielsweise erhält eine Site eine Anfrage und Sie möchten überprüfen, ob sie von einer "erlaubten" URL stammt. Und scheitern, wenn die URL nicht erlaubt ist.
Das funktioniert nicht:
function my_check_request_url( $request, $url ) {
$bits = parse_url( $url );
if ( $bits['host'] != 'example.com' )
$request = false;
return $request;
}
add_filter( 'rest_request_from_url', 'my_check_request_url', 10, 2 );
$request
und$url
wie Vars übervar_dump
oder ähnlich aussehen , finde ich, dass die Überprüfung der Ein- und Ausgänge immer zu einer richtigen Antwort führt.Antworten:
Dieser Filter ist definitiv nicht der, den Sie suchen. Dieser Filter wird ausgelöst, bevor das Ergebnis zurückgegeben wird. Dies
WP_REST_Request::from_url()
scheint eine Factory-Methode zu sein, die nur intern zum Behandeln von Einbettungen verwendet wird.Eine bessere Option ist die Rückgabe einer
WP_Error
Instanz imrest_pre_dispatch
Filter .Einige Einschränkungen:
Wie von @milo erwähnt, ist der Referer nicht zuverlässig und sollte nicht für eine Sicherheitsüberprüfung verwendet werden.
Darüber hinaus kann die Einstellung nicht garantiert werden.
Im Folgenden finden Sie ein Beispiel dafür, wie Sie den
rest_pre_dispatch
Filter verwenden können, um die Anforderung zum Fehlschlagen zu bringen, wenn sie von einem fehlerhaften Referer stammt:quelle
Alles, was Sie vom Client erhalten, gilt als Benutzereingabe und sollte nicht als vertrauenswürdig eingestuft werden. Da der Header leicht manipuliert und missbraucht werden kann, empfehle ich, diese Methode nicht zu verwenden, wenn Sie sich bei vertraulichen Daten darauf verlassen.
Wenn die Anforderungen von einer Seite stammen, können Sie einen anderen Ansatz wählen. Andernfalls kann jeder von nirgendwo aus eine Anfrage an die API senden und den Referrer ändern.
Angenommen, Sie haben eine Reihe von Seiten, die als "Zulässig" gefiltert werden . Sie können nur für diese Seiten einen Nounce erstellen und diese dann in Ihrer Anfrage validieren.
Wenn ein Nounce vorhanden und gültig ist, ist die Anforderung zulässig. Andernfalls blockieren Sie es.
quelle
@ssnepenthes Antwort lautet zu Recht, dass der von Ihnen verwendete Hook bei eingehenden Anfragen nicht der richtige ist.
Anforderungsinformationen stehen PHP sofort zur Verfügung, sodass Sie den frühesten verfügbaren Hook verwenden können, um sie zu überprüfen. Wenn Sie dies im Kontext der Anforderungs-API tun möchten, sollten Sie den frühesten Hook einer REST-API-Anforderung verwenden.
'rest_pre_dispatch'
Der von @ssnepenthe vorgeschlagene Vorschlag ist in Ordnung. Möglicherweiserest_authentication_errors
können Sie auch einen Fehler zurückgeben, falls etwas nicht stimmt.Aber Jack Johansson ist direkt sagen , dass HTTP - Header (wie die Referer - Header verwendet in @ ssnepenthe des aswer) sind nicht vertrauenswürdig, da sie sehr leicht vom Client geändert. Es wäre also so, als würde man einen Wachmann vor eine Tür stellen, der nur fragt: "Es ist sicher, Sie eintreten zu lassen?" an alle, die reingehen wollen: das wird nicht funktionieren.
Aber die von Jack Johansson vorgeschlagene Antwort (ein Nonce) ist auch keine echte Lösung: Der springende Punkt bei Nonces ist, sich mit der Zeit zu ändern, und ein öffentlicher API-Endpunkt kann keine Dinge haben, die sich basierend auf der Zeit ändern. Darüber hinaus sind WP-Nonces nur dann vertrauenswürdig, wenn ein angemeldeter Benutzer vorhanden ist, was bei einer öffentlichen API möglicherweise nicht der Fall ist. Wenn ein Benutzer angemeldet ist, gibt es wahrscheinlich keinen Grund, die eingehende Domäne zu überprüfen: Sie vertrauen dem Benutzer, nicht dem Benutzermaschine.
Also, was tun?
Selbst wenn HTTP-Header nicht vertrauenswürdig sind, stammen nicht alle verfügbaren Informationen
$_SERVER
aus Headern.Normalerweise stammen alle
$_SERVER
Werte, deren Schlüssel mit beginnen,HTTP_
aus Kopfzeilen und müssen als unsichere Benutzereingaben behandelt werden .Aber zum Beispiel
$_SERVER['REMOTE_ADDR']
enthält die IP - Adresse für die TCP - Verbindung zu Ihrem Server verwendet, was bedeutet , es ist vertrauenswürdiger 1 .Was auch bedeutet, dass entweder:
$_SERVER['REMOTE_HOST']
Werts (zum Beispiel in Apache, den SieHostnameLookups On
in Ihrem benötigenhttpd.conf
) dieses Wertsgethostbyaddr
diese Option, um eine umgekehrte DNS-Suche durchzuführen, um den Domänennamen der in gespeicherten IP-Adresse aufzulösen$_SERVER['REMOTE_ADDR']
Sie könnten recht zuverlässig einen Hostnamen erhalten , dass Sie gegen eine weiße Liste zu überprüfen , verwenden könnten (für den Code, können Sie den Code von @ ssnepenthe des aswer anzupassen , wo Sie ersetzen würden
$referer = $request->get_header('referer')
mit$referer = gethostbyaddr($_SERVER['REMOTE_ADDR'])
).Aber es gibt ein Problem .
Befindet sich Ihr Webserver hinter einem Reverse-Proxy (eigentlich eine recht häufige Lösung), wird die TCP-Verbindung zum Webserver tatsächlich vom Proxy hergestellt. Dies ist
$_SERVER['REMOTE_ADDR']
die IP des Proxys und nicht die IP des Clients, der die Anforderung ursprünglich gesendet hat.Die ursprüngliche Anforderungs-IP ist in solchen Fällen normalerweise als verfügbar
$_SERVER['HTTP_X_FORWARDED_FOR']
, aber einer der$_SERVER
Werte, die damit beginnenHTTP_
, ist nicht wirklich vertrauenswürdig.Wenn sich Ihr Webserver also hinter einem Reverse-Proxy 2 befindet ,
$_SERVER['REMOTE_ADDR']
wäre selbst dieser für einen solchen Schutz nicht nützlich, und eine domänenbasierte Whitelist könnte nur auf Proxy-Ebene implementiert werden.Kurz gesagt, eine zuverlässige Lösung für die API-Endpunktsicherung sollte entweder mithilfe eines echten Authentifizierungsmechanismus (z. B. oAuth) implementiert werden oder direkt auf der Serverkonfiguration und nicht auf Anwendungsebene erfolgen.
Anmerkungen
1 Nun, theoretisch könnte es kaputt gehen, wenn jemand Ihren ISP gehackt hat oder wenn ein Angreifer aus Ihrem LAN heraus agiert. In beiden Fällen können Sie nur sehr wenig tun, um sicher zu gehen.
2 Wenn Sie nicht wissen, ob Sie sich hinter einem Reverse-Proxy befinden, können Sie eine Anfrage von Ihrem lokalen PC senden und prüfen, ob
$_SERVER['REMOTE_ADDR']
auf dem Server die lokale PC-IP übereinstimmt und ob sie$_SERVER['HTTP_X_FORWARDED_FOR']
vorhanden ist und mit der lokalen PC-IP übereinstimmt.quelle