Como proteger uma API REST apenas para aplicativos móveis confiáveis

86

Como posso ter certeza de que minha API REST responde apenas a solicitações geradas por clientes confiáveis, no meu caso, meus próprios aplicativos para dispositivos móveis? Eu quero evitar solicitações indesejadas provenientes de outras fontes. Não quero que os usuários preencham uma chave serial ou qualquer outra coisa, isso deve acontecer nos bastidores, na instalação e sem a necessidade de interação com o usuário.

Tanto quanto eu sei, o HTTPS é apenas para validar o servidor com o qual você está se comunicando é quem ele diz que é. Eu provavelmente vou usar HTTPS para criptografar os dados.

Existe uma maneira de conseguir isso?

Atualização: O usuário pode executar ações somente leitura, que não exigem que o usuário faça o login, mas também podem executar ações de gravação, que exigem que o usuário efetue login (Autenticação por token de acesso). Nos dois casos, desejo que a API responda a solicitações provenientes apenas de aplicativos móveis confiáveis.

A API também será usada para registrar uma nova conta por meio do aplicativo para dispositivos móveis.

Atualização 2: Parece que há várias respostas para isso, mas eu sinceramente não sei qual sinalizar como resposta. Alguns dizem que isso pode ser feito, alguns dizem que não pode.

    
por Supercell 20.11.2013 / 18:43
fonte

8 respostas

44

Você não pode.

Você nunca pode verificar uma entidade, qualquer entidade , seja uma pessoa, cliente de hardware ou cliente de software. Você só pode verificar se o que eles estão dizendo para você está correto, então, assumir honestidade.

Por exemplo, como o Google sabe que está Estou acessando minha conta do Gmail? Eles simplesmente me pedem um nome de usuário e senha, verifique isso , então assuma a honestidade porque quem mais teria essa informação? Em algum momento, o Google decidiu que isso não era suficiente e acrescentou verificação comportamental (procurando por comportamentos estranhos), mas ainda está contando com a pessoa para fazer o comportamento , validando o comportamento .

Isso é exatamente o mesmo que validar o cliente. Você só pode validar o comportamento do Cliente, mas não o próprio Cliente.

Portanto, com o SSL, você pode verificar se o cliente tem um certificado válido ou não. Assim, basta instalar o aplicativo, obter o certificado e executar todo o código novo.

Então a questão é: Por que isso é tão crítico? Se esta é uma preocupação real, eu questionaria a sua escolha de um cliente gordo. Talvez você deva usar um aplicativo da Web (para não expor sua API).

Veja também: Derrotando a validação do certificado SSL para aplicativos Android

e: Quão seguros são os certificados SSL do cliente em um aplicativo para dispositivos móveis?

    
por 20.11.2013 / 19:53
fonte
27

Tenho certeza de que você se sente à vontade para lidar com logins de usuários e com comunicações por SSL. Por isso, vou me concentrar no que considero a parte mais interessante da pergunta: como garantir que seus comentários sejam lidos. somente ações - as quais não exigem que o usuário seja autenticado - só são aceitas de seus próprios aplicativos clientes?

Antes de mais nada, há a desvantagem que o fNek insinuou em uma resposta anterior - seus aplicativos cliente estão nas mãos de usuários potencialmente hostis. Eles podem ser examinados, suas comunicações inspecionadas, seu código desmontado. Nada que eu sugiro permitirá que você garanta que alguém não faça engenharia reversa do seu cliente e abuse da sua API REST. Mas deve colocar uma barreira na frente de qualquer tentativa casual.

De qualquer forma, uma abordagem comum é:

  • O cliente contém um segredo
  • Ao fazer uma solicitação, ela concatena os parâmetros da solicitação com os segredos e coloca o resultado em hash
  • Esse hash é enviado com a solicitação e verificado pelo servidor

por exemplo, imagine uma solicitação de GET para /products/widgets

Digamos que o segredo do cliente seja "OH_HAI_I_IZ_SECRET"

Concatene o verbo HTTP, o URL e o segredo:

GET/products/widgetsOH_HAI_I_IZ_SECRET

E use um hash SHA-1 disso:

4156023ce06aff06777bef3ecaf6d7fdb6ca4e02

Em seguida, envie isso, então a solicitação seria para:

GET /products/widgets?hash=4156023ce06aff06777bef3ecaf6d7fdb6ca4e02

Por fim, para impedir que alguém, pelo menos, reproduza solicitações individuais, use um timestamp também e adicione-o aos parâmetros e ao hash. por exemplo. agora, no tempo Unix, é 1384987891. Adicione isso à concatenação:

GET/products/widgetsOH_HAI_I_IZ_SECRET1384987891

Hash isso:

2774561d4e9eb37994d6d71e4f396b85af6cacd1

E envie:

GET /products/widgets?time=1384987891&hash=2774561d4e9eb37994d6d71e4f396b85af6cacd1

O servidor verificará o hash e também verificará se o registro de data e hora é atual (por exemplo, em 5 minutos para permitir que os relógios não estejam perfeitamente sincronizados)

Aviso! Como você está falando sobre aplicativos para dispositivos móveis, há um risco definitivo de que o telefone de alguém tenha seu relógio errado. Ou fuso horário errado. Ou alguma coisa. Adicionar o tempo ao hash provavelmente irá quebrar alguns usuários legítimos, então use essa ideia com cuidado.

    
por 20.11.2013 / 23:53
fonte
12

Para qualquer pessoa interessada, no Android você pode verificar se a solicitação recebida foi enviada pelo seu aplicativo.

