Comment sauvegarder une API REST pour les applications mobiles approuvées uniquement

96

Comment puis-je m'assurer que mon API REST ne répond qu'aux demandes générées par des clients approuvés, dans mon cas, mes propres applications mobiles? Je veux empêcher les demandes indésirables provenant d'autres sources. Je ne veux pas que les utilisateurs remplissent une clé de série ou quoi que ce soit, cela devrait se faire en coulisse, lors de l'installation et sans aucune interaction de l'utilisateur.

Autant que je sache, HTTPS ne sert qu'à valider le serveur avec lequel vous communiquez, c'est à qui il est destiné. Je vais bien sûr utiliser HTTPS pour chiffrer les données.

Y a-t-il un moyen d'accomplir cela?

Mise à jour: l'utilisateur peut effectuer des actions en lecture seule, ne nécessitant pas d'être connecté, mais également des actions en écriture, qui nécessitent que l'utilisateur soit connecté (authentification par jeton d'accès). Dans les deux cas, je souhaite que l'API réponde aux demandes provenant d'applications mobiles sécurisées.

L'API sera également utilisé pour l'enregistrement d'un nouveau compte via l'application mobile.

Mise à jour 2: Il semble y avoir plusieurs réponses à cette question, mais honnêtement, je ne sais pas laquelle indiquer. Certains disent que cela peut être fait, d'autres pas.

Supercell
la source
HTTPS utilise SSL (et TLS). SSL / TLS peut être utilisé avec l'authentification du client.
Atk
Voulez-vous dire des certificats SSL côté client? Je pense que c'est ce que je recherche, sauf que je ne sais pas si c'est même possible dans les applications mobiles (Android et iOS)? Où le certificat client serait-il stocké? Stockage de l'appareil, mémoire?
Supercell
SSL ne certifiera que le périphérique mobile, PAS l'application mobile.
Morons
@ Supercell: Je vais ajouter une réponse
atk

Réponses:

48

Vous ne pouvez pas.

Vous ne pouvez jamais vérifier une entité, aucune entité , que ce soit une personne, un client matériel ou un client logiciel. Vous pouvez seulement vérifier que ce qu'ils vous disent est correct, puis présumez l’honnêteté .

Par exemple, comment Google sait-il que je me connecte à mon compte Gmail? Ils me demandent simplement un nom d'utilisateur et un mot de passe, vérifient cela , puis supposent l'honnêteté, car qui d'autre aurait cette information? À un certain moment Google a décidé que cela ne suffisait pas et a ajouté la vérification du comportement ( à la recherche d' un comportement étrange) , mais qui est toujours sur la fonde personne pour faire le comportement , puis validez le comportement .

C'est exactement la même chose avec la validation du client. Vous pouvez uniquement valider le comportement du client, mais pas le client lui-même.

Donc, avec SSL, vous pouvez vérifier que le client possède un certificat valide ou non. Vous pouvez donc simplement installer votre application, obtenir le certificat, puis exécuter tout nouveau code.

La question est donc: pourquoi est-ce si critique? Si cela pose un réel problème, je m'interrogerais sur votre choix d'un gros client. Peut-être devriez-vous utiliser une application Web (pour ne pas avoir à exposer votre API).

Voir aussi: Suppression de la validation de certificat SSL pour les applications Android

et: Quel est le degré de sécurité des certificats SSL clients dans une application mobile?

