Estou com excesso de engenharia se considerar erros intencionais do usuário?

12

É um excesso de engenharia se eu adicionar proteção contra as ações intencionais de um usuário (para dizer o mínimo), se o dano que o usuário pode incorrer não está relacionado ao meu código?

Para esclarecer, estou expondo um serviço JSON RESTful simples como este:

GET /items - to retrieve list of user's items
PUT /items/id - to modify an item
POST /items - to add a new item

O serviço em si não se destina a ser usado através de um navegador, mas apenas a partir de aplicativos de terceiros, controlados pelo usuário (como aplicativos de telefone, aplicativo de desktop etc.). Além disso, o serviço em si deve ser sem estado (ou seja, sem sessão).

A autenticação é feita com autenticação básica sobre SSL.

Estou falando de um possível comportamento "prejudicial" como este:

O usuário digita o URL GET em um navegador (sem motivo, mas ...). O navegador solicita a autenticação básica, processa-a e armazena a autenticação para a sessão de navegação atual. Sem fechar o navegador, o usuário visita um site mal-intencionado, que possui um javascript CSRF / XSRF malicioso que faz um POST para o nosso serviço.

O cenário acima é altamente improvável e sei que, do ponto de vista comercial, não devo me preocupar muito. Mas, para melhorar a situação, você acha que, se o nome de usuário / senha também forem necessários nos dados do JSON POST, isso ajudará?

Ou devo abandonar completamente a autenticação básica, livrar-me do GET e usar apenas POST / PUT com informações de autorização? Como as informações recuperadas através do GET também podem ser sensíveis.

Por outro lado, o uso de cabeçalhos personalizados considerou a implementação REST pura? Posso largar a autenticação básica e usar cabeçalhos personalizados. Dessa forma, pelo menos o ataque CSRF de um navegador pode ser evitado, e os aplicativos que usam o serviço definirão o nome de usuário / senha no heather personalizado. O que é ruim para essa abordagem é que agora o serviço não pode ser consumido a partir de um navegador.

Ensolarado
fonte
3
Assim como com a minha resposta, eu também gostaria de deixar essa declaração, acho que provavelmente seria melhor respondida em SO ou em segurança
#
1
Eu acho que você mudou PUT e POST conforme definido pela RFC 2616 ( tools.ietf.org/html/rfc2616#section-9.5 ).
Svante

Respostas:

6

Excesso de engenharia? De modo nenhum. As medidas anti-XSRF são uma parte necessária de qualquer aplicativo ou serviço da Web seguro. Pode ou não ser "altamente improvável" alguém escolher atacá-lo, mas isso não torna o seu software menos inseguro.

Os sistemas geralmente são atacados usando o XSRF e, embora os resultados sejam menos imediatos - obviamente ruins do que a injeção de SQL ou o XSS, eles são ruins o suficiente para comprometer todos os recursos interativos do usuário.

Isso significa que você não pode ter uma interface RESTful "pura", onde os únicos parâmetros são as propriedades da própria chamada. Você deve incluir algo na solicitação que um invasor não conseguiu adivinhar. Isso poderia ser o par nome de usuário por senha, mas que está longe de ser a única escolha possível. Você pode ter o nome de usuário e o token gerados a partir de um hash salgado da senha. Você pode ter tokens emitidos pelo próprio serviço no momento da autenticação (que pode ser lembrado na sessão ou verificado criptograficamente).

devo me livrar do GET

Não, as solicitações GET são usadas para solicitações de leitura que não possuem operação de gravação ativa (elas são "idempotentes"). São apenas operações de gravação que exigem proteção XSRF.

bobince
fonte
E se a solicitação GET puder revelar informações confidenciais?
21811 Sunny
@ Sunny: O que você está considerando dados sensíveis?
Chris
2
Chris, se eu ficar paranóico, todos os dados são sensíveis, se forem recebidos pelo usuário "errado" :). É teórico.
Sunny
pls, reveja as alterações na pergunta que adicionei.
Sunny
1
É bom que a resposta (GET ou outro método) contenha dados que apenas o usuário deve ver. Um ataque XSRF apenas permite que o invasor faça com que o usuário faça uma solicitação específica, não permite que ele leia a resposta que volta dessa solicitação. A menos que o script de destino seja construído de uma maneira especial para permitir que páginas de terceiros o leiam de uma <script>tag, deliberadamente (“JSONP”) ou acidentalmente ( JSON desprotegido ).
bobince
32

