Attention avec les variables d'ENV

L’amélioration des techniques de déploiement fait partie du manifeste des 12 facteurs, c’est pourquoi de nombreux langages de programmation et frameworks incluent des outils et des librairies externes pour faciliter l’utilisation des variables d’environnement.

Cependant, certaines pratiques peuvent introduire du risque. Voyons ce que sont ces fameuses variables d’ENV et comment sécuriser leur utilisation.

Charger des fichiers de configuration

Les applis modernes font souvent appel aux variables d’environnement. Il n’est pas rare d’utiliser des fichiers .env où on peut écrire une série de clés-valeurs.

Chaque environnement (ex: staging, dev, prod) a son propre fichier .env avec ses propres valeurs. Seules les clés restent les mêmes.

N.B.: A noter que certains environnements ont besoin de clés supplémentaires, pour gérer le débug par exemple

L’appli va charger l’environnement depuis ce fameux fichier de configuration qui contient bien souvent des identifiants et des secrets. C’est pratique mais cela peut s’avérer dangereux et présenter certains inconvénients:

  • les fichiers .env sont souvent committés dans git
  • les fichiers .env sont parfois carrément déployés en prod dans un répertoire accessible publiquement
  • maintenir ces fichiers peut rapidement devenir pénible

Les attaquants énumèrent ce genre de fichiers à la vitesse de la lumière grâce à des outils gratuits comme Gobuster ou Nikto (et beaucoup d’autres). Il y a bien quelques solutions de fortune:

  • changer les permissions des fichiers .env, par exemple chmod 600 .env
  • interdire l’accès ces fichiers via le .htaccess, la config nginx, ou Web.Config (IIS)
  • placer ces fichiers dans un répertoire qui n’est pas accessible via le web

Allons droit au but: aucune de ces “solutions” n’est valable à long terme. Elles permettent d’établir une sorte de fine corde de sécurité supplémentaire, mais un changement de configuration volontaire ou accidentel est vite arrivé.

Dans le dernier scénario, le serveur pointe la racine du site vers un sous-dossier, par exemple Public/, au lieu d’exposer tous les dossiers:

├── .gitignore
├── Public/
│   ├── style.css
│   └── index.php
├── Config/
│   ├── .env
│   └── config.json
└── README.md

Cette structure imaginaire place le fichier .env en dehors de la racine web. Un exemple moins théorique peut concerner WordPress et le fichier wp-config.php qui contient les identifiants vers la base de données.

Certaines approches alternatives comme Bedrock peuvent améliorer significativement la sécurité. Le framework utilise les variables d’ENV pour stocker des informations et permet d’écraser certaines configurations facilement suivant les environnements.

Maintenant, c’est loin d’être parfait:

  • le framework ne vous laissera pas faire absolument tout ce que vous voulez
  • migrer une installation classique vers ce type d’architecture peut entraîner des bugs
  • suivant votre approche du versioning, cela n’éliminera pas le problème des identifiants stockés en clair (ex: configuration de dév)

Comment fonctionnent ces variables d’ENV

Démarrage

Chaque variable d’ENV a un nom et une valeur associée. Le nom est bien souvent en lettres capitales:

MY_ENV_VAR="ma valeur"

Techniquement, vous pourriez écrire le nom en minuscule, mais les majuscules sont une convention qu’il vaut mieux respecter. Sur une machine de type Linux, on peut utiliser la commande env (sans option) pour afficher les variables d’ENV disponibles.

Ces variables sont utilisées par bon nombre de processus (~ programmes), et leurs valeurs peuvent modifier les comportements. Par exemple, $PATH, la variable d’ENV qui contient des chemins, vous permet d’utiliser des commandes sans avoir à entrer le chemin vers le binaire associé à chaque fois.

Pour le dire très schématiquement, la plupart des systèmes d’exploitation vont fonctionner de cette manière, avec des processus dérivant d’autres processus. Durant ces operations, les variables d’ENV sont disponibles de manière implicite.

Sur votre machine, vous pouvez utiliser export pour définir une nouvelle variable d’ENV:

export MY_ENV_VAR="ma valeur"

Comment créer des variables d’ENV persistantes

La variable n’est disponible que pour les processus enfants et sera détruite avec la session en cours. Autrement dit, si vous tapez exit ou que vous fermez la fenêtre, la variable est morte.

Pour la faire persister, on peut utiliser export et sauvegarder la ligne dans le fichier .bash_profile ou .bashrc.

Ça marche bien mais n’allez pas stocker des identifiants dans des variables d’environnement, car beaucoup trop de programmes y auraient accès de fait.

Variables d’ENV vs. variables de shell

MY_ENV_VAR="the value" et export MY_ENV_VAR="the value" n’ont pas du tout le même objectif. La première définit une variable locale.

Si vous souhaitez la transmettre aux processus enfants, il faut utiliser export pour convertir cette variable locale en variable d’ENV.

Ne jamais stocker un identifiant dans une variable d’ENV

La nature-même d’une variable d’ENV devrait nous dissuader d’y stocker des identifiants:

  • chaque processus enfant hérite des variables d’ENV automatiquement, ce qui peut concerner beaucoup de programmes qui n’ont pourant aucun intérêt d’accéder à cette information
  • le système va créer des logs contenant les valeurs des variables d’ENV en clair (ex: débug, logs d’erreur, outils tiers)
  • les hackers peuvent utiliser env ou printenv pour les afficher après avoir exploité une vulnérabilité pour accéder au shell

Bonnes pratiques et alternatives

  • ne mettez pas toutes les variables d’ENV au même niveau
  • n’utilisez pas les mêmes clés d’API sur tous les environnements
  • soyez vigilants avec les tokens et autres secrets ainsi que les permissions utilisateurs, en particulier avec les architectures cloud
  • utilisez des secrets encryptés. Par exemple, GitHub fournit une interface assez pratique pour stocker des secrets et gérér les accès avec granularité
  • utilisez des solutions d’intégration continue CI/CD pour abstraire les variables d’ENV et les mettre à jour via des APIs sécurisées
  • si vous utilisez Kubernetes, mieux vaut utiliser leurs “secrets”, mais soyez conscients qu’ils ne seront pas encryptés par défaut

Conclusion

Les variables d’ENV sont accessibles à peu près partout, ce qui est très pratique pour le development web mais peut mener à des fuites d’information et des escalades de privilèges assez tendues.

Les solutions alternatives ne sont pas toujours triviales à implémenter, loin de là, et on ne règle pas tous les problèmes simplement en évitant les variables d’ENV, mais stocker des identifiants en clair reste une mauvaise pratique à éviter.

A voir aussi