Determinando Referer em PHP

102

Qual é a maneira mais confiável e segura de determinar qual página enviou ou chamou (via AJAX) a página atual. Não quero usar o $_SERVER['HTTP_REFERER'], por causa da (falta de) confiabilidade, e preciso que a página que está sendo chamada venha apenas de solicitações originadas em meu site.

Editar: estou procurando verificar se um script que realiza uma série de ações está sendo chamado de uma página em meu site.

UnkwnTech
fonte
5
Por que você diz que $ _SERVER ['HTTP_REFERER'] não é confiável?
Milan Babuškov,
9
A implementação do PHP é confiável. O problema é que nem mesmo o navegador está enviando isso, e você pode até modificá-lo se quiser. Portanto, não é confiável que esteja correto do lado do cliente.
Biri,
2
Uma maneira possível é colocar uma chave exclusiva (por exemplo, um GUID) em um campo da sua página e enviá-la de volta na próxima solicitação.
PhiLho,
Descubra o endereço IP do servidor e use $_SERVER[REMOTE_ADDR].

Respostas:

93

O REFERER é enviado pelo navegador do cliente como parte do protocolo HTTP e, portanto, não é confiável. Pode não estar lá, pode ser forjado, você simplesmente não pode confiar nele por razões de segurança.

Se você deseja verificar se uma solicitação está vindo do seu site, você não pode, mas pode verificar se o usuário acessou o seu site e / ou está autenticado. Os cookies são enviados em solicitações AJAX para que você possa confiar nisso.

Seldaek
fonte
5
Se quiser usar este método, você ainda deve verificar o referenciador também para evitar CSRF en.wikipedia.org/wiki/Cross-site_request_forgery
JD Isaacks
17
O ideal é usar um token exclusivo por sessão por usuário (por solicitação, se você for paranóico) para evitar ataques CSRF. Verificar o referenciador é apenas segurança por ofuscação e não é uma solução real.
Seldaek
3
@Seldaek não, verificar o referenciador não é 'segurança por ofuscação'. Um atacante tentando executar um ataque CSRF não pode controlar o referer enviado pelo navegador da vítima, de modo a verificar- faz proteger contra CSRF. No entanto, vou manter sua conclusão de que você deve usar um token CSRF em vez disso, uma vez que a abordagem de verificação de referenciador tem desvantagens, incluindo deixá-lo vulnerável se você tiver um redirecionamento aberto em seu site e interromper para agentes de usuário que retiram o referenciador.
Mark Amery
@MarkAmery, tudo depende do que você está tentando se defender, é claro, mas usar cabeçalhos http específicos do cliente em geral não é um modelo de segurança muito forte.
Seldaek de
23

O que eu encontrei melhor é um token CSRF e salve-o na sessão para links onde você precisa verificar o referenciador.

Portanto, se você estiver gerando um retorno de chamada FB, será algo assim:

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

Então o index.php ficará assim:

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

//Continue with the rest of code

Eu conheço sites seguros que fazem o equivalente a isso para todas as suas páginas seguras.

Nós0
fonte
1
Aqui está um link para mais informações sobre tokens CSRF: en.wikipedia.org/wiki/Cross-site_request_forgery
We0
7
Tem certeza que sim $_GET['token'] == $_SESSION['token']e não $_GET['token'] !== $_SESSION['token']?
Timo Huovinen
17

Usando $ _SERVER ['HTTP_REFERER']

O endereço da página (se houver) que direcionou o agente do usuário para a página atual. Isso é definido pelo agente do usuário. Nem todos os agentes de usuário definirão isso e alguns fornecem a capacidade de modificar HTTP_REFERER como um recurso. Em suma, não se pode realmente confiar nele.

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

Não existe uma maneira confiável de verificar isso. Está realmente nas mãos do cliente para lhe dizer de onde veio. Você poderia imaginar o uso de cookies ou informações de sessões colocadas apenas em algumas páginas do seu site, mas fazer isso quebraria a experiência do usuário com os favoritos.

gizmo
fonte
0

Só nos resta uma única opção depois de ler todos os problemas de referência falsa: ou seja, a página que desejamos rastrear como referenciador deve ser mantida na sessão, e como ajax chamado, em seguida, verificar na sessão se ela tem o valor da página referenciadora e fazer a ação de outra forma, não açao.

Por outro lado, quando ele solicita qualquer página diferente, torne o valor da sessão do referenciador nulo.

Lembre-se de que a variável de sessão é definida apenas na solicitação da página de desejo.

Justnajm
fonte