Nunca confie em nada. Toda solicitação é um ataque. Todo usuário é um hacker. Se você desenvolver com essa mentalidade, seu aplicativo será muito mais seguro, estável e menos propenso a ser invadido por um usuário mal-intencionado. Basta uma pessoa inteligente para encontrar uma maneira de contornar sua segurança para que você esteja com sérios problemas com seus dados (um dos recursos mais valiosos ).

Se você identificou uma falha de segurança no seu aplicativo, faça tudo o que achar necessário para preencher a lacuna. Sua API, em especial, deve ser o software menos confiável que existe. Eu exigiria as credenciais e aceitaria solicitações de postagem.

Jarrod Nettles
fonte
4
YAY pela paranóia! Você tem inimigos! (E um para cada pedido é um ataque )
Treb
0

Se o código for estabelecido e mantido, os casos extremos devem ser analisados ​​e tratados caso a caso.

CORRIGIDO POR ALGUNS ERROS NA MINHA PARTE:

GET ainda deve ser usado como parte de um serviço RESTful adequado; a autenticação ainda deve estar presente em qualquer caso. O que eu estava tentando supor era que, para fins de segurança, GET é o mesmo que POST, mas o post faz seu trabalho sem colocar as informações em uma barra de endereços, o que tende a ser a grande diferença de segurança (e por que eu não gosto de GET), mas como postado por @Lee,

GET requests are used to retrieve resources, and PUT/POST are used to add/update 
resources so it would be completely against expectations for a RESTful API to use
PUT/POST to get data. 

Como isso será usado por aplicativos de terceiros, deve-se seguir as boas práticas para um serviço RESTful, para que o implementador final não fique confuso nessa parte.

Jeff Langemeier
fonte
3
Como o GET difere do POST em termos de segurança? Ambos são enviados sem formatação pelo transporte (HTTP ou HTTPS), a única diferença é que as strings de consulta GET são visíveis na barra de endereço.
tdammers
1
@ Sunny: POST é tão exposto quanto GET a este respeito. Ligue o telnet e converse com um servidor da web, se você não acredita em mim.
tdammers
1
@ Jeff: A razão pela qual estou trazendo o telnet (ou curl, wget ou um bom sniffer antiquado) é que ele permite que você veja o fluxo de dados completo. Sim, o HTTPS oculta essas informações aos bisbilhoteiros, mas qualquer pessoa em qualquer extremidade da conexão SSL pode ver exatamente o que o telnet vê.
tdammers
1
@ Jeremy: O POST não mostra os parâmetros na barra de endereço, mas como os dados são visíveis no fluxo HTTP real, você está certo no geral.
tdammers
7
As solicitações GET são usadas para recuperar recursos e PUT / POST é usado para adicionar / atualizar recursos, portanto seria totalmente contra as expectativas de uma API RESTful usar PUT / POST para obter dados.
Lee
0

Você deve considerar todas as eventualidades plausíveis, incluindo o usuário ativamente malicioso e (com êxito) a engenharia reversa de quaisquer barreiras de "segurança pela obscuridade".

Mas, ao mesmo tempo, você deve avaliar o impacto de um hack de sucesso e a probabilidade de uma tentativa ocorrer. Por exemplo:

  • É menos provável que um serviço interno protegido por um firewall sólido seja sujeito a ataques do que um serviço na Internet pública.

  • O impacto de alguém derrubar um fórum de discussão de clientes é menor do que o roubo de cartões de crédito de clientes.


Meu argumento é que a "segurança total" é "infinitamente cara" ... e praticamente inatingível. Idealmente, você deve tomar suas decisões sobre onde traçar a linha com base em uma análise completa de custo-benefício.

Stephen C
fonte
Obrigado. A questão não era proteger "do" usuário, mas proteger o próprio usuário se agir de forma irresponsável. Mas sua resposta faz alguns bons pontos.
21911 Sunny