Crétins
la source
1
J'ai utilisé des certificats clients sur du matériel où le certificat était stocké sur un lecteur chiffré par le système d'exploitation. Mais même là, personne ne croyait que c'était à toute épreuve. L'objectif était simplement de rendre les choses difficiles pour les utilisateurs occasionnels.
Gort le robot
1
@Morons: une application Web résoudrait ce problème, mais nous pensons que les utilisateurs seront plus susceptibles d'utiliser l'application native qu'une application Web (corrigez-moi si notre hypothèse est fausse). La raison pour laquelle cela est si critique est que l'API donne à l'utilisateur un accès à des parties de notre base de données, qui contient beaucoup de données que nous avons collectées au cours de mois de travail. Ce sont des données que d’autres entreprises ou utilisateurs pourraient facilement utiliser à leurs propres fins. Sans sécuriser les clients, nous ne saurions pas qui l’utilisait (contre nous).
Supercell
6
Une application Web ne résout pas le problème. Il est assez simple de modifier n'importe quelle application Web et de lui faire faire ce que vous voulez.
Gort le robot
5
@Supercell Vous ne pouvez pas montrer les données de quelqu'un et ensuite les empêcher de les partager. Si vous ne voulez pas que certaines aient des données, vous ne les leur donnez pas.
Morons
Je suis d'accord mais pour une raison différente. Vous pouvez le faire si vous aviez le contrôle des périphériques, comme en.wikipedia.org/wiki/SecurID . Mais les mobiles ne sont pas quelque chose qui peut être contrôlé (ils pourraient accepter une pièce jointe comme une clé de plugin ou quelque chose).
imel96
31

Je suis sûr que vous êtes à l'aise avec les connexions des utilisateurs et les communications via SSL. Je vais donc me concentrer sur la partie la plus intéressante de la question: comment faire en sorte que vos actions en lecture seule - qui n'exigent pas que l' utilisateur soit authentifié - ne sont acceptés que depuis vos propres applications clientes?

Avant toute chose, il y a l'inconvénient auquel fNek a fait allusion dans une réponse précédente: vos applications clientes sont entre les mains d'utilisateurs potentiellement hostiles. Ils peuvent être examinés, leurs communications inspectées, leur code désassemblé. Rien de ce que je vais suggérer ne vous permettra de garantir que quelqu'un ne procédera pas à l'ingénierie inverse de votre client et n'abuse pas de votre API REST. Mais il devrait mettre une barrière devant toute tentative fortuite.

Quoi qu’il en soit, une approche commune est la suivante:

  • Le client contient un secret
  • Lors de la demande, il concatène les paramètres de la demande avec les secrets et hache le résultat
  • Ce hachage est envoyé avec la demande et vérifié par le serveur.

par exemple, imaginez une GETdemande de/products/widgets

Disons que le secret du client est "OH_HAI_I_IZ_SECRET"

Concaténez le verbe HTTP, l'URL et le secret:

GET/products/widgetsOH_HAI_I_IZ_SECRET

Et prenez un hachage SHA-1 de cela:

4156023ce06aff06777bef3ecaf6d7fdb6ca4e02

Puis envoyez-le, la demande serait donc pour:

GET /products/widgets?hash=4156023ce06aff06777bef3ecaf6d7fdb6ca4e02

Enfin, pour empêcher au moins une autre personne de rejouer des requêtes individuelles, prenez également un horodatage et ajoutez-le aux paramètres et au hachage. par exemple, à l'heure Unix, correspond à 1384987891. Ajoutez cela à la concaténation:

GET/products/widgetsOH_HAI_I_IZ_SECRET1384987891

Hache ça:

2774561d4e9eb37994d6d71e4f396b85af6cacd1

Et envoyer:

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

Le serveur vérifiera le hachage et vérifiera également que l'horodatage est actuel (par exemple, dans les 5 minutes pour permettre aux horloges de ne pas être parfaitement synchronisées)

Attention! Puisque vous parlez d'applications mobiles, il y a un risque certain que le téléphone de quelqu'un se trompe d'horloge. Ou le mauvais fuseau horaire. Ou quelque chose. Ajouter du temps au hash va probablement casser certains utilisateurs légitimes, utilisez donc cette idée avec prudence.

Carson63000
la source
6
Ce mécanisme de hachage peut être compris par tout programmeur lorsqu'il démonte l'apk.
Punith Raj
8
@PunithRaj exactement, j'ai couvert cela dans le deuxième paragraphe. "Rien de ce que je vais suggérer ne vous permettra de garantir que quelqu'un ne procédera pas à l'ingénierie inverse de votre client et n'abusera pas de votre API REST. Mais cela devrait mettre un obstacle devant toute tentative fortuite."
Carson63000
pour l'avertissement, j'utilise UTC sur le serveur et le mobile, cela résout le problème, non?
Shareef
@ Carson63000 - existe-t-il une solution concrète? en particulier pour l'API d'enregistrement d'utilisateur, qui doit être ouverte publiquement (un utilisateur doit s'inscrire avant de pouvoir se connecter, que ce soit sur le Web ou sur une application mobile) et peut être ciblée par des bots pour créer des milliers de faux utilisateurs.
Tohid le
17

