Segurança de esquemas de autenticação REST

228

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:

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?

dF.
fonte
6
O Amazon S3 pode incluir um Content-MD5 como parte da cadeia de cabeçalho para impedir o ataque MITM que você descreve.
laz
8
O MD5 é uma função de hash muito fraca e seu uso é desencorajado há muitos anos: en.wikipedia.org/wiki/MD5 . Use SHA2 hoje em dia. MD5 é batom em um porco com uma crise de identidade.
Henrik
6
Red Hat fornece certificados SSL livres que não lançam avisos de certificado nos principais navegadores
Platão
5
@SeanKAnderson (discurso retórico: acho absurdo como as pessoas falam sobre 99,9999999% s quando a Internet está sitiada por agências de espionagem que já automatizaram MUITOS ataques em 2008 - é uma maneira estranha de lidar com um problema real - "Naaah, não será um problema; para minha avó não conseguir invadir"
Henrik
2
@Plato eu recomendo LetsEncrypt estes dias para certificados SSL gratuitos
shuttle87

Respostas:

168

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 .

Les Hazlewood
fonte
16
Exatamente. A única coisa que o SSL verifica no que diz respeito à sua API é que a chamada com a qual ela está lidando não foi prejudicada no caminho. A API ainda não faz ideia de quem está falando com ela ou se deve ou não ter acesso.
21712 Tim Timututut
1
Boa resposta. Eu recomendaria também ter um olhar para estes excelentes recursos .. owasp.org/index.php/Web_Service_Security_Cheat_Sheet e owasp.org/index.php/REST_Security_Cheat_Sheet (PROJECTO)
dodgy_coder
2
Apenas um ponto menor, mas o uso do SSL também tem o benefício adicional de impedir a interceptação e ataques de intermediários.
Dodgy_coder 19/11/2012
@ Les Hazlewood Você poderia explicar como a autenticação HTTP Básica por HTTP pode ajudar a determinar o servidor sabe com quem está falando?
Mola
@ Les Hazlewood aqui, fiz uma pergunta; tnx stackoverflow.com/questions/14043397/…
Spring
60

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.)

mahemoff
fonte
3
Você pode obter um certificado SSL GoDaddy por US $ 30 por ano, eu acho. Fiquei chocado ao ver quanto os certificados SSL da Verisign custam (US $ 600 por ano ou algo assim, se bem me lembro?) Mas a opção GoDaddy é perfeitamente viável.
Brian Armstrong
19
A menos que você esteja usando autenticação mútua SSL / TLS e que o certificado usado pelo usuário / cliente seja confiável pelo servidor, você não autenticará o usuário no servidor / aplicativo. Você precisaria fazer algo mais para autenticar o usuário no servidor / aplicativo.
Pauld 3/08
5
Ryan: criptografia SSL nos dias de hoje tem uma quantidade muito pequena de poder de processamento em comparação com o que você usaria para gerar uma resposta com um quadro aplicativo web como Django ou Rails etc.
Cameron Walsh
4
certificados da startcom são gratuitos e amplamente reconhecidos. cacert.org é uma alternativa aberta com menos reconhecimento
Dima Tisnek
17
Isso não aborda a questão, que é sobre autenticação.
Sam Stainsby
8

Ou você pode usar a solução conhecida para esse problema e usar SSL. Certificados autoassinados são gratuitos e é um projeto pessoal, certo?

wowest
fonte
2
Certificados autoassinados são gratuitos, mas no AFAIK você ainda precisa de um IP estático.
dF.
8
@dF não é necessário ter um IP estático, exceto para determinados requisitos de licenciamento de comerciais pagos por certificados.
MarleneRodrigues1
Se você tem o controle dos armazenamentos de certificados nas duas extremidades (clientes e servidor), isso pode ser uma opção viável, mas ... o gerenciamento e a distribuição de certificados são provavelmente muito mais complexos na produção do que em um ambiente de desenvolvimento. Certifique-se de entender as complexidades dessa alternativa antes de se comprometer com ela.
aled
5

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 .

ZaDDaZ
fonte
9
Criar uma sequência que gere o mesmo hash md5 que o conteúdo válido pode ser muito mais fácil do que deveria ser, mas criar uma versão maligna de conteúdo válido com hashes no mesmo valor ainda é proibitivamente difícil. É por isso que o md5 não é mais usado para hashes de senhas, mas ainda é usado para verificar downloads.
Tim Gautier
1

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

LiorH
fonte