Token CSRF necessário ao usar a autenticação sem estado (= sem sessão)?

125

É necessário usar a proteção CSRF quando o aplicativo depende da autenticação sem estado (usando algo como HMAC)?

Exemplo:

  • Temos um único aplicativo página (caso contrário, temos de acrescentar o token em cada link: <a href="...?token=xyz">...</a>.

  • O usuário se autentica usando POST /auth. Na autenticação bem-sucedida, o servidor retornará algum token.

  • O token será armazenado via JavaScript em alguma variável dentro do aplicativo de página única.

  • Este token será usado para acessar URLs restritos como /admin.

  • O token sempre será transmitido dentro de cabeçalhos HTTP.

  • Não há sessão Http e cookies.

Pelo que entendi, não deveria (?!) haver possibilidade de usar ataques entre sites, porque o navegador não armazena o token e, portanto, não pode enviá-lo automaticamente ao servidor (é o que aconteceria ao usar Cookies / Sessão).

Estou esquecendo de algo?

Benjamin M
fonte
6
Tenha cuidado com a autenticação básica. Muitos navegadores enviarão automaticamente os cabeçalhos de autenticação básicos para o restante da sessão. Isso pode tornar a autenticação básica tão vulnerável ao CSRF quanto a autenticação de cookie.
Phylae

Respostas:

159

Encontrei algumas informações sobre o CSRF + sem usar cookies para autenticação:

  1. https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/
    "como você não depende de cookies, não precisa se proteger contra solicitações entre sites"

  2. http://angular-tips.com/blog/2014/05/json-web-tokens-introduction/
    "Se seguirmos o caminho dos cookies, você realmente precisará executar o CSRF para evitar solicitações entre sites. Isso é algo que podemos esqueça ao usar o JWT como você verá. "
    (JWT = Json Web Token, uma autenticação baseada em token para aplicativos sem estado)

  3. http://www.jamesward.com/2013/05/13/securing-single-page-apps-and-rest-services
    "A maneira mais fácil de fazer autenticação sem arriscar vulnerabilidades do CSRF é simplesmente evitar o uso de cookies para identificar o usuário "

  4. http://sitr.us/2011/08/26/cookies-are-bad-for-you.html
    "O maior problema com o CSRF é que os cookies não oferecem absolutamente nenhuma defesa contra esse tipo de ataque. Se você estiver usando autenticação de cookies você também deve empregar medidas adicionais para se proteger contra o CSRF. A precaução mais básica que você pode tomar é garantir que seu aplicativo nunca realize efeitos colaterais em resposta a solicitações GET ".

Existem muitas outras páginas, que afirmam que você não precisa de nenhuma proteção CSRF, se você não usa cookies para autenticação. É claro que você ainda pode usar cookies para todo o resto, mas evite armazenar qualquer coisa session_iddentro dele.


Se você precisar se lembrar do usuário, existem 2 opções:

  1. localStorage: Um armazenamento de valores-chave no navegador. Os dados armazenados estarão disponíveis mesmo após o usuário fechar a janela do navegador. Os dados não são acessíveis por outros sites, porque cada site recebe seu próprio armazenamento.

  2. sessionStorage: Também um repositório de dados do navegador. A diferença é: Os dados são excluídos quando o usuário fecha a janela do navegador. Mas ainda é útil se o seu aplicativo da web consistir em várias páginas. Então você pode fazer o seguinte:

    • O usuário efetua login e, em seguida, você armazena o token sessionStorage
    • O usuário clica em um link, que carrega uma nova página (= um link real e nenhuma substituição de conteúdo javascript)
    • Você ainda pode acessar o token em sessionStorage
    • Para sair, você pode excluir manualmente o token sessionStorageou aguardar que o usuário feche a janela do navegador, o que limpará todos os dados armazenados.

(para ambos, dê uma olhada aqui: http://www.w3schools.com/html/html5_webstorage.asp )


Existem padrões oficiais para autenticação de token?

JWT (Json Web Token): Acho que ainda é um rascunho, mas já é usado por muitas pessoas e o conceito parece simples e seguro. (IETF: http://tools.ietf.org/html/draft-ietf-oauth-json-web-token-25 )
Também existem bibliotecas para muitos frameworks disponíveis. Basta pesquisar no google!

Benjamin M
fonte
37
Grande resumo sobre CSRF! Observarei que o armazenamento de seus tokens no localStorage ou sessionStorage é vulnerável a ataques XSS e que os dados podem ser visualizados por scripts na página - portanto, se você tiver um script comprometido servido por uma CDN ou se houver código malicioso em um dos seus Bibliotecas JS, eles podem roubar o token desses locais de armazenamento. Consulte: stormpath.com/blog/… Acho que a abordagem mais segura é armazenar um token JWT + CSRF no cookie e, em seguida, coloque seu JWT computado com o token CSRF dentro dele no cabeçalho da solicitação.
Aaron Gray
Em relação a: "A precaução mais básica que você pode tomar é garantir que seu aplicativo nunca realize efeitos colaterais em resposta a solicitações GET". É possível que um ataque de CSRF falsifique uma solicitação POST?
Costa
Dependendo da aplicação do servidor, PODE ser possível. Existem frameworks Web, que usam algo parecido http://.../someRestResource?method=POST. Portanto, é basicamente uma GETsolicitação, mas o Aplicativo de Servidor a interpreta como uma POSTsolicitação, porque foi configurado para usar o methodparâmetro em vez do cabeçalho HTTP. ...Em relação aos navegadores da Web comuns, eles aplicam a mesma política de origem e só executam GETsolicitações para servidores estrangeiros. Embora possa ser possível executar POSTsolicitações se o navegador da web não aplicar esses padrões da web (bug, malware).
Benjamin M
1
Além do Server Side App: ainda não é possível enviar um corpo de solicitação, porque os navegadores comuns não permitem isso. No entanto, se o Aplicativo do servidor permitir method=POST, ele também poderá body={someJson}substituir o corpo da solicitação padrão. É um projeto de API muito ruim e extremamente arriscado. No entanto, se o aplicativo do servidor permitir, http://...?method=POST&body={someJson}você deve realmente pensar demais no que fez lá e por que e se for necessário. (Eu diria que em 99,9999% dos casos é não necessário). Além disso, os navegadores podem enviar apenas alguns kilobytes dessa maneira.
Benjamin M
O @BenjaminM notou que a mesma política de origem impede o código javaScript de acessar o resultado; portanto, enquanto a solicitação é "bloqueada", ela realmente chega ao servidor - jsbin.com/mewaxikuqo/edit?html,js,output Eu testei isso apenas no Firefox, mas você pode abrir as ferramentas de desenvolvimento e ver que, mesmo que você receba "Solicitação de origem cruzada", o servidor remoto realmente vê toda a solicitação. é por isso que você deve ter fichas ou cabeçalhos personalizados (e se possível ambos) para todas as suas solicitações POST
Yoni Jah
59

TL; DR

Um JWT, se usado sem cookies, nega a necessidade de um token CSRF - MAS! armazenando o JWT em session / localStorage, você expõe o JWT e a identidade do usuário se o site tiver uma vulnerabilidade XSS (bastante comum). É melhor adicionar uma csrfTokenchave para a JWT e armazenar a JWT em um cookie com securee http-onlyconjunto de atributos.

Leia este artigo com uma boa descrição para obter mais informações https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage

Você pode tornar essa proteção CSRF sem estado incluindo uma reivindicação xsrfToken JWT:

{ "iss": "http://galaxies.com", "exp": 1300819380, "scopes": ["explorer", "solar-harvester", "seller"], "sub": "[email protected]", "xsrfToken": "d9b9714c-7ac0-42e0-8696-2dae95dbc33e" }

Portanto, você precisará armazenar o csrfToken em localStorage / sessionStorage, bem como no próprio JWT (que é armazenado em um cookie seguro apenas para http). Em seguida, para proteção csrf, verifique se o token csrf no JWT corresponde ao cabeçalho csrf-token enviado.

Scott Jungwirth
fonte
2
Deve-se isentar o uso do token csrf durante a autenticação da API pelo usuário?
user805981
3
Vale ressaltar (como outros também mencionaram nos comentários no link de origem) que qualquer atenuação do CSRF que use a) cookies, que não são apenas http ou b) armazena o token CSRF no armazenamento local é vulnerável ao XSS. Isso significa que a abordagem apresentada pode ajudar a manter o JWT secreto de um invasor usando XSS, mas um invasor ainda poderá executar uma solicitação maliciosa na sua API porque ele pode fornecer uma JWT válida (por meio do cookie, navegador de agradecimento) e token CSRF (lido via JS injetado do armazenamento / cookie local).
Johannes Rudolph
1
Na verdade, mesmo um token CSRF não pode protegê-lo neste nível de XSS, pois você supõe que o invasor possa acessar localStorage, que atualmente é a única maneira de acessar o acesso a nível de script, que pode ser visto de qualquer maneira no token CSRF .
itsnotvalid
1
Não é isso que @JohannesRudolph estava dizendo? Assim que você armazena o token CSRF no cookie Web Storage / não apenas http, você aumenta sua presença em um ataque XSS, porque eles são acessíveis via JS.
precisa saber é o seguinte
1
Não é um especialista total aqui, mas se você ainda está exposto ao XSS como era no começo, não tenho certeza da parte que é melhor adicionar ... realmente vale. Provavelmente, é um pouco (?) Mais complicado para um invasor obter o token CSRF, mas no final ele ainda pode executar uma solicitação em seu nome, mesmo sem conhecer o token JWT. Isso está correto? Obrigado
superjos