Em resumo, quando você faz o upload do seu aplicativo no google, você o assina, com uma chave única que é conhecida apenas por você (e pelo google).

O processo de verificação é assim (ish):

  1. seu aplicativo acessa o google e solicita o token de autenticação
  2. seu aplicativo envia o token com segurança para seu back-end
    1. o seu back-end vai para o google e verifica o token de autenticação do seu aplicativo.
    2. seu back-end verifica se a chave exclusiva que seu aplicativo assinou corresponde, se não significa que não foi seu aplicativo ...

o blog completo que explica e como implementá-lo pode ser encontrado aqui: link

    
por 12.04.2016 / 11:20
fonte
5

Ok, então vale a pena mencionar antes de começar que para a maioria das aplicações isso é imensamente exagerado. Para a maioria dos casos de uso, simplesmente ter um único certificado válido e / ou token é mais que suficiente. Se isso envolve fazer algo difícil, como descompilar seu aplicativo, a maioria dos hackers não vai incomodar, a menos que você forneça alguns dados muito valiosos. Mas ei, onde a diversão nessa resposta?

Então, o que você pode fazer é configurar uma criptografia assimétrica um pouco como assinatura digital usada para assinar programas. Cada aplicativo pode ter um certificado individual que é emitido por uma única CA e verificado quando o usuário se conecta. (ao registrar pela primeira vez ou ao fazer a primeira instalação) Quando esse certificado for autenticado, você poderá proteger ainda mais seu aplicativo registrando esse certificado como válido para um determinado identificador de dispositivo (como ID do Android )

    
por 21.11.2013 / 00:36
fonte
4

Como @Morons mencionou em sua resposta, é muito difícil verificar a entidade no outro extremo da conexão.

A maneira mais simples de fornecer algum nível de autenticidade é fazer com que o servidor verifique algum segredo que somente a entidade real saberia. Para um usuário, isso pode ser um nome de usuário e uma senha. Para um software onde não há usuário, você pode incorporar um segredo.

O problema com essas abordagens é que você precisa colocar alguma confiança no cliente. Se alguém reverter os engenheiros do seu aplicativo ou roubar sua senha, ele poderá fingir ser você.

Você pode tomar medidas para tornar mais difícil extrair as informações secretas, ofuscando-as no executável. Ferramentas como o ProGuard, que é um ofuscador para Java, podem ajudar nisso, eu não sei tanto sobre ofuscação em outras linguagens, mas provavelmente há ferramentas similares. O uso de uma conexão TLS ajuda a impedir que as pessoas espionem seu tráfego, mas não impede um ataque MITM. O Fixar pode ajudar a resolver esse problema.

Eu trabalho para uma empresa chamada CriticalBlue (Full disclosure!) que tem um produto chamado Approov que tenta resolver esse problema de confiança . Ele funciona para Android / iOS atualmente e fornece um mecanismo para que nossos servidores verifiquem a integridade do aplicativo cliente. Isso é feito fazendo com que o cliente calcule uma resposta a um desafio aleatório. O cliente precisa calcular a resposta usando atributos do pacote de aplicativos instalados, que são difíceis de falsificar e inclui alguns mecanismos sofisticados de proteção contra falsificação.

Ele retorna um token que você pode enviar como prova de autenticidade para sua API.

A diferença importante com essa abordagem é que, embora seja possível desativar a verificação de autenticidade no cliente, se você fez isso, você não obteria o token de autenticação necessário para verificar seu aplicativo no servidor. A biblioteca também é strongmente acoplada às características do executável, portanto, seria muito difícil incorporá-lo em um aplicativo falso e fazê-lo funcionar.

Há uma análise de custo / benefício que qualquer desenvolvedor de API deve fazer para decidir a probabilidade de alguém tentar hackear sua API e o quanto isso pode ser caro. Uma simples verificação secreta no aplicativo impede ataques triviais, mas proteger-se contra um invasor mais determinado é provavelmente consideravelmente mais complicado e potencialmente caro.

    
por 25.07.2016 / 18:10
fonte
0

SSL protegerá o canal de comunicação.

O login bem-sucedido emitirá um token de autenticação por conexão criptografada.

O token de autenticação será passado para sua API REST em todas as solicitações subsequentes.

    
por 20.11.2013 / 19:09
fonte
0

Não seria muito seguro, mas você poderia adicionar algum tipo de código secreto ou até mesmo uma assinatura dgital. Desvantagem: deve ser incluído no aplicativo, o que facilita a obtenção se você souber o que faz.

    
por 20.11.2013 / 19:59
fonte
0

As far as I know, HTTPS is only to validate the server you are communicating with is who it says it is.

Na verdade, você pode usar o SSL para autenticar o cliente e o servidor. Ou, dito de outra forma, "sim, você pode usar certificados de cliente".

Você precisará ...

  • observe a biblioteca SSL que você está usando para determinar como especificar certificados de clientes no dispositivo móvel,
  • escreva o código ou configure seu servidor HTTPS para que ele aceite apenas conexões de clientes confiáveis e registrados.
  • crie um mecanismo para adicionar certificados de cliente confiáveis ao seu servidor
  • crie um mecanismo para remover certificados de cliente não mais confiáveis do seu servidor

Você pode fazer com que o aplicativo para dispositivos móveis armazene o certificado onde você quiser. Como você deseja a autenticação específica do aplicativo, considere armazenar o certificado em um local de disco protegido (no Android, você pode criar uma tabela "config" no banco de dados SQLite e uma linha para o certificado e outra para a chave privada) .

    
por 20.11.2013 / 21:15
fonte