Fundo:
Estou projetando o esquema de autenticação para um serviço web REST. Isso "realmente" não precisa ser seguro (é mais um projeto pessoal), mas quero torná-lo o mais seguro possível como uma experiência de exercício / aprendizado. Não quero usar SSL, pois não quero o aborrecimento e, principalmente, as despesas de configuração.
Essas perguntas de SO foram especialmente úteis para começar:
- Autenticação RESTful
- Práticas recomendadas para proteger uma API REST / serviço da web
- Exemplos das melhores APIs da web SOAP / REST / RPC? E por que você gosta deles? E o que há de errado com eles?
Estou pensando em usar uma versão simplificada da autenticação do Amazon S3 (gosto do OAuth, mas parece muito complicado para minhas necessidades). Estou adicionando um nonce gerado aleatoriamente , fornecido pelo servidor, à solicitação, para evitar ataques de reprodução.
Para chegar à pergunta:
O S3 e o OAuth dependem da assinatura do URL da solicitação, juntamente com alguns cabeçalhos selecionados. Nenhum deles assina o corpo da solicitação para solicitações POST ou PUT. Isso não é vulnerável a um ataque man-in-the-middle, que mantém o URL e os cabeçalhos e substitui o corpo da solicitação por quaisquer dados que o invasor queira?
Parece que posso me proteger disso, incluindo um hash do corpo da solicitação na string que é assinada. Isso é seguro?
Respostas:
Uma resposta anterior mencionou apenas o SSL no contexto da transferência de dados e não cobriu a autenticação.
Você está realmente perguntando sobre a autenticação segura de clientes da API REST. A menos que você esteja usando a autenticação do cliente TLS, o SSL sozinho NÃO é um mecanismo de autenticação viável para uma API REST. O SSL sem autenticação do cliente autentica apenas o servidor , o que é irrelevante para a maioria das APIs REST porque você realmente deseja autenticar o cliente .
Se você não usar a autenticação do cliente TLS, precisará usar algo como um esquema de autenticação baseada em resumo (como o esquema personalizado do Amazon Web Service) ou o OAuth 1.0a ou até a autenticação HTTP Basic (mas apenas SSL).
Esses esquemas autenticam que a solicitação foi enviada por alguém esperado. O TLS (SSL) (sem autenticação do cliente) garante que os dados enviados pela conexão permaneçam inalterados. São preocupações separadas - mas complementares -.
Para os interessados, expandi uma questão SO sobre os esquemas de autenticação HTTP e como eles funcionam .
fonte
REST significa trabalhar com os padrões da Web, e o padrão para transferência "segura" na Web é SSL. Qualquer outra coisa será meio descolada e exigirá um esforço extra de implantação para os clientes, que terão que ter bibliotecas de criptografia disponíveis.
Depois de se comprometer com o SSL, não há realmente nada exigido para autenticação em princípio. Você pode novamente seguir os padrões da web e usar a autenticação HTTP Basic (nome de usuário e token secreto enviados junto com cada solicitação), pois é muito mais simples que um protocolo de assinatura elaborado e ainda é eficaz no contexto de uma conexão segura. Você só precisa ter certeza de que a senha nunca passa por texto simples; portanto, se a senha for recebida através de uma conexão de texto sem formatação, você pode até desativar a senha e enviar um email ao desenvolvedor. Você também deve garantir que as credenciais não sejam registradas em nenhum lugar após o recebimento, assim como você não registraria uma senha comum.
O HTTP Digest é uma abordagem mais segura, pois evita que o token secreto seja transmitido; em vez disso, é um hash que o servidor pode verificar do outro lado. Embora possa ser um exagero para aplicativos menos sensíveis, se você tomou as precauções mencionadas acima. Afinal, a senha do usuário já é transmitida em texto sem formatação quando eles efetuam login (a menos que você esteja fazendo alguma criptografia JavaScript sofisticada no navegador) e da mesma forma seus cookies em cada solicitação.
Observe que, com as APIs, é melhor para o cliente passar tokens - sequências geradas aleatoriamente - em vez da senha com a qual o desenvolvedor faz logon no site. Portanto, o desenvolvedor deve poder fazer login no seu site e gerar novos tokens que podem ser usados para verificação da API.
O principal motivo para usar um token é que ele pode ser substituído se for comprometido, enquanto que se a senha for comprometida, o proprietário poderá fazer login na conta do desenvolvedor e fazer o que quiser com ele. Uma outra vantagem dos tokens é que você pode emitir vários tokens para os mesmos desenvolvedores. Talvez por terem vários aplicativos ou por quererem tokens com diferentes níveis de acesso.
(Atualizado para cobrir as implicações de tornar a conexão somente SSL.)
fonte
Ou você pode usar a solução conhecida para esse problema e usar SSL. Certificados autoassinados são gratuitos e é um projeto pessoal, certo?
fonte
Se você exigir o hash do corpo como um dos parâmetros no URL e esse URL for assinado por meio de uma chave privada, um ataque de intermediário poderá substituir o corpo apenas pelo conteúdo que geraria o mesmo hash. Agora, é fácil fazer isso com os valores de hash MD5 e, quando o SHA-1 está quebrado, bem, você entendeu.
Para proteger o corpo de adulteração, você precisaria de uma assinatura do corpo, que seria menos provável que um ataque de homem do meio seja capaz de quebrar, pois eles não conheceriam a chave privada que gera a assinatura .
fonte
Na verdade, o auth S3 originais que permitem o conteúdo a ser assinado, embora com uma assinatura MD5 fraco. Você pode simplesmente impor a prática opcional de incluir um cabeçalho Content-MD5 no HMAC (sequência a ser assinada).
http://s3.amazonaws.com/doc/s3-developer-guide/RESTAuthentication.html
Seu novo esquema de autenticação v4 é mais seguro.
http://docs.aws.amazon.com/general/latest/gr/signature-version-4.html
fonte
Lembre-se de que suas sugestões dificultam a comunicação dos clientes com o servidor. Eles precisam entender sua solução inovadora e criptografar os dados de acordo. Esse modelo não é tão bom para API pública (a menos que você seja amazon \ yahoo \ google ..).
De qualquer forma, se você precisar criptografar o conteúdo do corpo, sugiro que você verifique os padrões e soluções existentes, como:
Criptografia XML (padrão W3C)
Segurança XML
fonte