Práticas recomendadas para proteger uma API REST / serviço da web [fechado]

828

Ao projetar uma API ou serviço REST, existem práticas recomendadas para lidar com segurança (autenticação, autorização, gerenciamento de identidades)?

Ao criar uma API SOAP, você tem o WS-Security como guia e muita literatura existe sobre o tópico. Encontrei menos informações sobre a proteção de terminais REST.

Embora eu entenda que o REST intencionalmente não tem especificações análogas ao WS- *, espero que surjam as melhores práticas ou os padrões recomendados.

Qualquer discussão ou link para documentos relevantes seria muito apreciado. Se isso importa, estaríamos usando o WCF com mensagens serializadas POX / JSON para nossas APIs / Serviços REST criados usando a v3.5 do .NET Framework.

Nathan
fonte
1
você conhece algum aplicativo real completo usando bons padrões e práticas com a API REST e os serviços da web no github?
PreguntonCojoneroCabrón

Respostas:

298

Como o tweakt disse, o Amazon S3 é um bom modelo para se trabalhar. Suas assinaturas de solicitação possuem alguns recursos (como incorporar um carimbo de data / hora) que ajudam a proteger contra a reprodução acidental e maliciosa de solicitações.

O bom do HTTP Basic é que praticamente todas as bibliotecas HTTP o suportam. É claro que você precisará exigir SSL nesse caso, porque enviar senhas de texto sem formatação pela rede é quase universalmente uma coisa ruim. O Basic é preferível ao Digest ao usar SSL porque, mesmo que o chamador já saiba que as credenciais são necessárias, o Digest exige uma ida e volta extra para trocar o valor de nonce. Com o Basic, os chamadores simplesmente enviam as credenciais pela primeira vez.

Uma vez que a identidade do cliente é estabelecida, a autorização é realmente apenas um problema de implementação. No entanto, você pode delegar a autorização para outro componente com um modelo de autorização existente. Novamente, o mais interessante do Basic aqui é que o servidor acaba com uma cópia em texto sem formatação da senha do cliente, que você pode simplesmente passar para outro componente da infraestrutura, conforme necessário.

Greg Hewgill
fonte
3
O SSL é uma parte importante da segurança, mas nem todos os aplicativos exigem esse nível de criptografia. Se alguém rouba em trânsito o que você vai publicar publicamente no Twitter, isso é uma desvantagem tão significativa? Para a maioria da criptografia SSL da API, será preferida. Os requisitos de infraestrutura do SSL são um pouco mais altos do que os servidores de armazenamento em cache de texto sem formatação e intermediários (leia aqui pela borda) que podem participar do armazenamento em cache de conteúdo acessado repetidamente. Cuidado, sua escalabilidade pode sofrer se você precisar absolutamente da criptografia oferecida.
Norman H
36
@NormanH: Seu argumento é ilusório, porque se alguém puder ver toda a transação que eu uso para postar no Twitter, poderá, portanto, me passar por mim e postar suas próprias mensagens em meu nome.
precisa saber é o seguinte
3
Citando a Wikipedia sobre autenticação Digest, "A autenticação de acesso Digest é um dos métodos acordados que um servidor Web pode usar para negociar credenciais com o navegador da Web do usuário. Aplica uma função hash a uma senha antes de enviá-la pela rede, o que é mais segura que a autenticação de acesso básico, que envia texto sem formatação ". o que seria uma maneira padrão de realizar o que aludi acima. (Veja en.wikipedia.org/wiki/Digest_access_authentication para obter detalhes)
Norman H
5
"sending plaintext passwords over the net is almost universally a bad thing"- Você pode elaborar sobre o "quase"? Quando não é uma má ideia?
Toniedzwiedz 29/05
2
@GregHewgill, mesmo em uma rede privada, não gostaria que meus usuários interceptassem as senhas uns dos outros. A única situação em que consigo pensar, em que não há problema em enviar uma senha pela rede é quando o usuário está sozinho na rede. O fato de essas coisas acontecerem em outros lugares dificilmente é uma razão para permitir isso.
Toniedzwiedz 29/05
115

