web-dev-qa-db-fra.com

Le stockage de données sensibles dans des fichiers au lieu d'une base de données est-il sûr?

Disons que j'ai une hypothétique application PHP qui stockera les mots de passe hachés dans un fichier du même répertoire. Au début, cela semble très peu sûr, car on pourrait deviner le nom du fichier et ouvrez-le via un navigateur Web (http://example.com/php-app/hashed_passwords.txt).

Cependant, je me demandais quel était le niveau de sécurité que cela fournirait en utilisant différentes méthodes:

  • La sécurité par l'obscurité: donner au fichier texte un nom absurde qui serait difficile à deviner (hashed_password_wefhbweifvbewuivgbwueigfvu4gf.txt)
  • Donner au fichier texte une certaine extension de fichier (hashed_password.secret), et demandant au serveur Web de renvoyer un 403 lorsqu'il est demandé
  • Chiffrement du fichier texte avec une clé codée en dur dans l'application PHP
  • Stocker les informations dans une partie commentée d'un fichier PHP, donc il ne peut être lu que depuis le backend (et retournera un fichier vierge dans un navigateur Web)

Par rapport à une base de données, ces méthodes sont-elles plus ou moins sécurisées et pourraient-elles fournir un niveau de sécurité raisonnable (à peu près celui d'une base de données) contre les attaquants?

7
Redwolf Programs

La meilleure mesure pour ce faire est de stocker ce fichier dans un répertoire en dehors de la racine Web.

Fondamentalement, toutes les solutions "résolvent" le problème en rendant le fichier de mot de passe non disponible. Leurs différences proviennent du type d'erreur de configuration qui doit se produire pour qu'il se brise.

Étonnamment, de telles erreurs de configuration se produisent de temps en temps (par exemple lors de la mise à jour ou de la réinstallation d'un système) et les solutions varient simplement selon leur robustesse. De plus, ces configurations sont parfois définies dans des fichiers .htaccess, mais une configuration a ensuite été modifiée sur le serveur et n'a pas été appliquée.

  1. Arrête si le serveur Web a généré une liste d'index.
  2. Échoue si l'élément configurant le serveur Web pour ne pas servir les fichiers .secret n'a pas été ajouté/appliqué, ou si un éditeur a laissé un fichier de sauvegarde avec une extension non protégée
  3. Échouerait si les fichiers PHP n'étaient pas interprétés (mod_php non chargé?) Ou si le mot de passe n'était pas modifié par défaut.
  4. Échouerait également si les fichiers PHP n'étaient pas interprétés

Placer le fichier en dehors de la racine Web (par exemple. /etc/php-app/hashed_passwords.txt) Rend plus difficile son téléchargement par un acteur malveillant.

Évidemment, rien ne vous empêche de combiner plusieurs de ces méthodes (bien qu'à un moment donné cela vous gagnerait peu).

Remarque: si vous utilisez la route .php, vous devez vous assurer qu'un utilisateur malveillant ne peut pas insérer de code dans les fichiers générés, ce qui entraîne une vulnérabilité d'exécution de code. Généralement, cela signifie que vous mourrez au début (par exemple, en démarrant le fichier avec <?php die(1);). Vous pouvez également utiliser __ halt_compiler pour vous assurer qu'aucune partie du reste du fichier n'est interprétée par PHP.

La principale différence que je vois sur l'utilisation de fichiers par rapport à la connexion à un serveur de base de données (notez que vous seriez confronté au même dilemme sur la façon de nommer le fichier si vous avez utilisé SQlite) serait sur sa robustesse pour les conditions de concurrence. Supposons qu'un utilisateur effectue une action de changement de mot de passe en même temps qu'un autre s'inscrit. Une implémentation naïve utilisant des fichiers serait vulnérable à une condition de concurrence où l'utilisateur récemment créé serait perdu lors du remplacement du fichier par le nouveau hachage de mot de passe, tandis qu'une base de données s'en occuperait automatiquement (une implémentation naïve serait vulnérable à l'injection SQL, bien que).

D'autres différences concernent les autorisations, les sauvegardes et l'évolutivité:

  • Si l'application se connecte à une base de données, le code lui-même pourrait être en lecture seule sur le système de fichiers, tandis que les fichiers contenant des informations stockées doivent y accéder en écriture (et si vous utilisez des fichiers .php, ils doivent pouvoir écrire dans un fichier où le code pourrait être exécuté s'il est écrit dedans, donc une vulnérabilité d'écriture de fichier deviendrait automatiquement une vulnérabilité d'exécution).
  • S'il existe déjà un système pour sauvegarder le serveur de base de données, c'est plus simple, plutôt que d'avoir à faire une sauvegarde personnalisée d'un fichier au nom étrange. D'un autre côté, l'utilisation d'un fichier signifie que la simple copie du répertoire entraîne une sauvegarde complète, pas besoin de vider la base de données séparément.
  • Si vous finissez par évoluer horizontalement, il est préférable d'utiliser une base de données normale. Souvent, simplement en faisant pointer plusieurs nœuds vers la même base de données, faites-les tous fonctionner (vous devez également partager les sessions). Si vous avez utilisé une base de données de fichiers, cela signifie que vous devrez partager ce fichier (par nfs, peut-être?) Et l'avoir en écriture par les multiples nœuds (avec toute la complication supplémentaire des conditions de concurrence, juste avec plus de nœuds et un système de fichiers moins capable couche).

Et évidemment, l'exécution d'un serveur de base de données impose une certaine surcharge. S'il n'est pas déjà nécessaire d'en utiliser un et que les ressources du serveur sont limitées, il peut être préférable d'utiliser des fichiers simplement pour être plus légers.

Comme vous le voyez, la plupart des raisons qui conduiraient votre décision d'utiliser un fichier par rapport à un serveur de base de données ne concernent pas la sécurité, car vous pourriez avoir une application équivalente sécurisée dans les deux cas.

14
Ángel

Dans un sens arbitraire, une base de données est un fichier - dans les systèmes Unix, elle l'est certainement. Je ne sais pas pourquoi cependant, si vous voulez stocker quelque chose dans un fichier que vous ne voulez pas accessible, vous ne le stockez pas en dehors de la racine Web. Faire cela rend immédiatement inutile les puces un et deux (en plus, la sécurité par l'obscurité n'existe pas).

Le point 4 échoue si un attaquant peut faire vider le fichier sans l'exécuter. Le numéro 3 donne un aspect d'une solution.

Un avantage d'une base de données est le contrôle total des utilisateurs qui peuvent lire et écrire la base de données. Ceux-ci existent dans un sens avec des autorisations de fichier mais pas presque avec le même degré de granularité.

Tout cela ignore les autres avantages d'une base de données, tels que la vitesse d'une recherche dans une base de données; stocker 1000 utilisateurs dans un fichier rend les recherches beaucoup plus difficiles ... les sauvegardes deviendraient également compliquées, et tous les outils dont vous avez besoin pour interagir en toute sécurité avec une base de données sont déjà là. Disons que vous séparez les utilisateurs et les mots de passe par deux points; que faire si un utilisateur soumet un nom avec deux points dans?

Un fichier contenant une ou deux clés, en dehors de la racine Web, chiffré (sans que la clé ne soit codée en dur dans l'application) et lisible uniquement par root et PHP, lorsqu'une base de données n'est pas disponible, peut être justifiable et correct d'un point de sécurité de vue, mais vos solutions répertoriées ne sont pas utiles. J'ai fait cela pour des systèmes où je démontre un premier PoC de la façon dont une telle chose pourrait fonctionner, mais jamais pour aucun service de production.

3
LTPCGO

Les problèmes

La sécurité par l'obscurité: donner au fichier texte un nom absurde qui serait difficile à deviner (hashed_password_wefhbweifvbewuivgbwueigfvu4gf.txt)

Cela n'est sûr que tant que personne n'active la liste des répertoires. Si vous travaillez avec Apache + PHP c'est une bonne règle que votre PHP doit être sécurisé même pour les mauvaises configurations d'Apache. Parce que dans le fin, Dieu sait comment Apache finira par être configuré ...

En outre, il existe un risque de divulgation accidentelle du code source (voir le troisième point).

Donner au fichier texte une certaine extension de fichier (hashed_password.secret), et demandant au serveur Web de renvoyer un 403 lorsqu'il est demandé

Même problème que ci-dessus. Je dirais cependant que c'est une amélioration.

Chiffrement du fichier texte avec une clé codée en dur dans l'application PHP

Un peu mieux, mais toujours pas bon. Vous avez toujours le risque de divulgation accidentelle du code source, qui peut facilement se produire avec une mauvaise configuration ou simplement un commit dans un dépôt public de git.

Le chiffrement du fichier texte et le stockage de la clé de chiffrement ailleurs (voir cette question pour les alternatives) serait bien mieux.

Stocker les informations dans une partie commentée d'un fichier PHP, donc il ne peut être lu que depuis le backend (et retournera un fichier vierge dans un navigateur Web)

Mêmes problèmes que ci-dessus, plus le très grave problème d'exécution de code Ángel écrit . J'éviterais absolument cela.

La solution

Mettez le fichier en dehors de la racine Web! Là, il est moins susceptible d'être servi accidentellement. Espérons qu'il l'exclura également de tous vos dépôts git (il ne devrait pas y être).

Vous pouvez combiner cela avec une combinaison de vos trois premières suggestions. N'utilisez pas le quatrième!

2
Anders
  1. non. tout simplement pas.

  2. -4. Faites très attention à la configuration de votre serveur Web, assurez-vous de mettre des commentaires d'avertissement dans les fichiers de configuration qui le traitent et de bien le documenter. En pratique, cela prolongera la fenêtre de temps moyenne jusqu'à ce qu'un clown désactive accidentellement la configuration appropriée (notoire: des solutions de secours qui renverront des fichiers source en cas d'échec d'un interprète!).

0
rackandboneman

Votre problème principal est que si le fichier est accessible à votre application PHP, alors tout ce qui exploite l'application PHP peut également y accéder. Aucun moyen de contourner cela.

Rendre les choses un peu plus difficiles pour l'attaquant est une bonne idée, mais ne faites pas de demi-mesures. Mettez-le en dehors de la racine Web et en finir avec cela, pourquoi ne le feriez-vous pas?

Une base de données est presque toujours plus sécurisée qu'un fichier. Selon la base de données que vous utilisez, vous pouvez par exemple disposer de contrôles d'accès au niveau des lignes.

Encore plus important est comment vous stockez vos mots de passe. Si vous les hachez et les salez correctement, et peut-être même ajoutez un peu de poivre comme décrit dans cette réponse: Mot de passe haché: ajoutez du sel + du poivre ou est-ce assez de sel?

0
Tom