Ne sont pas API keys
a considéré les noms d'utilisateur et API secrets
envisagé des mots de passe? Pourquoi les serveurs API comme Amazon Web Services vous permettent-ils de visualiser votre secret API en texte brut? Cela me fait penser qu'ils le stockent en texte brut ou au moins dans un format déchiffrable.
N'est-il pas préférable que les secrets de l'API soient traités comme des mots de passe que vous devez taper pour créer puis hacher dans la base de données au lieu de vous être remis en texte brut? Si, pour une raison quelconque, leur base de données secrète d'API était compromise, elle ouvrirait facilement les vannes pour de nombreuses applications utilisant leur API. Cependant, s'il a été haché de manière non déchiffrable, tout n'est pas facilement perdu.
Non. Les clés API doivent être stockées en texte clair.
Ce ne sont pas des mots de passe: ce sont des clés cryptographiques. Ces clés sont utilisées pour des choses comme l'authentification des demandes (à l'aide de SHA1-HMAC). Le serveur doit connaître la clé de chiffrement pour appliquer les algorithmes de chiffrement.
Par conséquent, la clé API doit être stockée en texte clair sur le serveur. Si le serveur ne stockait qu'un hachage de la clé API, il ne pouvait pas vérifier l'authenticité des messages du client ou authentifier les messages envoyés au client.
Le hachage n'est pas du stockage; il détruit irréversiblement les données. Nous pouvons nous contenter d'appeler le hachage de mot de passe comme "stockage de mot de passe" car lorsque nous avons réellement besoin du mot de passe, nous avons un opérateur humain à portée de main pour le taper. suffisant pour vérifier le mot de passe tapé.
Une clé API doit être stockée de manière à pouvoir être réutilisée sans surveillance . Le serveur doit vraiment stocker, au lieu de se souvenir juste d'un fantôme, car il a besoin de la véritable clé pour accéder à l'API.
Bien qu'il soit plus sûr de hacher les jetons d'API, il présente un problème de convivialité: les jetons sont longs et aléatoires, et ne devraient être communiqués à l'utilisateur qu'une seule fois avant de hacher. Cela rend un peu difficile de les sécuriser avec un hachage.
Ma suggestion pour un scénario sécurisé serait la suivante:
salt
et stockez-la dans la base de données. Ce sel ne doit pas être égal au sel de mot de passe de l'utilisateur.KDF(password, salt)
, où KDF
est une fonction de dérivation de clé telle que bcrypt. Appelez la valeur résultante k
.k
comme clé et stockez le texte chiffré dans la base de données.k
.Lorsque l'utilisateur se connecte, la webapp connaît son mot de passe et l'utilise pour calculer k
, qui est ensuite utilisé pour déchiffrer la clé API et l'afficher pour eux.
Lorsque l'utilisateur souhaite utiliser l'API, il doit envoyer k
ainsi que la clé d'API en texte brut, via SSL. La webapp peut ensuite déchiffrer la valeur de clé API stockée à l'aide de k
et la comparer à la clé API donnée. S'ils correspondent, c'est valide. Cela permet l'utilisation de la clé API sans que l'application ait besoin de stocker le mot de passe de l'utilisateur.
Si un attaquant viole la base de données, il doit cracker le mot de passe de l'utilisateur afin de calculer k
.
Il semble y avoir un peu de confusion ici et autres endroits , donc j'ajoute cette réponse dans l'espoir que cela clarifiera la situation pour les autres utilisateurs.
Il existe deux types de secrets API qui peuvent être utilisés.
Le cas d'utilisation dont la plupart des réponses sur cette page discutent est une clé secrète utilisée pour signer et vérifier les messages à l'aide d'un algorithme tel que HMAC. Dans ce cas, le client et l'API ont besoin de la valeur réelle de la clé pour créer une signature du message. Le serveur compare ensuite la signature qu'il a générée à la signature envoyée par le client et est en mesure de vérifier le message. Comme mentionné ci-dessus, si la clé d'origine n'est pas reproductible sur le serveur, cela ne peut pas fonctionner. Après avoir initialement partagé la clé avec le client (sur un canal crypté), la clé n'a plus besoin d'être transmise entre le client et le serveur.
L'autre secret client API commun est simplement une information d'identification secrète (comme vous pouvez le voir dans une demande de jeton d'accès OAuth2 typique). Ces informations d'identification sont transmises à chaque demande et ne doivent donc être transmises que sur un canal crypté (tel que HTTPS). Dans ce cas, le serveur doit uniquement conserver suffisamment d'informations pour vérifier que la valeur secrète fournie par le client est correcte, de sorte que le secret peut et doit être haché. Dans ce cas, le secret agit effectivement comme un mot de passe, et donc les mêmes précautions doivent être prises.
Avis de non-responsabilité: je ne suis pas un chercheur en sécurité, et vous devriez absolument faire plus de recherches sur ce sujet et sur tout sujet avant de suivre aveuglément les conseils de ce StackExchange.
tl; dr Le point le plus important est que différentes API peuvent utiliser le secret de différentes manières. Il est important de comprendre comment votre API utilise le secret client afin d'évaluer les meilleures pratiques pour le stocker.
Je mets mes deux cents à cause d'un problème qui n'a pas encore été mentionné. En particulier, je suis d'accord avec ce que @NickSloan a dit, mais avec une mise en garde supplémentaire.
Il existe une autre différence importante entre une clé API et un mot de passe. Les clés API sont uniques à votre site. La partie qui rend la sécurité des mots de passe si critique est le partage de mots de passe. Si quelqu'un obtient le mot de passe qu'un utilisateur a enregistré sur votre site, ce n'est pas seulement votre site qui est compromis: c'est tous les autres sites pour lesquels l'utilisateur a utilisé ce mot de passe (et email/nom d'utilisateur). De nombreuses personnes réutilisent des mots de passe sur des sites critiques: banques, réseaux sociaux, e-mail, etc., ce qui signifie qu'une bonne sécurité par mot de passe ne concerne pas tant la protection de l'accès à votre site que la protection de vos utilisateurs sur d'autres sites. Nous ne pouvons pas forcer les utilisateurs à améliorer la sécurité, nous devons donc assumer le pire et prendre des mesures supplémentaires pour qu'ils protègent leur propre vie privée.
Une clé API est un scénario complètement différent car elle est unique à votre site. En conséquence, s'il est volé, l'attaquant accède à votre site, mais ne gagne rien qu'ils puissent utiliser contre la banque/le courrier électronique/etc. de cette personne. Cela signifie que le niveau de risque pour les clés API est en fait inférieur à celui des mots de passe. Ils ne sont pas tout à fait dans la même situation: les clés d'API sont plus proches des identifiants de session que des mots de passe.
Comprendre que ceux-ci s'apparentent plus à des identifiants de session qu'à des mots de passe donne quelques informations pratiques sur la façon de protéger correctement ces clés. Notez que la discussion suivante s'applique aux clés API pour des choses comme OAuth informations d'identification, et non les informations d'identification de chiffrement (comme expliqué par @NickSloan dans sa réponse).
Les plus grandes menaces pour les mots de passe sont les attaques de phishing et les bases de données piratées, c'est pourquoi nous les stockons hachées dans nos bases de données. Les plus grandes menaces pesant sur les clés API sont les mêmes que pour les clés de session: faiblesses dans les applications frontales telles que les vulnérabilités XSS, MIM, etc. Il est important de noter que l'application frontale a besoin du mot de passe sous forme non cryptée, donc le hachage de la clé API ne vous rapporte vraiment rien lorsque la personne la plus susceptible de se faire voler en a besoin en texte brut.
Au lieu de cela, vous protégez un identifiant de session (ou OAuth ou clé API spécifique au client) principalement en gardant une trace du client. Si un identifiant de session est volé via XSS ou d'autres moyens du client , un résultat typique est que cet identifiant soit utilisé par l'attaquant sur un nouvel appareil. Cela signifie que tout à coup, vous verrez une ancienne clé arriver avec un nouvel agent utilisateur. Une telle modification est facile à détecter et à corriger: invalider immédiatement toutes les clés API. En particulier dans le cas des demandes OAuth, cela est très indolore pour l'utilisateur: il suffit de se reconnecter et d'en obtenir immédiatement une nouvelle, tandis que quelqu'un qui n'a volé que la clé (et n'a pas le mot de passe) est de retour à la planche à dessin.
Il s'agit d'une mesure de défense suffisamment courante pour qu'un pirate plus intelligent tente également d'enregistrer l'agent utilisateur associé à la clé volée et de l'utiliser dans toutes les demandes futures, mais vous pouvez toujours facilement voir quelque chose de louche se produire lorsque le même utilisateur a des demandes à venir. à partir de plusieurs adresses IP. Comme tout le reste du monde, cela peut être un peu un jeu de chat et de souris, mais il y a quelques points importants à retenir:
L'une des principales raisons pour lesquelles les mots de passe sont hachés avant de les stocker est de se protéger contre un attaquant obtenant un accès en lecture seule à la base de données . De cette façon, si un attaquant s'empare de la liste des identifiants de connexion, il ne pourra toujours pas les utiliser directement car les mots de passe sont hachés/salés.
Et ce n'est pas seulement un problème théorique que nous essayons de résoudre ici, ce type d'attaques se produisent vraiment ( y compris aux principaux acteurs de l'industrie ), et un hachage approprié permet d'atténuer l'impact d'une attaque.
Si vous êtes des utilisateurs d'authentifications utilisant un secret d'API, le secret d'API est effectivement devenu un mot de passe donc, du point de vue de la sécurité, ils devraient avoir le même mécanismes de protection comme les mots de passe habituels.
Amazon lui-même maintenant ne permet pas de récupérer le secret de l'API . Si vous l'oubliez, vous devez en demander un nouveau.
Non, ce n'est pas acceptable pour certains types de services.
Mise en œuvre
1. Lors de la connexion de l'utilisateur avec le mot de passe de connexion, générez une clé dérivée de son mot de passe pour crypter les données de cet utilisateur et conservez-les dans une session sur le serveur.
De cette façon, chaque utilisateur aura une clé unique. Cette clé dérivée ne doit pas être réversible, c'est le point principal. L'utilisation de hash_mac ou d'une autre méthode de hachage avec du sel et/ou une clé principale le permettra.
2. Utilisez cette clé pour crypter le secret API généré en utilisant AES 256 avec un iv aléatoire pour chaque utilisateur.
Ou
2.bis Utilisez cette clé pour générer la vraie clé de cryptage au tout dernier moment et crypter la méthode API en utilisant la même manière qu'en 2. pour éviter en mémoire des mots de passe flottants.
. Stocker l'iv dans la base de données avec l'ID utilisateur et l'ID d'application dans une table dédiée
4. Stockez le secret API chiffré dans la base de données dans la table appropriée.
tilisation
Maintenant, lorsque l'utilisateur se connecte à son panneau de contrôle, vous pouvez recréer la clé, récupérer l'iv, déchiffrer le secret de l'API pour cet utilisateur et l'afficher en texte clair. Vous affichez également la clé et demandez les deux lors de l'appel de l'API afin de pouvoir vérifier le secret de l'application.
Si vous souhaitez éviter d'afficher la clé et ne pas avoir à la demander lors d'un appel API, vous pouvez également utiliser la même méthode pour l'authentification que pour la connexion. Cela signifie que vous pouvez créer une autre table pour stocker une clé/sel aléatoire pour chaque application cliente et stocker une version hash_mac du secret API. Ainsi, seuls l'ID API et le secret API sont requis pour authentifier la demande d'API. mais c'est plus de travail.
Remarque
C'est pratiquement la même chose que la réponse @Polynomial.
De cette façon, il est très très difficile pour quelqu'un de pirater votre serveur et votre base de données pour voler les informations d'identification de vos utilisateurs et effectuer un appel API en leur nom. Vous pouvez maintenant évaluer que si une demande a été acceptée d'un client API, c'est le bon client ou c'est leur fuite.
Si l'utilisateur perd son mot de passe, vous régénérez un nouveau secret et une nouvelle clé API à partir de son nouveau mot de passe.