Não há outros padrões para o REST além do HTTP. Existem serviços REST estabelecidos por aí. Sugiro que você dê uma olhada nelas e tenha uma ideia de como elas funcionam.

Por exemplo, emprestamos muitas idéias do serviço S3 REST da Amazon ao desenvolver as nossas. Mas optamos por não usar o modelo de segurança mais avançado, com base em assinaturas de solicitação. A abordagem mais simples é a autenticação HTTP Basic sobre SSL. Você tem que decidir o que funciona melhor na sua situação.

Além disso, eu recomendo o livro RESTful Web Services da O'reilly. Explica os conceitos principais e fornece algumas práticas recomendadas. Geralmente, você pode pegar o modelo que eles fornecem e mapeá-lo para seu próprio aplicativo.

Mark Renouf
fonte
6
RESTful Web Services é definitivamente um ótimo livro. A deve ler nesta área. Foi absolutamente inspirador.
EdgarVerona
6
Como é que @aehlke recebeu tantos votos positivos por esse comentário, considerando (1) que não existe uma especificação REST e (2) a dissertação de campo sobre os estilos arquitetônicos e o design de arquiteturas de software baseadas em rede menciona explicitamente o REST e HTTP no 6.3: REST aplicado ao HTTP.
20
HTTP não é um requisito para o REST.
Nategood 16/05
1
O livro RESTful Web Services está disponível gratuitamente a partir de seu site: crummy.com/writing/RESTful-Web-Services
icc97
Eu estava planejando ler o livro e percebi que ele é direcionado principalmente para o formato XML. Devo usar este livro considerando a popularidade do JSON? Ou não depende do formato de intercâmbio de dados. Precisa de orientação.
Bhargav Jhaveri
72

Você também pode dar uma olhada no OAuth , um protocolo aberto emergente para autorização baseada em token voltada especificamente para apis http.

É muito semelhante à abordagem adotada pelo flickr e lembre-se das apis de "descanso" do leite (não necessariamente bons exemplos de apis repousantes, mas bons exemplos da abordagem baseada em token).

John Spurlock
fonte
3
Mas parece que o oAuth de duas pernas, que eu acho que é necessário aqui, não é coberto (falta de informação) tanto quanto o de três pernas.
Redben
4
OAuth é sobre delegação de autorização, ou seja, eu, o proprietário da informação / conta, deixo o serviço A interagir com meus dados no serviço B (por exemplo, deixo o Twitter escrever no meu facebook). Não é uma autorização no sentido mais amplo, que consiste em controlar o que os usuários podem fazer com recursos (dados, informações, serviços ...). É aqui que o XACML entra em cena. O XACML permite definir políticas de autorização sobre quem pode fazer o que.
David Brossard
60

Existe uma ótima lista de verificação encontrada no Github :

Autenticação

  • Não reinvente a roda na autenticação, geração de token e armazenamento de senha. Use os padrões.

  • Use Max Retrye prenda recursos no Login.

  • Use criptografia em todos os dados confidenciais.

JWT (Token da Web JSON)

  • Use uma chave complicada aleatória (JWT Secret) para dificultar a força bruta do token.

  • Não extraia o algoritmo da carga útil. Força o algoritmo no back-end (HS256 ou RS256).

  • Torne a expiração do token ( TTL, RTTL) o mais curta possível.

  • Não armazene dados confidenciais na JWTcarga, eles podem ser decodificados facilmente.

OAuth

  • Valide sempre o redirect_uriservidor para permitir apenas URLs na lista de permissões.

  • Sempre tente trocar por código e não por tokens (não permita response_type=token).

  • Use o parâmetro state com um hash aleatório para impedir CSRFo OAuthprocesso de autenticação.

  • Defina o escopo padrão e valide os parâmetros de escopo para cada aplicativo.

Acesso

  • Solicitações de limite (limitação) para evitar ataques DDoS / força bruta.

  • Use HTTPS no lado do servidor para evitar MITM (Man In The Middle Attack)

  • Use o HSTScabeçalho com SSL para evitar o ataque da tira SSL.