Sur Android, vous POUVEZ vérifier que la demande que vous avez reçue a été envoyée depuis votre application.

En bref, lorsque vous téléchargez votre application sur Google, vous la signez avec une clé unique que vous seul connaissez (et google).

Le processus de vérification se passe comme suit:

  1. votre application va sur google et demande un jeton d'authentification
  2. votre application envoie le jeton en toute sécurité à votre serveur
    1. votre back-end va sur google et vérifie le jeton d'authentification obtenu de votre application.
    2. votre système vérifie ensuite si la clé unique de votre application contient des correspondances signées, sinon, cela signifie que ce n'était pas votre application ...

le blog complet qui l'explique et comment le mettre en œuvre peut être trouvé ici: http://android-developers.blogspot.co.il/2013/01/verifying-back-end-calls-from-android.html

Ndori
la source
1
Bonne réponse, mais un utilisateur malveillant peut toujours simuler une application avec suffisamment d'effort. mais rien n'est vraiment sûr, ce n'est pas une question de savoir si - juste une question de quand
mateos
1
Pour iOS, il existe cette option: link Les API DeviceCheck vous permettent également de vérifier que le jeton que vous recevez provient d'un périphérique Apple authentique sur lequel votre application a été téléchargée
Iwaz
Il faut des comptes (courriels)
user25
5

Ok, donc il vaut la peine de mentionner avant de commencer que pour la plupart des applications, cela est excessivement excessif. Dans la plupart des cas d'utilisation, le simple fait de posséder un seul certificat et / ou jeton valide suffit largement. Si cela implique de faire quelque chose de difficile, comme de décompiler votre application, alors même la plupart des pirates informatiques ne s'embêteront pas, à moins que vous ne fournissiez des données de grande valeur. Mais bon, où est le plaisir dans cette réponse?

