@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:
- Richtiges Konfigurieren des Servers zum Generieren des
$_SERVER['REMOTE_HOST']
Werts (zum Beispiel in Apache, den Sie HostnameLookups On
in Ihrem benötigen httpd.conf
) dieses Werts
- Verwenden Sie
gethostbyaddr
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 beginnen HTTP_
, 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.