Entrada

  • Use o método HTTP adequado de acordo com a operação: GET(leia), POST(crie), PUT/PATCH(substitua / atualize) e DELETE(para excluir um registro) e responda com 405 Method Not Allowedse o método solicitado não for apropriado para o recurso solicitado.

  • Validar tipo de conteúdo a pedido Acceptcabeçalho (Negociação de Conteúdo) para permitir que apenas o seu formato suportado (por exemplo application/xml, application/json, etc) e responder com 406 Not Acceptableresposta se não correspondido.

  • Validar content-typede publicado dados que você aceitar (por exemplo application/x-www-form-urlencoded, multipart/form-data, application/json, etc).

  • Valide a entrada do usuário para evitar vulnerabilidades comuns (por exemplo, XSS, injeção de SQL, execução remota de código etc.).

  • Não use dados confidenciais (credenciais, senhas, tokens de segurança ou chaves de API) no URL, mas use o Authorizationcabeçalho padrão .

  • Use um serviço API Gateway para habilitar o cache, as Rate Limitpolíticas (por exemplo, Cota, Spike Arrest, Limite de Taxa Simultânea) e implante recursos de APIs dinamicamente.

Em processamento

  • Verifique se todos os terminais estão protegidos por trás da autenticação para evitar um processo de autenticação quebrado.

  • O ID do recurso próprio do usuário deve ser evitado. Use / me / orders em vez de / user / 654321 / orders.

  • Não incremente IDs automaticamente. Use UUID em vez disso.

  • Se você estiver analisando arquivos XML, verifique se a análise de entidades não está ativada para evitar XXE (ataque de entidade externa XML).

  • Se você estiver analisando arquivos XML, verifique se a expansão da entidade não está ativada para evitar a bomba Billion Laughs / XML por meio de um ataque de expansão exponencial da entidade.

  • Use uma CDN para upload de arquivos.

  • Se você estiver lidando com uma quantidade enorme de dados, use Trabalhadores e Filas para processar o máximo possível em segundo plano e retornar a resposta rapidamente para evitar o bloqueio de HTTP.

  • Não esqueça de desligar o modo DEBUG .

Resultado

  • Enviar X-Content-Type-Options: nosniffcabeçalho.

  • Enviar X-Frame-Options: denycabeçalho.

  • Enviar Content-Security-Policy: default-src 'none'cabeçalho.

  • Remover fingerprinting cabeçalhos - X-Powered-By, Server, X-AspNet-Versionetc.

  • Forçar content-typea sua resposta, se você retornar, application/jsonentão o tipo de conteúdo da resposta é application/json.

  • Não retorne dados confidenciais, como credenciais, senhas, tokens de segurança.

  • Retorne o código de status adequado de acordo com a operação concluída. (por exemplo 200 OK, 400 Bad Request, 401 Unauthorized, 405 Method Not Allowed, etc.).

Andrejs
fonte
1
Boa lista, embora um pouco opinativa - e começa com um imho absurdo: "Não use Autenticação Básica Use autenticação padrão (por exemplo, JWT, OAuth)." Você não pode obter um padrão mais do que o Basic Auth, e ele tem seu lugar, especialmente para APIs onde os clientes não são navegadores (para navegadores, o JWT geralmente é mais adequado). O OAuth, por outro lado, está usando um conjunto totalmente diferente de compromissos para autenticação e não é realmente comparável ao Basic Auth e JWT.
Johndodo
Você está certo, o BasicAuth com HTTPS é comum, mas é muito debatido - security.stackexchange.com/questions/988/… . Vou remover esse ponto de qualquer maneira.
28917 Andrejs
43

Estou surpreso com o SSL com certificados de cliente ainda não mencionado. Concedido, essa abordagem só é realmente útil se você puder contar com a comunidade de usuários que está sendo identificada por certificados. Mas vários governos / empresas os emitem para seus usuários. O usuário não precisa se preocupar em criar mais uma combinação de nome de usuário / senha, e a identidade é estabelecida em todas as conexões para que a comunicação com o servidor possa ser totalmente sem estado, sem necessidade de sessões do usuário. (Para não implicar que qualquer / todas as outras soluções mencionadas exijam sessões)