Vous pouvez donc configurer une cryptographie asymétrique, un peu comme une signature numérique utilisée pour signer des programmes. Chaque application peut ensuite avoir un certificat individuel émis par une seule autorité de certification et vérifié lors de la connexion de votre utilisateur. (soit lors de la première inscription ou lors de la première installation) Lorsque ce certificat est authentifié, vous pouvez alors sécuriser davantage votre application en enregistrant ce certificat comme valide pour un identifiant de périphérique donné (tel que l' ID Android ).

Tom Squires
la source
5

Comme @Morons l'a mentionné dans sa réponse, il est très difficile de vérifier l'entité à l'autre bout de la connexion.

Le moyen le plus simple de fournir un certain niveau d'authenticité est de demander au serveur de vérifier un secret que seule l'entité réelle connaît. Pour un utilisateur, cela pourrait être un nom d'utilisateur et un mot de passe. Pour un logiciel sans utilisateur, vous pouvez intégrer un secret.

Le problème avec ces approches est que vous devez faire confiance au client. Si quelqu'un inverse l'ingénierie de votre application ou vole votre mot de passe, il peut se faire passer pour vous.

Vous pouvez prendre des mesures pour rendre plus difficile l'extraction des informations secrètes en les masquant dans l'exécutable. Des outils tels que ProGuard, qui est un obfuscateur pour Java, peuvent aider à cela. Je ne connais pas autant le principe d’obscurcissement dans d’autres langues, mais il existe probablement des outils similaires. L'utilisation d'une connexion TLS aide à empêcher les personnes d'espionner votre trafic, mais n'empêche pas une attaque MITM. Épingler peut aider à résoudre ce problème.

Je travaille pour une société appelée CriticalBlue (divulgation complète!) Qui propose un produit appelé Approov qui tente de résoudre ce problème de confiance. Il fonctionne actuellement pour Android / iOS et fournit un mécanisme permettant à nos serveurs de vérifier l'intégrité de l'application cliente. Pour ce faire, il demande au client de calculer une réponse à un défi aléatoire. Le client doit calculer la réponse à l'aide d'attributs du package d'application installés qui sont difficiles à simuler et comprend des mécanismes sophistiqués anti-sabotage.

Il renvoie un jeton que vous pouvez ensuite envoyer comme preuve d'authenticité à votre API.

La différence importante avec cette approche réside dans le fait qu'il est possible de désactiver le contrôle d'authenticité sur le client. Si vous le faites, vous n'obtiendrez pas le jeton d'authentification dont vous avez besoin pour vérifier votre application sur le serveur. La bibliothèque est également étroitement liée aux caractéristiques de l'exécutable dans lequel elle se trouve. Il serait donc très difficile de l'intégrer dans une fausse application et de la faire fonctionner.

Tout développeur d’API doit effectuer une analyse coûts / avantages pour déterminer la probabilité que quelqu'un essaie de pirater son API et son coût éventuel. Une simple vérification secrète dans l'application évite les attaques triviales, mais se protéger contre un attaquant plus déterminé est probablement beaucoup plus compliqué et potentiellement coûteux.

Le pragmatiste
la source
0

SSL sécurisera le canal de communication.

Une connexion réussie émettra un jeton d’authentification sur une connexion chiffrée.

Le jeton d'authentification sera transmis à votre API REST dans toutes les demandes suivantes.

CodeART
la source
1
J'ai ajouté des informations supplémentaires. Je prévoyais de faire l'authentification comme vous l'avez mentionné, avec un jeton d'accès. L'API REST ne nécessite pas que l'utilisateur soit connecté, uniquement pour des actions spécifiques. Dans les deux cas, les clients doivent être signés / approuvés.
Supercell
Je ne connais pas grand-chose au développement mobile natif, mais votre application mobile peut-elle fournir le numéro de mobile à l'API REST? Lorsque j'installe des applications sur mon téléphone Android, on me demande souvent de donner certaines autorisations à l'application. Si vous pouvez envoyer un numéro de téléphone portable avec chaque demande via une connexion sécurisée, vous pouvez rejeter toutes les demandes avec un numéro de téléphone portable inconnu. Juste penser à voix haute ici ...
CodeART
Cela pourrait fonctionner, mais il faudrait que l'utilisateur soit connecté et que le numéro soit lié au compte d'utilisateur. Sinon, le serveur n’aurait rien pour vérifier le nombre.
Supercell
Comment allez-vous installer votre application mobile?
CodeART
Ils seront disponibles via les app stores (Google, Apple, Microsoft)
Supercell
0

Ce ne serait pas trop sécurisé, mais vous pourriez ajouter une sorte de code secret ou même une signature générique. Inconvénient: il doit être inclus dans l'application, ce qui facilite son obtention si vous savez ce que vous faites.

fNek
la source
0

Autant que je sache, HTTPS ne sert qu'à valider le serveur avec lequel vous communiquez, c'est à qui il est destiné.

En fait, vous pouvez utiliser SSL pour authentifier le client et le serveur. Ou, autrement dit, "oui, vous pouvez utiliser des certificats clients".

Vous aurez besoin de ...

  • Examinez la bibliothèque SSL que vous utilisez pour déterminer comment spécifier les certificats clients sur le périphérique mobile.
  • écrivez du code ou configurez votre serveur HTTPS de manière à ce qu’il n’accepte que les connexions provenant de clients approuvés et enregistrés.
  • proposer un mécanisme pour ajouter des certificats clients de confiance sur votre serveur
  • mettre en place un mécanisme permettant de supprimer les certificats clients non approuvés de votre serveur

L'application mobile peut stocker le certificat où vous voulez. Puisque vous voulez une authentification spécifique à l’application, vous devriez envisager de stocker le certificat dans un emplacement de disque protégé (sous Android, vous pouvez créer une table "config" dans votre base de données SQLite, ainsi qu’une ligne pour votre certificat et une autre pour votre clé privée). .

atk
la source