La risposta di @ssnepenthe ha ragione nel dire che l'hook che stai usando non è quello giusto nella richiesta in arrivo.
Le informazioni sulla richiesta sono immediatamente disponibili per PHP, quindi è possibile utilizzare il primo hook disponibile per verificarle. E se vuoi farlo nel contesto dell'API di richiesta, dovresti usare il primo hook di una richiesta API REST. 'rest_pre_dispatch'
suggerito da @ssnepenthe va bene, forse un'altra opzione potrebbe essere rest_authentication_errors
che ti consentirebbe di restituire un errore nel caso in cui qualcosa non va.
Ma Jack Johansson ha ragione nel dire che le intestazioni HTTP (come l'intestazione di riferimento usata nella risposta di @ssnepenthe) non sono affidabili, in quanto possono essere facilmente cambiate dal client. Quindi sarebbe come mettere una guardia di sicurezza davanti a una porta che chiede semplicemente "è sicuro di farti entrare?" a chiunque voglia entrare: non funzionerà.
Ma la soluzione proponeva che la risposta di Jack Johansson (un nonce) non fosse nemmeno una vera soluzione: l'intero punto delle nonces è cambiare con il tempo e un endpoint pubblico dell'API non può avere cose che cambiano in base al tempo. Inoltre, le nonces WP sono affidabili solo quando c'è un utente connesso, il che potrebbe non essere il caso di un'API pubblica e se un utente ha effettuato l'accesso, probabilmente non c'è motivo di controllare il dominio in arrivo: ti fidi dell'utente, non del macchina dell'utente.
Quindi che si fa?
Bene, anche se le intestazioni HTTP non sono affidabili, non tutte le informazioni disponibili $_SERVER
provengono dalle intestazioni.
Normalmente, tutti i $_SERVER
valori le cui chiavi iniziano con cui inizia HTTP_
provengono dalle intestazioni e devono essere trattati come input dell'utente non sicuro .
Ma, ad esempio, $_SERVER['REMOTE_ADDR']
contiene l'indirizzo IP utilizzato per la connessione TCP al server, il che significa che è affidabile 1 .
Il che significa anche che:
- configurando correttamente il server per generare il
$_SERVER['REMOTE_HOST']
valore (ad esempio in Apache ti servirà HostnameLookups On
all'interno del tuo httpd.conf
) quel valore
- usando
gethostbyaddr
per fare una ricerca DNS inversa per risolvere il nome di dominio dell'IP memorizzato in$_SERVER['REMOTE_ADDR']
si potrebbe ottenere molto affidabile un nome host che si potrebbe usare per controllare contro una whitelist (per il codice, è possibile adattare il codice da @ di ssnepenthe risponderti in cui si desidera sostituirlo $referer = $request->get_header('referer')
con $referer = gethostbyaddr($_SERVER['REMOTE_ADDR'])
).
Ma c'è un problema .
Se il tuo server web si trova dietro un proxy inverso (soluzione abbastanza comune, in realtà) la connessione TCP al server web viene effettivamente effettuata dal proxy, quindi $_SERVER['REMOTE_ADDR']
sarà l'IP del proxy e non l'IP del client che ha originariamente inviato la richiesta.
L'IP di richiesta originale in questi casi è solitamente disponibile come $_SERVER['HTTP_X_FORWARDED_FOR']
, ma essendo uno di quei $_SERVER
valori che iniziano con HTTP_
esso non è veramente affidabile.
Quindi, se il tuo server web è dietro un proxy inverso 2, anche $_SERVER['REMOTE_ADDR']
questo non sarebbe utile per tale protezione e una whitelist basata su dominio potrebbe essere implementata solo a livello di proxy.
In breve, una soluzione affidabile per la protezione degli endpoint API dovrebbe essere implementata utilizzando un meccanismo di autenticazione reale (ad esempio oAuth) o dovrebbe essere eseguita agendo direttamente sulla configurazione del server e non a livello di applicazione.
Appunti
1 Beh, in teoria potrebbe essere rotto se qualcuno ha violato il tuo ISP o se un attaccante agisce dall'interno della tua LAN, in entrambi i casi c'è molto poco che potresti fare per essere al sicuro.
2 Se non si sa se si è dietro un proxy inverso, è possibile inviare una richiesta dal PC locale e verificare se $_SERVER['REMOTE_ADDR']
sul server corrisponde l'IP del PC locale e anche se $_SERVER['HTTP_X_FORWARDED_FOR']
è presente e corrisponde all'IP del PC locale.