Como os cookies HttpOnly funcionam com solicitações AJAX?

195

O JavaScript precisa acessar os cookies se o AJAX for usado em um site com restrições de acesso baseadas em cookies. Os cookies HttpOnly funcionarão em um site AJAX?

Edit: A Microsoft criou uma maneira de impedir ataques XSS, proibindo o acesso do JavaScript aos cookies, se HttpOnly for especificado. Mais tarde, o FireFox adotou isso. Portanto, minha pergunta é: se você estiver usando o AJAX em um site, como o StackOverflow, os cookies somente HTTP são uma opção?

Edit 2: Question 2. Se o objetivo do HttpOnly é impedir o acesso do JavaScript aos cookies, e você ainda pode recuperá-los via JavaScript através do objeto XmlHttpRequest, qual é o objetivo do HttpOnly ?

Edit 3: Aqui está uma citação da Wikipedia:

Quando o navegador recebe um cookie, é suposto usá-lo normalmente nas trocas HTTP a seguir, mas não para torná-lo visível para os scripts do cliente. [32] O HttpOnlysinalizador não faz parte de nenhum padrão e não é implementado em todos os navegadores. Observe que atualmente não há prevenção de ler ou gravar o cookie da sessão por meio de um XMLHTTPRequest. [33]

Eu entendo que document.cookieestá bloqueado quando você usa o HttpOnly. Mas parece que você ainda pode ler os valores dos cookies no objeto XMLHttpRequest, permitindo o XSS. Como o HttpOnly o torna mais seguro que? Fazendo cookies essencialmente apenas para leitura?

No seu exemplo, não posso gravar no seu document.cookie, mas ainda posso roubar o seu cookie e publicá-lo no meu domínio usando o objeto XMLHttpRequest.

<script type="text/javascript">
    var req = null;
    try { req = new XMLHttpRequest(); } catch(e) {}
    if (!req) try { req = new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) {}
    if (!req) try { req = new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) {}
    req.open('GET', 'http://stackoverflow.com/', false);
    req.send(null);
    alert(req.getAllResponseHeaders());
</script>

Edição 4: Desculpe, eu quis dizer que você poderia enviar o XMLHttpRequest para o domínio StackOverflow e salvar o resultado de getAllResponseHeaders () em uma string, regexar o cookie e publicá-lo em um domínio externo. Parece que a Wikipedia e os ha.ckers concordam comigo nesse caso, mas eu adoraria ser reeducado ...

Edição final: Ahh, aparentemente os dois sites estão errados, isso é realmente um bug no FireFox . O IE6 e o ​​7 são, na verdade, os únicos navegadores que atualmente oferecem suporte total ao HttpOnly.

Para reiterar tudo o que aprendi:

  • O HttpOnly restringe todo o acesso ao document.cookie no IE7 e no FireFox (não tenho certeza sobre outros navegadores)
  • HttpOnly remove as informações de cookies dos cabeçalhos de resposta em XMLHttpObject.getAllResponseHeaders () no IE7.
  • O XMLHttpObjects pode ser enviado apenas ao domínio de origem, portanto, não há postagem entre os cookies.

editar: é provável que essas informações não estejam mais atualizadas.

Shawn
fonte
Dei seu exemplo em um script greasemonkey e parece que o FF não exibe mais cookies. Excelente pesquisa e exemplo.
Talvez com a mesma política de origem você não possa fazer uma solicitação http para um domínio que não seja o mesmo em que o script está sendo executado; no entanto, acredito que você poderia facilmente passar os cookies redirecionando o usuário para uma página usando window.location e passar todas as informações através dos parâmetros da string de consulta.
Luca Marzi
@LucaMarzi " você não pode fazer uma solicitação http para um domínio que não seja o mesmo em que o script está sendo executado " Você está dizendo que um site X não pode incluir uma imagem do host Y? (uma característica que tem sido apoiada por todos os navegadores desde Mosaic?)
curiousguy

Respostas:

64

Sim, cookies somente HTTP seriam adequados para essa funcionalidade. Eles ainda receberão a solicitação do XmlHttpRequest para o servidor.

No caso de estouro de pilha, os cookies são automaticamente fornecidos como parte da solicitação XmlHttpRequest. Não conheço os detalhes de implementação do provedor de autenticação Stack Overflow, mas esses dados de cookies provavelmente são usados ​​automaticamente para verificar sua identidade em um nível inferior ao método do controlador "vote".

De maneira mais geral, os cookies não são necessários para o AJAX. O suporte ao XmlHttpRequest (ou mesmo remoting iframe, em navegadores mais antigos) é tudo o que é tecnicamente necessário.

