Je vois parfois des questions demandant comment stocker en toute sécurité les mots de passe des utilisateurs pour une application Web (en utilisant un SGBDR, je ne parle pas de Facebook ou de Twitter). La réponse habituelle est "salez le mot de passe, puis hachez-le avec un algorithme puissant tel que TDES ou SHA512".
Ma question est: en tant qu'utilisateur du SGBDR, pourquoi devrais-je me soucier du stockage des mots de passe, car la plupart des moteurs ont un mécanisme d'authentification intégré.
Par exemple, si un utilisateur X souhaite créer un mot de passe d'utilisateur de compte Y sur mon application Web, comment émettre la requête suivante:
CREATE USER X WITH ENCRYPTED PASSWORD Y IN GROUP baseuser;
Ensuite, dans mon application, l'utilisateur peut ouvrir une connexion à la base de données en utilisant ses informations d'identification et je n'ai pas à me soucier de la gestion des mots de passe.
Je vois plusieurs avantages à cette méthode:
- Si le SGBDR décide que l'algorithme de chiffrement doit être changé, je n'ai besoin de rien toucher, juste pour appliquer les mises à jour de sécurité;
- Il m'est facile de gérer les autorisations utilisateurs. Si un utilisateur est promu au rôle d'administrateur, je n'ai qu'à ajouter l'utilisateur au groupe correspondant;
- Les injections SQL n'ont plus de sens, car je gère les autorisations pour autoriser exactement ce que je veux autoriser à chaque utilisateur de la base de données (par exemple, dans un forum comme SO, ajouter de nouveaux messages, répondre aux messages, commenter et éditer / supprimer ses propres questions / réponses / commentaires);
- Un compte utilisateur "anonyme" peut être utilisé pour les connexions non authentifiées à mon application;
- Chaque utilisateur est propriétaire des données qu'il a fournies.
Mais sur pratiquement toutes les questions que je vois à ce sujet, il semble y avoir un consensus général sur le fait que ce n'est pas ainsi que les choses doivent être faites. Ma question est: pourquoi?
Remarque: le troisième point est autorisé par les stratégies de PostgreSQL et les stratégies de sécurité de Microsoft SQL Server. Je me rends compte que ces concepts sont des nouveaux venus, mais de toute façon, maintenant qu'ils sont là, pourquoi la technique que je décris ne devient-elle pas le moyen standard de gérer les comptes des utilisateurs?
Réponses:
Parce que pour de nombreuses applications, ils ne veulent pas que des comptes d'utilisateurs individuels se connectent à la base de données. Les utilisateurs / mots de passe / droits / autorisations sont tous gérés au niveau de la couche application, et un seul compte de service dédié est utilisé pour se connecter au serveur principal de la base de données.
En tant que DBA, je ne veux pas avoir à gérer, au niveau de la base de données, les 10 000 utilisateurs actifs d'une application Web publique de taille moyenne, ou peut-être les 2 millions et plus d'utilisateurs d'une application soudainement populaire.
Dans un sens très réel, il s'agit d'une différence de philosophie entre les développeurs d'applications et les développeurs de bases de données / DBA.
Beaucoup / la plupart des développeurs d'applications ne voudront pas transférer la responsabilité des principaux aspects de la fonctionnalité de l'application et / ou des règles métier à la couche de base de données. Au lieu de cela, ils voient la base de données comme un outil pour simplement stocker et récupérer des données.
Dans certains cas, cela peut être à courte vue; de nombreux SGBDR ont des fonctionnalités impressionnantes qui pourraient faciliter la vie des développeurs d'applications (sécurité au niveau des lignes, index en colonnes, stockage de flux de fichiers, etc.).
Mais certaines de ces fonctionnalités plus cool ne sont disponibles que dans les versions plus récentes, et les organisations ne sont pas toujours rapides à mettre à niveau les environnements existants (voir ce tableau de 2014 ).
Et dans d'autres cas, la gestion de ces choses au niveau de la couche application est préférée (et pas seulement pour la portabilité de la plate-forme de base de données, je pense franchement que la revendication est exagérée).
la source
La ligne de démarcation devient un peu duveteuse à ce stade, mais je considérerais que les utilisateurs et les autorisations au niveau de la base de données font partie du schéma et ne font pas partie des données, et en général, les applications n'ont pas leur place pour modifier le schéma (il y a, comme toujours, exceptions à cette règle).
Je préfère ne pas donner aux applications les autorisations dont elles ont besoin pour gérer les objets de schéma (connexions, utilisateurs et autorisations) car de nouveaux utilisateurs sont nécessaires et les anciens quittent, car si cette application est piratée, l'attaquant a alors accès à ces autorisations ce qui facilite l'ouverture de la base de données. Dans MS SQL Server, à moins que vous n'utilisiez des bases de données entièrement contenues, les connexions sont des objets de niveau serveur, vous devez donc distribuer des droits au-delà de la base de données d'application unique, ce qui la rend encore plus risquée.
De plus, même si vous avez des comptes d'utilisateurs par application au niveau de votre base de données, vous avez toujours besoin de comptes d'utilisateurs au niveau de l'application pour traiter les demandes non authentifiées - c'est-à-dire si l'application a besoin d'informations de la base de données avant que l'utilisateur de l'application ne s'authentifie avec succès (peut-être pour afficher les informations d'état sur l'écran d'accueil / de connexion?).
De plus, si la portabilité entre les moteurs de base de données est un objectif (peut-être que votre application veut pouvoir fonctionner à la fois sur mysql et sur postgres?), Vos applications devront résumer les fonctions de gestion des utilisateurs / connexions pour chaque moteur car elles ne sont pas standard entre elles - si vous faites cet effort, vous pourriez aussi bien implémenter vous-même les mots de passe et obtenir les options de gestion que vous désirez au lieu d'accepter le jeu de fonctionnalités commun le plus bas que les moteurs offrent.
la source
Reformuler la question
La réponse la plus simple est que vous devez le faire. Vous conservez toujours les mots de passe dans votre méthode alternative. C'est juste que vous utilisez le système intégré de la base de données pour gérer le stockage. Votre méthode est donc aussi bonne que celle de votre base de données. C'est peut-être encore mieux que ce que vous pourriez faire autrement, mais cela n'évite pas le stockage. Cela évite vraiment de coder le stockage.
Cela pourrait aussi ne pas être mieux. Si je compromets une base de données et obtiens des copies des fichiers, je peux accéder directement aux tables. Il n'y a donc aucun intérêt à utiliser un système de gestion de mots de passe génial. Parce que si quelqu'un peut accéder à la table de niveau système contenant les mots de passe ou les mots de passe hachés, il peut également accéder directement aux fichiers. Pourquoi s'embêter à casser des mots de passe alors que vous avez déjà les données? Ce n'est pas comme si vous pouviez chiffrer les données facilement non plus. Chaque utilisateur doit pouvoir y accéder. Le chiffrement au niveau utilisateur ne fonctionnera donc pas aussi bien.
Mais ce que vous semblez vraiment demander, c'est
Sécurité
Ignorant la possibilité que vous puissiez écrire une version plus sécurisée, d'autres ont suggéré un certain nombre de raisons. Je suis généralement d'accord. Mais il y en a un autre que personne n'a encore mentionné. Vous compromettez la sécurité de votre base de données.
Dans ce système, chaque utilisateur de votre application possède un utilisateur de base de données et un mot de passe. Bien sûr, c'est un utilisateur limité, mais c'est toujours un utilisateur qui peut se connecter à la base de données. Même si vous utilisez la sécurité au niveau des lignes, vous autorisez toujours les utilisateurs finaux à connaître les informations de connexion à la base de données. S'il y a un exploit où un utilisateur peut obtenir un accès égal au niveau de la table, vous avez ouvert votre base de données pour attaquer. Et certains exploits sont allés au-delà de cet accès administrateur.
Dans les couches de l'oignon de sécurité, le système normal est:
Dans ce système:
Nous avons perdu tout le niveau de sécurité de l'application. Et nous avons volontairement abandonné une partie de la couche de base de données. Nous n'avons donc besoin que de deux exploits:
Si nous pouvons faire ces deux choses, nous avons accès à la base de données. On passe donc de trois couches à deux. (La troisième couche du système normal est que vous avez besoin d'un utilisateur valide pour vous connecter à la base de données.)
Vous allez faire beaucoup de gestion de ces comptes. Et si vous vous trompez? Au lieu de limiter l'utilisateur X à certaines lignes seulement, vous leur donnez tous accès à une table critique. Ce genre de choses se fait normalement manuellement et il n'y en a que quelques-unes, donc elles sont faciles à auditer. Mais dans votre système, vous pourriez créer des milliers, voire des millions, voire des milliards de comptes d'utilisateurs, chacun avec son propre accès idiosyncrasique.
D'ailleurs, le système de la base de données s'adapte-t-il à des millions ou des milliards d'utilisateurs? Si c'est le cas, qu'en est-il du nombre de règles? Si chaque utilisateur adopte une centaine de règles ou plus sur ce qu'il peut et ne peut pas accéder, cela peut-il atteindre un milliard d'utilisateurs? Vous prenez un système normalement à petite échelle et vous le faites à grande échelle. Cela ne fonctionnera pas nécessairement. Vous pouvez rencontrer des limitations du système à mesure que vous grandissez.
la source
Ce que vous décrivez gérera l'authentification, mais pas l'autorisation (quelles données l'utilisateur peut accéder) ou uniquement dans le cas d'utilisation le plus simple.
Pour continuer sur votre exemple avec stackexechange: Comment feriez-vous pour que le message supprimé ne soit visible que pour les utilisateurs de haut niveau? Donc, pour les règles d'accès, vous aurez toujours besoin de logique dans le code. Au lieu de partager la logique d'accès entre les règles de base de données et les règles d'accès applicatives, la plupart des développeurs préfèrent les avoir toutes au même endroit.
Vous aurez également besoin d'une table pour stocker les informations utilisateur: un utilisateur n'est pas seulement un nom d'utilisateur + mot de passe. Il a un e-mail, une réputation, etc. Vous avez donc toujours besoin de la table utilisateur, dont vous devez vous assurer qu'elle est synchronisée avec la table utilisateur de la base de données, à condition que vous puissiez y accéder.
Avec votre solution, vous pouvez simplement omettre une colonne de mot de passe, ce qui n'est pas si difficile à remplir: il existe de bonnes bibliothèques et une bonne documentation sur la façon de gérer / hacher les mots de passe.
Autre point: comment créer un pool de connexions? Je ne connais que jdbc (java <-> db), et vous devez fournir un nom d'utilisateur + mot de passe pour obtenir une connexion, que vous pourrez ensuite regrouper.
J'ai pensé à d'autres points qui seront plus difficiles / plus compliqués à mettre en œuvre qu'avec la méthode établie:
la source
CREATE POLICY deleted_posts_high_rep ON posts FOR SELECT TO baseuser USING ((SELECT rep FROM users WHERE name = current_user()) > 10000)
répond à votre première question. Je n'ai jamais dit que je n'avais plus besoin d'une table d'utilisateurs, et assurer la synchronisation avec la table d'utilisateurs db est quelque peu délicat mais possible. Le point principal de la technique discutée est la sécurité. Quant au pool de connexions, je travaille avec OCaml et je dois dire que je ne comprends pas pourquoi j'aurais besoin d'un pool de connexions. J'utilise actuellement une carte de hachage associant les valeurs des cookies aux fonctions 0-aire renvoyant des connexions :-)Autre point: de nombreuses [1] applications Web vous permettent de vous inscrire et de créer un compte utilisateur en ligne via l'application elle-même. Cela signifie que votre utilisateur anonyme (qui devrait avoir le moins de privilèges que l'on pourrait supposer) doit avoir le droit de créer des utilisateurs et d'accorder des privilèges!
OK, il peut être possible de limiter les privilèges qu'il pourrait accorder, et de donner aux utilisateurs de niveau supérieur plus d'options d'octroi (je ne suis pas conscient que c'est le cas - n'est-ce pas "accorder des privilèges" un seul privilège souvent). Mais encore, cela signifie mettre en ligne quelque chose avec des privilèges de subvention pour que tout le monde puisse pirater. Je suis sûr que mon DBA ne m'aimerait pas si je faisais ça :)
Je sais qu'à un certain niveau, ce problème existe de toute façon, mais vous avez des couches de défense, en particulier pour supprimer des données, si vous ne permettez pas à l'application Web de gérer les utilisateurs de la base de données.
En outre, cela empêcherait toute utilisation de connexions DB regroupées ou réutilisées.
[1] La plupart je dirais, mais pas les chiffres pour le confirmer
la source