stinkymatt
fonte
Na verdade, usamos isso para algumas integrações e túneis vpn criptografados para oferecer suporte a sistemas mais antigos que não controlamos e que não podem se comunicar por https.
Casey #
Certificados de clientes podem causar problemas quando você precisa de balanceamento de carga ... isso pode ser feito, mas é menos direto.
Jeremy Logan
2
@fiXedd - O contrário tem sido minha experiência com clientes certs, porque eles são verdadeiramente apátridas. As conexões autenticadas pelo certificado do cliente podem ter balanceamento de carga com um balanceador de carga estúpido, sem levar em consideração a aderência da conexão, porque exigem um estado compartilhado absolutamente zero entre o cliente e o servidor.
Stinkymatt 15/10/12
4
Ah, você pode fazer isso ... você pode apenas fazer com que o balanceador de carga encaminhe o tráfego TCP, mas não pode, por exemplo, fazer com que o balanceador de carga seja o ponto de terminação do SSL.
21412 Jeremy Logan
Ainda é seguro se os certificados do cliente e sua autoridade raiz são autoassinados? A autoridade raiz será importada para as autoridades de certificação raiz confiáveis ​​do cliente.
Joyce
38

Todos nestas respostas ignoraram o verdadeiro controle / autorização de acesso.

Se, por exemplo, suas APIs / serviços REST da Web forem sobre registros médicos de POST / GETing, convém definir uma política de controle de acesso sobre quem pode acessar os dados e sob quais circunstâncias. Por exemplo:

  • os médicos podem OBTER o prontuário médico de um paciente com o qual mantêm uma relação de cuidado
  • ninguém pode POSTAR dados médicos fora do horário de prática (por exemplo, das 9 às 5)
  • os usuários finais podem OBTER registros médicos de sua propriedade ou registros médicos de pacientes de quem são os responsáveis
  • os enfermeiros podem ATUALIZAR o prontuário médico de um paciente que pertence à mesma unidade que o enfermeiro.

Para definir e implementar essas autorizações refinadas, você precisará usar uma linguagem de controle de acesso baseada em atributo chamada XACML, a eXtensible Access Control Markup Language.

Os outros padrões aqui são os seguintes:

  • OAuth: id. federação e delegação de autorização, por exemplo, deixar um serviço agir em meu nome em outro serviço (o Facebook pode postar no meu Twitter)
  • SAML: federação de identidade / SSO da web. SAML é muito sobre quem é o usuário.
  • Padrões WS-Security / WS- *: focam na comunicação entre serviços SOAP. Eles são específicos para o formato de mensagens no nível do aplicativo (SOAP) e lidam com aspectos de mensagens, como confiabilidade, segurança, confidencialidade, integridade, atomicidade, evento ... Nenhum abrange o controle de acesso e todos são específicos ao SOAP.

XACML é independente de tecnologia. Pode ser aplicado a aplicativos java, .NET, Python, Ruby ... serviços da web, APIs REST e muito mais.

A seguir, são recursos interessantes:

David Brossard
fonte
2
Não entendo por que você não pode simplesmente implementar um sistema de token que obterá o usuário e suas permissões, que serão essencialmente a mesma coisa?
Stan
Você pode adotar uma abordagem baseada em token. Isso funciona bem também, mas você ainda precisa da lógica que define quais permissões os usuários obtêm, em outras palavras, quais permissões inserir dentro do token. É isso que o XACML pode ajudá-lo a alcançar. Também evita o inchaço do token.
David Brossard
2
Como um comentário lateral, o que "9 a 5" contribui para a segurança? Como se os atacantes estivessem ativos apenas à noite? Para não falar das implicações graves do uso, como se os médicos trabalhassem apenas "9 às 5".
Roland
Esse é um requisito comum em cenários de assistência médica. Confira o HL7, por exemplo. Também existem cenários de quebra de vidros, caso um médico precise acessar fora do horário comercial. Quanto aos hackers, uma vez que está em todas as apostas estão fora
David Brossard
1
Alguns de meus colegas estão investigando isso de fato. Obrigado @SimplyG.
David Brossard
25

