Déterminer le référent en PHP

102

Quel est le moyen le plus fiable et le plus sûr de déterminer quelle page a envoyé ou appelé (via AJAX) la page actuelle. Je ne veux pas utiliser le $_SERVER['HTTP_REFERER'], à cause du (manque de) fiabilité, et j'ai besoin que la page appelée ne provienne que de requêtes provenant de mon site.

Edit: Je cherche à vérifier qu'un script qui préforme une série d'actions est appelé à partir d'une page de mon site Web.

UnkwnTech
la source
5
Pourquoi dites-vous que $ _SERVER ['HTTP_REFERER'] n'est pas fiable?
Milan Babuškov
9
L'implémentation PHP est fiable. Le problème est que jamais le navigateur n'envoie cela, et vous pouvez même le modifier si vous le souhaitez. Ce n'est donc pas fiable que ce soit correct du côté du client.
Biri
2
Une manière possible est de mettre une clé unique (par exemple, un GUID) dans un champ de votre page, et de la renvoyer dans la requête suivante.
PhiLho
Découvrez l'adresse IP du serveur et son utilisation $_SERVER[REMOTE_ADDR].

Réponses:

93

Le REFERER est envoyé par le navigateur du client dans le cadre du protocole HTTP, et n'est donc pas fiable. Il peut ne pas être là, il peut être falsifié, vous ne pouvez pas lui faire confiance si c'est pour des raisons de sécurité.

Si vous souhaitez vérifier si une demande provient de votre site, eh bien, vous ne pouvez pas, mais vous pouvez vérifier que l'utilisateur a été sur votre site et / ou est authentifié. Les cookies sont envoyés dans les requêtes AJAX afin que vous puissiez vous y fier.

Seldaek
la source
5
Si vous souhaitez utiliser cette méthode, vous devez toujours vérifier le référent également pour empêcher CSRF en.wikipedia.org/wiki/Cross-site_request_forgery
JD Isaacks
17
Idéalement, vous devriez utiliser un jeton unique par session et par utilisateur (par requête si vous êtes paranoïaque) pour éviter les attaques CSRF. Vérifier le référent est juste une sécurité par obfuscation et pas tout à fait une vraie solution.
Seldaek
3
@Seldaek non, vérifier le référent n'est pas «sécurité par obfuscation». Un attaquant essayant d'effectuer une attaque CSRF ne peut pas contrôler le referer envoyé par le navigateur de la victime, afin de vérifier qu'il ne se protéger contre CSRF. Cependant, je maintiens votre conclusion selon laquelle vous devriez utiliser un jeton CSRF à la place, car l'approche de vérification des référents présente des inconvénients, notamment vous rendre vulnérable si vous avez une redirection ouverte sur votre site et interrompre les agents utilisateurs qui suppriment le référent.
Mark Amery
@MarkAmery tout dépend de ce contre quoi vous essayez de vous défendre, bien sûr, mais l'utilisation d'en-têtes http spécifiques au client n'est généralement pas un modèle de sécurité très solide.
Seldaek
23

Ce que j'ai trouvé le mieux est un jeton CSRF et enregistrez-le dans la session pour les liens où vous devez vérifier le référent.

Donc, si vous générez un rappel FB, cela ressemblerait à ceci:

$token = uniqid(mt_rand(), TRUE);
$_SESSION['token'] = $token;
$url = "http://example.com/index.php?token={$token}";

Ensuite, l'index.php ressemblera à ceci:

if(empty($_GET['token']) || $_GET['token'] !== $_SESSION['token'])
{
    show_404();
} 

//Continue with the rest of code

Je connais des sites sécurisés qui font l'équivalent de cela pour toutes leurs pages sécurisées.

We0
la source
1
Voici un lien pour en savoir plus sur les jetons CSRF: en.wikipedia.org/wiki/Cross-site_request_forgery
We0
7
Etes-vous sûr que c'est le cas $_GET['token'] == $_SESSION['token']et non $_GET['token'] !== $_SESSION['token']?
Timo Huovinen
17

Utilisation de $ _SERVER ['HTTP_REFERER']

L'adresse de la page (le cas échéant) qui a référé l'agent utilisateur à la page en cours. Ceci est défini par l'agent utilisateur. Tous les agents utilisateurs ne le définiront pas, et certains offrent la possibilité de modifier HTTP_REFERER en tant que fonctionnalité. En bref, on ne peut pas vraiment y faire confiance.

if (!empty($_SERVER['HTTP_REFERER'])) {
    header("Location: " . $_SERVER['HTTP_REFERER']);
} else {
    header("Location: index.php");
}
exit;
Lawrence Cherone
la source
0

Il n'existe aucun moyen fiable de vérifier cela. C'est vraiment sous la main du client de vous dire d'où il vient. Vous pourriez imaginer utiliser des cookies ou des informations de session placées uniquement sur certaines pages de votre site Web, mais cela briserait l'expérience utilisateur avec les signets.

gadget
la source
0

Il ne nous reste qu'une seule option après avoir lu tous les faux problèmes de référent: c'est-à-dire que la page que nous souhaitons suivre en tant que référent doit être conservée en session, et comme ajax est appelée, vérifiez en session si elle a une valeur de page de référent et faites l'action autrement non action.

Alors que, d'autre part, il demande une page différente, puis rendez la valeur de session du référent à null.

N'oubliez pas que la variable de session est définie uniquement sur la demande de page souhaitée.

justnajm
la source