No entanto, se você deseja fornecer segurança para a funcionalidade habilitada para AJAX, as mesmas regras se aplicam aos sites tradicionais. Você precisa de algum método para identificar o usuário por trás de cada solicitação, e os cookies são quase sempre os meios para esse fim.

No seu exemplo, não posso gravar no seu document.cookie, mas ainda posso roubar o seu cookie e publicá-lo no meu domínio usando o objeto XMLHttpRequest.

O XmlHttpRequest não fará solicitações entre domínios (exatamente pelos tipos de motivos pelos quais você está abordando).

Normalmente, você pode injetar um script para enviar o cookie ao seu domínio usando iframe remoting ou JSONP, mas depois o HTTP-only protege o cookie novamente, pois está inacessível.

A menos que você tenha comprometido o StackOverflow.com no lado do servidor, não poderá roubar meu cookie.

Edit 2: Question 2. Se o objetivo do Http-Only é impedir o acesso do JavaScript aos cookies, e você ainda pode recuperá-los via JavaScript através do XmlHttpRequest Object, qual é o objetivo do Http-Only?

Considere este cenário:

  • Encontro uma via para injetar código JavaScript na página.
  • Jeff carrega a página e meu JavaScript malicioso modifica seu cookie para corresponder ao meu.
  • Jeff envia uma resposta excelente para sua pergunta.
  • Como ele envia os dados dos meus cookies em vez dos dele, a resposta se tornará minha.
  • Você votou na "minha" resposta estelar.
  • Minha conta real entende o ponto.

Com cookies Somente HTTP, a segunda etapa seria impossível, derrotando assim minha tentativa de XSS.

Edit 4: Desculpe, eu quis dizer que você poderia enviar o XMLHttpRequest para o domínio StackOverflow e salvar o resultado de getAllResponseHeaders () em uma string, regexar o cookie e publicá-lo em um domínio externo. Parece que a Wikipedia e os ha.ckers concordam comigo nesse caso, mas eu adoraria ser reeducado ...

Está correto. Você ainda pode sequestrar uma sessão dessa maneira. No entanto, reduz significativamente o rebanho de pessoas que podem executar com êxito mesmo esse XSS hackeado contra você.

No entanto, se você voltar para o meu cenário de exemplo, você pode ver onde HTTP-Only não cortar com sucesso os ataques XSS que dependem de modificar os cookies do cliente (não é incomum).

Ela resume-se ao fato de que a) nenhuma melhoria única vai resolver todas as vulnerabilidades e b) nenhum sistema vai sempre ser completamente seguro. Somente HTTP é uma ferramenta útil para apoiar o XSS.

Da mesma forma, mesmo que a restrição de domínio cruzado no XmlHttpRequest não tenha 100% de êxito na prevenção de todas as explorações de XSS, você ainda sonharia em remover a restrição.

Dave Ward
fonte
Muitas estruturas colocam csrf token em cookies . Suponho que a chamada AJAX que precisa de uma csrfverificação não funcione, a menos que você coloque o token csrf em um elemento HTML oculto para que o JS o recupere.
usuário
4

Não necessariamente, depende do que você quer fazer. Você poderia elaborar um pouco? O AJAX não precisa acessar os cookies para funcionar, ele pode fazer solicitações por conta própria para extrair informações, a solicitação de página que a chamada AJAX faz pode acessar os dados do cookie e repassá-los ao script de chamada sem que o Javascript precise acessar diretamente o biscoitos

Glenn Slaven
fonte
4

Sim, eles são uma opção viável para um site baseado em Ajax. Os cookies de autenticação não são para manipulação de scripts, mas são simplesmente incluídos pelo navegador em todas as solicitações HTTP feitas ao servidor.

Os scripts não precisam se preocupar com o que o cookie da sessão diz - desde que você seja autenticado, qualquer solicitação ao servidor iniciada por um usuário ou pelo script incluirá os cookies apropriados. O fato de os scripts não poderem conhecer o conteúdo dos cookies não importa.

Para quaisquer cookies usados ​​para outros fins que não a autenticação, eles podem ser configurados sem o sinalizador somente HTTP, se você desejar que o script possa modificá-los ou lê-los. Você pode escolher quais cookies devem ser apenas HTTP, portanto, por exemplo, qualquer coisa não sensível, como preferências da interface do usuário (ordem de classificação, recolhimento do painel esquerdo ou não), pode ser compartilhada nos cookies com os scripts.

Gosto muito dos cookies apenas HTTP - é uma daquelas extensões de navegador proprietárias que foi uma ideia realmente interessante.