Eu usei o OAuth algumas vezes e também usei outros métodos (BASIC / DIGEST). Sugiro sinceramente OAuth. O link a seguir é o melhor tutorial que eu já vi sobre o uso do OAuth:

http://hueniverse.com/oauth/guide/

Rob Ottaway
fonte
Embora essa seja uma resposta muito antiga relacionada ao OAuth 1.0, vale a pena notar que o autor do link que você citou tinha a dizer sobre o OAuth 2.0 : "Cheguei à conclusão de que o OAuth 2.0 é um protocolo ruim ... Quando comparado ao OAuth 1.0, a especificação 2.0 é mais complexa, menos interoperável, menos útil, mais incompleta e, o mais importante, menos segura ". . Para deixar claro, o comentário que estou citando foi feito vários anos depois que você postou sua resposta.
Skomisa 22/01/19
17

Uma das melhores postagens que eu já vi sobre Segurança no que se refere ao REST terminou em 1 RainDrop . As APIs do MySpace usam o OAuth também por segurança e você tem acesso total aos canais personalizados no código RestChess, com o qual eu fiz muita exploração. Isso foi demonstrado no Mix e você pode encontrar a postagem aqui .

desgnome
fonte
Obrigado pelo link (1 RainDrop) - discussão muito interessante sobre segurança no que se refere ao SOAP v REST
Nathan
15

Obrigado pelo excelente conselho. Acabamos usando um cabeçalho HTTP personalizado para passar um token de identidade do cliente para o serviço, em preparação para integrar nossa API RESTful à futura estrutura Zermatt Identity da Microsoft. Eu descrevi o problema aqui e nossa solução aqui . Também segui os conselhos de tweakt e comprei o RESTful Web Services - um livro muito bom se você estiver criando uma API RESTful de qualquer tipo.

Nathan
fonte
1
Essa abordagem parece suspeita para mim. O que impede um invasor de usar o token de identidade para mascarar o cliente? HTTPS não protege o URL ou cabeçalhos a última vez que verifiquei ...
Gili
2
Hmmm ... não sei se você está certo sobre isso. Acredito que, exceto pelos poucos cabeçalhos necessários para entender que tipo de criptografia é necessária, todos os outros cabeçalhos são criptografados.
194 Nathan
51
Isso esta errado. HTTPS protege TUDO. É o seguinte: handshake TCP ... handshake TLS ... <ENCRYPTED> GET / foo 200 OK ... teardown </ENCRYPTED>.
Mark Renouf #
1
Observe que você também pode passar um token como um cookie (em vez de um cabeçalho personalizado). Isso se comporta bem nos navegadores, pois usa um cabeçalho HTTP com comportamentos padrão na maioria dos kits de ferramentas e aplicativos. No lado do serviço, o cookie não precisa estar relacionado a uma sessão, você pode usá-lo para comunicar qualquer token que desejar.
Bruce Alderson
11
O Wayback Machine é uma coisa bonita: a descrição do problema e solução
cjc343
14

OWASP (Projeto de segurança de aplicativos da Web abertos) tem algumas dicas sobre todos os aspectos do desenvolvimento de aplicativos da Web. Este projeto é uma fonte de informações muito valiosa e confiável. Em relação aos serviços REST, você pode verificar isso: https://www.owasp.org/index.php/REST_Security_Cheat_Sheet

WelsonJR
fonte
7

Eu recomendaria o OAuth 2/3. Você pode encontrar mais informações em http://oauth.net/2/

Abhijit Gaikwad
fonte
8
Cuidado para elaborar por que você recomendaria a versão 2 quando ela permanece praticamente incompleta? IMHO, versão 1.0a, continua sendo uma solução sólida para a maioria dos aplicativos.
Butifarra 20/03/2013
6

Eu pesquisei bastante sobre segurança tranquila e também acabamos usando token via cookie do cliente para o servidor para autenticar as solicitações. Usei a segurança de primavera para autorização de solicitações em serviço, pois tive que autenticar e autorizar cada solicitação com base nas políticas de segurança especificadas que já estavam no DB.

Parisa Kachoui
fonte
6

