Fichiers .env exposés et clés divulguées

Un fichier .env exposé est un fichier de configuration — celui qui contient le mot de passe de votre base de données, vos identifiants de messagerie et vos clés API — que votre serveur web remet à quiconque le demande par son nom, et un dossier .git exposé est le même accident avec tout votre historique de code en pièce jointe. Ni l’un ni l’autre n’exige qu’un attaquant casse quoi que ce soit : le fichier se trouve simplement à un endroit que le serveur publie, et une seule requête GET ordinaire le télécharge. Cet article explique comment cela arrive — erreurs de racine documentaire, hébergeurs statiques qui servent le dépôt lui-même, artefacts de build que personne n’a audités —, ce que celui qui le trouve fait des clés dans la première heure, et pourquoi supprimer le fichier ensuite est la plus petite partie de la réponse. Pour vérifier votre propre site maintenant, lancez le scanner de secrets divulgués et lisez avec vos résultats.

Comment un fichier privé devient public : la racine documentaire

Chaque serveur web a une racine documentaire : le répertoire dont le contenu est public par définition. Tout ce qui y est placé — volontairement ou par accident — peut être demandé par URL, qu’une page y mène ou non. L’accident classique est un projet déployé en copiant tout le répertoire de travail sur le serveur : le code de l’application, qui a sa place là, arrive avec le fichier .env à côté de lui, le dossier .git en lui, les copies de sauvegarde d’éditeur, le dump de base de données que quelqu’un a fait avant la migration et l’archive de la version du mois dernier. Le serveur ne distingue pas ces choses. Il sert des fichiers ; les privés sont aussi des fichiers.

Les conventions des frameworks rendent le piège facile. Un fichier .env est censé se trouver un niveau au-dessus de la racine documentaire, ou entièrement hors de l’arbre déployé, l’application le lisant depuis le disque — jamais à travers le serveur web. Mais les serveurs de développement servent volontiers la racine du projet, les petits déploiements traînent tout dans public_html, et une configuration copiée d’un tutoriel peut pointer la racine documentaire sur le projet lui-même. Rien ne se casse visiblement quand cela arrive, et c’est exactement le problème : le site fonctionne parfaitement, le fichier est public, et le premier à le remarquer est celui qui demande /.env — une requête que les scanners automatisés adressent à chaque site d’internet, sans relâche.

Hébergeurs statiques, dépôts servis et artefacts de build

L’hébergement statique retire la configuration du serveur de l’équation et la remplace par une règle plus simple : ce qui est dans le répertoire de publication est publié. Déployez un dépôt chez un hébergeur statique avec le répertoire de sortie placé à la racine du projet et l’hébergeur servira fidèlement le dépôt — .git inclus, s’il a été copié dans la sortie. Un .git exposé est pire qu’il n’y paraît : le fichier HEAD et la configuration prouvent la structure, les fichiers d’objets contiennent chaque blob jamais commité, et avec l’outillage Git ordinaire tout l’historique peut être reconstruit — y compris les secrets commités une fois et « supprimés » dans un commit ultérieur, ce qui les retire de l’arbre de travail et de nulle part ailleurs.

Les artefacts de build créent une seconde classe d’exposition, plus silencieuse. Les bundlers JavaScript inlinent ce que le code référence, donc une clé API lue depuis une variable d’environnement au moment du build peut finir comme une chaîne littérale dans le bundle livré — public par conception, lisible par chaque visiteur, et jamais signalé par aucun contrôle de permissions, parce que ce fichier devait être public. Les source maps aggravent la chose en livrant le code source original à côté du bundle. Rien de tout cela n’exige un serveur mal configuré ; il suffit d’un build qui n’a jamais été inspecté de l’extérieur.

Le troisième motif est le reste oublié : des scripts de déploiement qui décompressent une archive dans la racine web et y laissent l’archive, des extensions de sauvegarde qui écrivent des dumps dans un dossier accessible par le web, un config.php.bak enregistré par un éditeur — que beaucoup de serveurs servent en texte brut précisément parce que l’extension ne correspond plus au gestionnaire PHP. Chaque reste est une copie complète de quelque chose de privé, à une adresse prévisible.

Ce que font les attaquants dans la première heure

La découverte est automatisée et constante. Les scanners énumèrent les chemins connus — fichiers env, intérieurs de Git, noms de configuration, extensions de sauvegarde — sur d’immenses plages d’adresses, et une exposition fraîche est en général trouvée en quelques heures, souvent plus vite. Ce qui arrive sur votre serveur est une requête GET banale qui renvoie 200 ; il n’y a pas d’alarme, parce que du point de vue du serveur rien d’inhabituel ne s’est produit. Partez donc du principe que tout fichier public pendant un jour a été téléchargé, et que la charge de la preuve court dans l’autre sens.

Le tri est automatisé aussi. Un .env téléchargé est analysé en quelques secondes : les identifiants de base de données sont testés contre tout port joignable, les clés cloud sont validées par un appel API inoffensif qui dit si elles sont vivantes, les identifiants de messagerie sont essayés pour envoyer, et les clés de paiement sont vérifiées quant à leur mode — une clé de paiement en mode réel et des identifiants de production sont le gros lot, parce que chacun se convertit directement en argent ou en données. Les clés valides sont utilisées, échangées ou conservées vite, parce que leurs propriétaires peuvent les faire tourner à tout moment ; la première heure est celle où une clé exposée vaut le plus, et elle est dépensée efficacement.