thomasrutter
fonte
3

Há um pouco mais nisso.

O Ajax não exige estritamente cookies, mas eles podem ser úteis como outros pôsteres mencionaram. Marcar um cookie como HTTPOnly para ocultá-lo dos scripts funciona apenas parcialmente, porque nem todos os navegadores o suportam, mas também porque existem soluções comuns.

É estranho que os cabeçalhos XMLHTTPresponse estejam fornecendo o cookie, tecnicamente o servidor não precisa retornar o cookie com a resposta. Uma vez definido no cliente, ele permanece definido até expirar. Embora existam esquemas nos quais o cookie é alterado a cada solicitação para impedir a reutilização. Portanto, você pode evitar essa solução alternativa alterando o servidor para não fornecer o cookie nas respostas XMLHTTP.

Em geral, porém, acho que o HTTPOnly deve ser usado com cautela. Existem ataques de script entre sites nos quais um invasor solicita que um usuário envie uma solicitação do tipo Ajax originária de outro site, usando formulários de postagem simples, sem o uso de XMLHTTP, e o cookie ainda ativo do navegador autenticaria a solicitação.

Se você deseja ter certeza de que uma solicitação AJAX está autenticada, a própria solicitação E os cabeçalhos HTTP precisam conter o cookie. Por exemplo, através do uso de scripts ou entradas ocultas exclusivas. HTTPOnly impediria isso.

Geralmente, o motivo interessante para querer o HTTPOnly é impedir que o conteúdo de terceiros incluído na sua página da Web roube cookies. Mas há muitos motivos interessantes para ser muito cauteloso ao incluir conteúdo de terceiros e filtrá-lo de forma agressiva.

davenpcj
fonte
1

Os cookies são manipulados automaticamente pelo navegador quando você faz uma chamada AJAX; portanto, não é necessário que o seu Javascript mexa com os cookies.

pkchukiss
fonte
1

Portanto, estou assumindo que o JavaScript precisa acessar seus cookies.

Todas as solicitações HTTP do seu navegador transmitem suas informações de cookies para o site em questão. O JavaScript pode definir e ler cookies. Os cookies não são, por definição, necessários para aplicativos Ajax, mas são necessários para a maioria dos aplicativos Web manter o estado do usuário.

A resposta formal à sua pergunta foi formulada - "O JavaScript precisa acessar os cookies se o AJAX for usado?" - é, portanto, "não". Pense nos campos de pesquisa aprimorados que usam solicitações do Ajax para fornecer opções de sugestão automática, por exemplo. Não há necessidade de informações de cookies nesse caso.

Polsonby
fonte
XmlHttpRequest precisa de cookies. A pesquisa avançada que você mencionou pode estar atrás de uma página de login. Mas se o Javascript precisa ou não ser capaz de expor o valor do cookie à VM é uma questão diferente.
Sr. Shiny e New # 23/03/09
1

Como esclarecimento - da perspectiva do servidor, a página solicitada por uma solicitação AJAX não é essencialmente diferente de uma solicitação de obtenção HTTP padrão feita pelo usuário clicando em um link. Todas as propriedades normais da solicitação: user-agent, ip, session, cookies etc. são passadas para o servidor.

Glenn Slaven
fonte
A "sessão" não é um conceito HTTP. É um conceito de alto nível construído sobre conceitos HTTP por uma estrutura.
precisa
0

Não, a página solicitada pela chamada AJAX também tem acesso aos cookies e é isso que verifica se você está logado.

Você pode fazer outra autenticação com o Javascript, mas eu não confio nele, sempre prefiro colocar qualquer tipo de verificação de autenticação no back-end.

Glenn Slaven
fonte
0

Sim, os cookies são muito úteis para o Ajax.

Colocar a autenticação no URL de solicitação é uma prática recomendada. Na semana passada, houve um item de notícias sobre como obter os tokens de autenticação nos URLs a partir do cache do Google.

Não, não há como impedir ataques. Navegadores mais antigos ainda permitem acesso trivial a cookies via javascript. Você pode ignorar apenas o http etc. O que você criar pode ser contornado, com esforço suficiente. O truque é fazer muito esforço para valer a pena.

Se você deseja tornar seu site mais seguro (não há segurança perfeita), use um cookie de autenticação que expire. Então, se o cookie for roubado, o invasor deverá usá-lo antes de expirar. Caso contrário, você tem uma boa indicação de que há atividades suspeitas nessa conta. Quanto menor a janela de tempo, melhor a segurança, mas maior a carga que ele coloca no servidor, gerando e mantendo chaves.

Jay
fonte