Segurança de esquemas de autenticação REST

Fundo:

Eu estou projetando o esquema de autenticação para um serviço web REST. Isso não “realmente” precisa ser seguro (é mais um projeto pessoal), mas eu quero torná-lo o mais seguro possível, como uma experiência de exercício / aprendizagem. Eu não quero usar o SSL, pois não quero o incômodo e, principalmente, a despesa de configurá-lo.

Essas perguntas do SO foram especialmente úteis para me ajudar:

  • Autenticação RESTful
  • Melhores Práticas 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 (eu 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 repetição.

Para chegar à pergunta:

O S3 e o OAuth dependem da assinatura do URL de solicitação junto com alguns headers 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 a URL e os headers e substitui o corpo da solicitação pelos dados que o invasor deseja?

Parece que posso me proteger contra isso incluindo um hash do corpo da solicitação na string que é assinada. Isso é seguro?

Uma resposta anterior mencionou apenas o SSL no contexto da transferência de dados e não abrangeu 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 de cliente TLS, somente SSL NÃO é um mecanismo de autenticação viável para uma API REST. 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 de cliente TLS, precisará usar algo como um esquema de autenticação baseado em resumo (como o esquema personalizado do Amazon Web Service) ou o OAuth 1.0a ou até mesmo a autenticação Básica HTTP (mas somente 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 pelo cabo permaneçam sem proteção. São preocupações separadas – mas complementares.

Para os interessados, ampliei uma pergunta sobre esquemas de autenticação HTTP e como eles funcionam .

REST significa trabalhar com os padrões da Web e o padrão para transferência “segura” na Web é SSL. Qualquer outra coisa vai ser um pouco funky e requer esforço extra de implantação para os clientes, que terão que ter bibliotecas de criptografia disponíveis.

Depois que você se compromete com o SSL, não há realmente nada sofisticado para autenticação em princípio. Você pode ir novamente com os padrões da web e usar a autenticação HTTP básica (nome de usuário e token secreto enviado junto com cada solicitação), pois é muito mais simples do que um protocolo de assinatura elaborado e ainda efetivo 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 simples, você poderá até mesmo desabilitar a senha e enviar um e-mail 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 normal.

O HTTP Digest é uma abordagem mais segura, pois impede que o token secreto seja passado adiante; em vez disso, é um hash que o servidor pode verificar no outro extremo. Embora possa ser um exagero para aplicações menos sensíveis, se você tiver tomado as precauções mencionadas acima. Afinal de contas, a senha do usuário já é transmitida em texto sem formatação quando se conecta (a menos que você esteja fazendo alguma criptografia JavaScript sofisticada no navegador), e também seus cookies em cada solicitação.

Observe que com as APIs, é melhor que o cliente esteja passando tokens – strings geradas aleatoriamente – em vez da senha com a qual o desenvolvedor faz login no site. Assim, o desenvolvedor deve conseguir fazer login no seu site e gerar novos tokens que possam ser usados ​​para verificação da API.

A principal razão para usar um token é que ele pode ser substituído se estiver comprometido, ao passo que se a senha for comprometida, o proprietário poderá fazer login na conta do desenvolvedor e fazer o que quiser com ele. Outra vantagem dos tokens é que você pode emitir vários tokens para os mesmos desenvolvedores. Talvez porque eles tenham vários aplicativos ou porque querem tokens com diferentes níveis de access.

(Atualizado para cobrir as implicações de tornar a conexão somente SSL.)

Ou você pode usar a solução conhecida para esse problema e usar o SSL. Certs auto-assinados são gratuitos e é um projeto pessoal certo?

Se você precisar do hash do corpo como um dos parâmetros no URL e esse URL for assinado por meio de uma chave privada, um ataque man-in-the-middle só poderá replace o corpo por um conteúdo que gere o código. mesmo hash. Fácil de fazer com valores hash MD5 agora, pelo menos, e quando SHA-1 está quebrado, bem, você começa a foto.

Para proteger o corpo de adulterações, você precisaria exigir uma assinatura do corpo, que seria menos provável que um ataque do tipo intermediário fosse capaz de quebrar, já que não conheceria a chave privada que gera a assinatura. .

De fato, o S3 auth original permite que o conteúdo seja assinado, embora com uma assinatura MD5 fraca. Você pode simplesmente impor sua prática opcional de include um header Content-MD5 no HMAC (string a ser assinado).

http://s3.amazonaws.com/doc/s3-developer-guide/RESTAuthentication.html

O novo esquema de autenticação da v4 é mais seguro.

http://docs.aws.amazon.com/general/latest/gr/signature-version-4.html

Lembre-se de que suas sugestões dificultam a comunicação entre os clientes e o servidor. Eles precisam entender sua solução inovadora e criptografar os dados de acordo, esse modelo não é tão bom para a 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 verifique os padrões e soluções existentes, como:

Criptografia XML (padrão W3C)

Segurança XML