Pourquoi supprimer le fichier ne suffit pas

Supprimer le fichier arrête les nouveaux téléchargements. Cela ne fait rien pour les copies qui existent déjà : celle de celui qui l’a trouvé, évidemment, mais aussi celles que vous avez faites vous-même — la réponse mise en cache par votre CDN ou un proxy d’entreprise, l’instantané dans le crawl d’un moteur de recherche ou d’un service d’archives, le bundle qu’un navigateur a déjà téléchargé. Tant que chaque cache n’est pas purgé et n’a pas expiré, le fichier « supprimé » peut encore être servi par une infrastructure que vous contrôlez mais avez oublié de nettoyer, et la version hors de votre contrôle y est pour toujours.

C’est pourquoi la première réponse à une exposition confirmée est la rotation, pas la suppression : révoquez l’identifiant exposé et émettez-en un nouveau, pour que chaque copie au monde devienne sans valeur au même instant. La rotation a un ordre — émettre le remplaçant, le déployer, vérifier que le service fonctionne, puis révoquer l’ancien identifiant — et elle s’étend à tout ce que le matériau exposé peut ouvrir : une exposition .git signifie faire tourner chaque secret jamais apparu dans l’historique, pas seulement les actuels, parce que ce qui est divulgué, c’est l’historique. Ensuite, lisez vos journaux d’accès pour les chemins exposés : ils vous disent si vous avez été le premier à savoir, et les récupérations antérieures transforment un incident de configuration en une enquête de violation avec une liste très différente.

La liste de sondes, expliquée — et la liste de prévention

Un scanner comme le scanner de secrets divulgués ne peut demander des fichiers que par leur nom, donc sa liste est l’ensemble connu : /.env et ses variantes d’environnement, /.git/HEAD et /.git/config, les noms de configuration familiers, les extensions de sauvegarde et d’archive, et les noms de fichiers de clés — plus les propres scripts de la page, cherchés pour des chaînes en forme de clé. La limite honnête coupe dans les deux sens : un scanner ne trouve que ce qu’il demande, et c’est pourquoi il confirme une trouvaille par le contenu, pas par le code de statut. Un 200 qui renvoie votre page d’accueil est une route attrape-tout, pas une fuite, et tout rapport qui le compte comme telle se gonfle lui-même. Le risque de chaîne d’approvisionnement lié — les scripts que vous chargez délibérément chez d’autres — est traité dans scripts tiers et risque de chaîne d’approvisionnement.

Prévenir est surtout une affaire de placement et d’une couche de refus. Gardez les secrets hors de la racine documentaire et hors de la sortie de publication du dépôt ; faites refuser au serveur les noms dangereux même s’ils y atterrissent — règles de refus pour les fichiers à point, les extensions env et de configuration, les archives et le matériau de clés, testées en les demandant — ; retirez .git des artefacts de déploiement ou bloquez-le net. Dans le pipeline, ajoutez l’analyse de secrets en CI — sur les commits, pour qu’une clé soit arrêtée avant d’être livrée, et sur l’artefact construit, pour qu’une clé intégrée au bundle soit attrapée dans la sortie plutôt que par un étranger. Enfin, scannez vous-même régulièrement et après chaque changement de déploiement : les expositions de cet article sont toutes silencieuses, et la seule façon d’apprendre la vôtre avant quelqu’un d’autre est de poser à votre propre serveur les mêmes questions que posent les scanners.

Sources et lectures complémentaires

Questions fréquentes

J’ai supprimé mon fichier .env exposé. Suis-je en sécurité maintenant ?

Pas encore. La suppression arrête les nouveaux téléchargements, mais des copies peuvent exister entre les mains de celui qui l’a trouvé, dans les caches CDN et proxy, et dans les crawls et archives. Faites tourner chaque identifiant que le fichier contenait — révoquez les anciennes clés et émettez-en de nouvelles —, purgez vos caches et examinez les journaux d’accès du chemin. Seule la rotation rend les copies sans valeur.

Mon site renvoie 200 pour /.env. Le fichier est-il exposé ?

Pas nécessairement. Beaucoup de sites répondent à chaque chemin inconnu avec un 200 et leur page d’accueil ou leur coquille d’application — un repli attrape-tout. Ce qui compte, c’est le contenu : si le corps de la réponse est votre page, rien n’est exposé ; si ce sont des lignes clé–valeur avec de vraies valeurs, il l’est. Un scanner digne de confiance confirme par le contenu et liste les 200 nus à part comme non confirmés.

Que doit exécuter la CI pour que cela ne se reproduise pas ?

Deux contrôles à deux moments : un scanner de secrets sur le commit, qui empêche une clé d’entrer dans le dépôt, et un contrôle de l’artefact construit et du répertoire de sortie déployé, qui attrape ce que le build a inliné et ce que le déploiement a copié. Ajoutez les règles de refus du serveur pour les fichiers à point et le matériau de clés comme dernière couche, et relancez une sonde externe après les changements de déploiement.