O fato de o mundo SOAP estar muito bem coberto por padrões de segurança não significa que ele é seguro por padrão. Em primeiro lugar, os padrões são muito complexos. A complexidade não é muito amiga das vulnerabilidades de segurança e implementação, como ataques de quebra de assinatura de XML, são endêmicas aqui.

Quanto ao ambiente .NET, não ajudarei muito, mas “Construir serviços da Web com Java” (um bloco com ~ 10 autores) me ajudou muito entender a arquitetura de segurança WS- * e, principalmente, suas peculiaridades.

kravietz
fonte
4

O próprio REST não oferece padrões de segurança, mas coisas como OAuth e SAML estão rapidamente se tornando os padrões nesse espaço. No entanto, autenticação e autorização são apenas uma pequena parte do que você precisa considerar. Muitas das vulnerabilidades conhecidas relacionadas a aplicativos da web se aplicam muito às APIs REST. Você deve considerar a validação de entrada, quebra de sessão, mensagens de erro inadequadas, vulnerabilidades internas dos funcionários e assim por diante. É um grande assunto.

Robert Morschel
fonte
4

Quero adicionar (de acordo com o stinkeymatt), a solução mais simples seria adicionar certificados SSL ao seu site. Em outras palavras, verifique se o seu URL é HTTPS: //. Isso cobrirá a segurança do seu transporte (economize dinheiro). Com os URLs RESTful, a idéia é mantê-lo simples (diferente do WS * security / SAML), você pode usar oAuth2 / openID connect ou mesmo Basic Auth (em casos simples). Mas você ainda precisará de SSL / HTTPS. Verifique a segurança da API da Web do ASP.NET 2 aqui: http://www.asp.net/web-api/overview/security (artigos e vídeos)

Manish Jain
fonte
3

Como o @Nathan acabou com um simples cabeçalho HTTP, e alguns disseram certificados OAuth2 e SSL do lado do cliente. A essência disso é esta ... sua API REST não deve ter que lidar com segurança, pois isso realmente deve estar fora do escopo da API.

Em vez disso, uma camada de segurança deve ser colocada em cima, seja um cabeçalho HTTP atrás de um proxy da Web (uma abordagem comum como SiteMinder, Zermatt ou mesmo Apache HTTPd) ou tão complicada quanto o OAuth 2.

O principal é que as solicitações devem funcionar sem nenhuma interação do usuário final. Tudo o que é necessário é garantir que a conexão com a API REST seja autenticada. No Java EE, temos a noção de userPrincipalque pode ser obtida em um HttpServletRequest. Também é gerenciado no descritor de implementação que um padrão de URL pode ser seguro para que o código da API REST não precise mais verificar.

No mundo do WCF, eu usaria ServiceSecurityContext.Currentpara obter o contexto de segurança atual. Você precisa configurar seu aplicativo para exigir autenticação.

Há uma exceção à declaração que tive acima e é o uso de um nonce para impedir replays (que podem ser ataques ou alguém apenas enviando os mesmos dados duas vezes). Essa parte só pode ser manipulada na camada de aplicativo.

Archimedes Trajano
fonte
3

Para Segurança de aplicativos Web, você deve dar uma olhada no OWASP ( https://www.owasp.org/index.php/Main_Page ), que fornece dicas para vários ataques de segurança. Você pode incorporar o maior número possível de medidas para proteger seu aplicativo. Com relação à segurança da API (autorização, autenticação, gerenciamento de identidades), há várias maneiras, como já mencionado (Basic, Digest e OAuth). Existem brechas no OAuth1.0, portanto você pode usar o OAuth1.0a (o OAuth2.0 não é amplamente adotado devido a preocupações com a especificação)

java_geek
fonte
2

Já faz um tempo, mas a pergunta ainda é relevante, embora a resposta possa ter mudado um pouco.

Um gateway de API seria uma solução flexível e altamente configurável. Eu testei e usei o KONG um pouco e gostei muito do que vi. O KONG fornece uma API REST de administração própria, que você pode usar para gerenciar usuários.

O Express-gateway.io é mais recente e também é um gateway de API.

Matt Bannert
fonte