Utilisation de WP 4.8.2
Quelle est la meilleure façon de vérifier l'URL demandeuse lors du traitement d'une demande avec l'api rest?
Par exemple, un site reçoit une demande et vous souhaitez vérifier si elle provient d'une URL «autorisée». Et échouez si l'URL n'est pas autorisée.
Cela ne fonctionne pas:
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
et$url
vars ressembler viavar_dump
ou similaire, je trouve que l' inspection des entrées et sorties conduisent toujours à une réponse appropriée.Réponses:
Ce filtre n'est certainement pas celui que vous recherchez. Ce filtre se déclenche avant de renvoyer le résultat
WP_REST_Request::from_url()
qui semble être une méthode d'usine qui n'est utilisée qu'en interne pour gérer les incorporations.Une meilleure option consiste à renvoyer une
WP_Error
instance sur lerest_pre_dispatch
filtre .Quelques mises en garde:
Comme mentionné par @milo, le référent n'est pas fiable et ne doit pas être utilisé pour un contrôle de sécurité.
De plus, il n'est pas garanti d'être réglé.
Avec ceux-ci à l'écart, voici un exemple de la façon dont vous pouvez utiliser le
rest_pre_dispatch
filtre pour provoquer l'échec de la demande si elle provient d'un mauvais référent:la source
Tout ce que vous recevez du client est considéré comme une entrée utilisateur et ne doit pas être approuvé. Comme l'en-tête peut être facilement manipulé et abusé, ma suggestion est de ne pas utiliser cette méthode si vous vous en remettez à des données sensibles.
Si les demandes proviennent d'une page, vous pouvez avoir une autre approche. Sinon, n'importe qui peut envoyer une demande à l'API de nulle part et modifier le référent.
Supposons que vous ayez un tas de pages filtrées comme "Autorisées" . Vous pouvez créer un nom uniquement pour ces pages, puis les valider dans votre demande.
Si un substantif existe et est valide, la demande est autorisée. Sinon, bloquez-le.
la source
La réponse de @ssnepenthe a raison de dire que le crochet que vous utilisez n'est pas le bon dans la demande entrante.
Les informations de demande sont immédiatement disponibles pour PHP, vous pouvez donc utiliser le premier crochet disponible pour les vérifier. Et si vous souhaitez le faire dans le contexte de l'API de demande, vous devez utiliser le premier crochet d'une demande d'API REST.
'rest_pre_dispatch'
suggéré par @ssnepenthe est très bien, peut-être une autre option pourraitrest_authentication_errors
vous permettre de retourner une erreur en cas de problème.Mais Jack Johansson a raison de dire que les en-têtes HTTP (comme l'en-tête de référence utilisé dans l'aswer de @ ssnepenthe) ne sont pas fiables, car ils sont très facilement modifiés par le client. Donc, ce serait comme mettre un gardien de sécurité devant une porte qui demande simplement "c'est sûr de vous laisser entrer?" à tous ceux qui veulent y entrer: ça ne marchera pas.
Mais la solution proposée par Jack Johansson (un nonce) n'est pas non plus une vraie solution: tout le point des nonces est de changer avec le temps, et un point de terminaison API public ne peut pas avoir des choses qui changent en fonction du temps. De plus, les nonces WP ne sont fiables que lorsqu'il y a un utilisateur connecté, ce qui peut ne pas être le cas pour une API publique et si un utilisateur est connecté, il n'y a probablement aucune raison de vérifier le domaine entrant: vous faites confiance à l'utilisateur, pas au machine utilisateur.
Alors que faire?
Eh bien, même si les en-têtes HTTP ne sont pas fiables, toutes les informations disponibles ne
$_SERVER
proviennent pas des en-têtes.Normalement, toutes les
$_SERVER
valeurs dont les clés commencent par qui commencentHTTP_
proviennent d'en-têtes et doivent être traitées comme des entrées utilisateur non sécurisées .Mais, par exemple,
$_SERVER['REMOTE_ADDR']
contient l'adresse IP utilisée pour la connexion TCP à votre serveur, ce qui signifie qu'elle est fiable 1 .Ce qui signifie également que:
$_SERVER['REMOTE_HOST']
valeur (par exemple dans Apache dont vous aurez besoinHostnameLookups On
dans votrehttpd.conf
) cette valeurgethostbyaddr
pour effectuer une recherche DNS inversée pour résoudre le nom de domaine de l'adresse IP stockée dans$_SERVER['REMOTE_ADDR']
vous pourriez obtenir assez fiable un nom d'hôte que vous pouvez utiliser pour vérifier contre un whitelist (pour le code, vous pouvez adapter le code de @ la aswer de ssnepenthe où vous devez remplacer
$referer = $request->get_header('referer')
par$referer = gethostbyaddr($_SERVER['REMOTE_ADDR'])
).Mais il y a un problème .
Si votre serveur Web se trouve derrière un proxy inverse (solution assez courante, en fait), la connexion TCP au serveur Web est en fait établie par le proxy, ainsi
$_SERVER['REMOTE_ADDR']
sera l'IP du proxy, et non l'IP du client qui a initialement envoyé la demande.Dans de tels cas, l'IP de requête d'origine est généralement disponible en tant que
$_SERVER['HTTP_X_FORWARDED_FOR']
, mais être l'une de ces$_SERVER
valeurs qui commencent parHTTP_
n'est pas vraiment fiable.Donc, si votre serveur Web est derrière un proxy inverse 2, même le
$_SERVER['REMOTE_ADDR']
ne serait pas utile pour une telle garde et une liste blanche basée sur le domaine ne pourrait être implémentée qu'au niveau du proxy.En bref, une solution fiable pour la sécurisation des points de terminaison de l'API doit être implémentée à l'aide d'un mécanisme d'authentification réel (par exemple oAuth) ou doit être effectuée en agissant directement sur la configuration du serveur et non au niveau de l'application.
Remarques
1 Eh bien, en théorie, cela pourrait être cassé si quelqu'un piratait votre FAI ou si un attaquant agissait de l'intérieur de votre réseau local, dans les deux cas, vous ne pouviez pas faire grand-chose pour être en sécurité.
2 Si vous ne savez pas si vous êtes derrière un proxy inverse, vous pouvez envoyer une demande à partir de votre PC local et vérifier si
$_SERVER['REMOTE_ADDR']
le serveur correspond à l'IP du PC local et également s'il$_SERVER['HTTP_X_FORWARDED_FOR']
est présent et correspond à l'IP du PC local.la source