Une vulnérabilité Nginx qui expose le coffre-fort de Bitwarden
(labs.hakaioffsec.com)- Nginx, serveur web polyvalent qui domine le marché avec une part majeure depuis 2004
- Une mauvaise configuration de Nginx peut entraîner des failles de sécurité et une exposition de données
- Présentation de NavGix, un outil automatisé pour détecter les vulnérabilités de Nginx
- Cette vulnérabilité peut permettre d’accéder à des fichiers et répertoires au-delà du périmètre prévu
- Des études de cas sur Bitwarden et le HPC Toolkit de Google montrent la gravité de cette vulnérabilité
1 commentaires
Commentaires Hacker News
Pour information, gixy (un vérificateur de configuration nginx) détecte ce problème : https://github.com/yandex/gixy/blob/master/docs/en/plugins/a...
Et NixOS exécutait automatiquement gixy sur les configurations générées via son système, en refusant le build du système s’il y avait un problème
$uridans une redirection 301Par contre, je me demande s’il existe un meilleur chercheur d’options. Je n’aimais pas devoir chercher dans l’ensemble des milliers d’options ; j’aimerais pouvoir regarder seulement un paquet comme
sshpuis voir uniquement les options qui s’y rapportent, mais il y a trop de résultats sans rapportC’est peut-être une question bête, mais y a-t-il une bonne raison pour que nginx autorise la remontée vers le répertoire parent avec
..dans le chemin d’URL ? Ça ressemble juste à un comportement qui attend les problèmesÉdition : je suis un peu confus sur ce qui se passe exactement dans la vulnérabilité d’origine. On dirait que http://localhost/foo../secretfile.txt est interprété comme quelque chose du genre
/var/www/foo/../secretfile.txt, mais alors, sur un serveur non vulnérable, pourquoi http://localhost/foo/../secretfile.txt ne serait-il pas interprété de la même façon ? Je ne comprends pas pourquoi..dans le chemin ne fonctionne que dans certains casDans ce cas, une partie de l’URL est interprétée comme un répertoire (http://localhost/foo) par nginx à cause de la façon dont la configuration la mappe au système de fichiers local. Comme cela semble désigner un répertoire, nginx construit alors le chemin complet de la ressource demandée comme
"${mapped_path}/../secretfile.txt", ce qui n’a aucun sens du point de vue de l’URL mais devient valide sur le système de fichiers local. Une URL n’est qu’une chaîne, pas une vraie suite d’éléments de chemin, donc la position des slashs n’a pas d’importance intrinsèqueC’est un problème qu’on voit très souvent, dans tous les serveurs web, depuis les débuts du Web. Le mapping direct des URL vers des chemins de fichiers était populaire parce qu’on partait de simples serveurs de fichiers avec index, puis on est vite passé à des environnements hybrides où l’URL n’était plus un chemin mais un identifiant d’application. On désignait l’application avec une partie du chemin, et le reste devenait des paramètres ou des arguments
Et de manière générale, respecter
.ou..de l’URL pour des objets du système de fichiers n’a généralement pas de sens. Mes applications normalisent les chemins de requête pour garantir un mapping correct. Les navigateurs, eux, traitent les URL comme des chemins lorsqu’ils construisent des liens relatifs, donc il faut aussi faire attention à l’usage du/final selon les cas. Cela peut pointer vers des ressources dont le sens côté serveur est différentlocationun drapeau du typeallow_parent_traversal on;et d’en faire un comportement activé explicitement"/foo/bar/.."et l’interdit ou le normalise en"/foo/". Mais"/foo/bar.."est un nom de fichier tout à fait valide, donc ce type de vérification semble lui échapper..fonctionne ou non dans un chemin dépend entièrement des permissions de fichiersDans ce cas, si l’on suppose que depuis le répertoire d’index web (
../index.html) on a le droit de lire jusqu’au répertoire racine (/), alors une fois qu’on peut remonter jusqu’à la racine, on peut aussi voir tous les fichiers lisibles par tous accessibles depuis cette racine, par exemple/etc/passwdImaginez une fourche à trois dents : le serveur web se trouve sur la dent tout à droite. Si la partie où les dents se rejoignent représente le système de fichiers, alors, tant que le serveur web a les permissions d’accès sur les fichiers et répertoires allant de sa dent droite jusqu’au manche, une fois arrivé au manche il peut continuer à accéder aux fichiers des autres dents
Je ne vois pas pourquoi cela ne serait pas considéré comme une vulnérabilité nginx. Ce comportement est complètement absurde, ne semble avoir aucun usage bénéfique, et il est immédiatement exploitable
Il faut aussi se rappeler que nginx a gagné en popularité grâce à des benchmarks qui le présentaient comme plus “web scale” qu’Apache2
Je me dis qu’on pourrait faire comme ceci : ajouter une option proche d’une capability Linux qui supprimerait la possibilité d’utiliser
..dans l’analyseur de noms de fichiers du noyau LinuxDans les applis web, il existe depuis l’époque des modems téléphoniques toutes sortes de contournements pour réussir à glisser
..d’une manière ou d’une autre. Comme pour d’autres catégories de bugs en espace utilisateur que le noyau Linux a déjà traitées, il serait peut-être temps de trouver un moyen de fermer ce problème une bonne fois pour toutesRESOLVE_BENEATHdans https://man7.org/linux/man-pages/man2/openat2.2.htmlFreeBSD propose aussi cette fonctionnalité dans
openat(2)standard viaO_RESOLVE_BENEATHIl suffit d’exécuter nginx avec un utilisateur séparé aux privilèges très limités, ou dans Docker. En y ajoutant des mises à jour régulières, on règle en général 90 % des problèmes de sécurité
/some/../pathdevrait être interdit dans presque 100 % des cas. À part « quelqu’un a écrit du code affreux », il n’y a pas de cas d’usage rationnel../some/patha au moins parfois un sensCela dit, ce ne serait sans doute pas aussi utile qu’on l’imagine. Beaucoup d’applis résolvent déjà
..avant de passer le chemin au système d’exploitationSi l’on sert des fichiers d’un dossier vers le web, c’est au framework web de veiller à ne pas sortir du dossier racine public dont il a la charge. Si vous faites cela vous-même, il faut prévoir toutes sortes de situations, y compris celle-ci
« Le Google VRP Team a accordé une récompense de 500 dollars pour la découverte de cette vulnérabilité. Il a estimé que l’impact sur l’application n’était pas assez grave pour justifier une prime plus élevée » : donc l’exposition d’un e-mail de compte GCP et d’une clé privée ne vaut que 500 dollars ? C’est quoi, au juste ? Très Google, en effet
Heureusement, les éléments divulgués étaient encore chiffrés. Même une entreprise spécialisée dans ce domaine n’est pas à l’abri d’une fuite, donc honnêtement, c’est à peu près le meilleur scénario possible
Le titre a été pas mal retouché. Le titre original est Hunting for Nginx Alias Traversals in the wild
Le titre de la soumission HN met l’accent sur la vulnérabilité de Bitwarden, mais l’article traite aussi du cas de Google
Si l’on a seulement besoin d’un serving de fichiers statiques sûr et fiable, avec une consommation minimale de ressources, quelle est aujourd’hui la meilleure option ? Autrefois, j’aurais choisi Nginx, mais du point de vue de la sécurité, je me demande s’il ne vaut pas mieux un outil plus spécialisé et moins configurable
C’est multiplateforme, écrit en Rust, la configuration est simple, et les valeurs par défaut sont sûres. Il existe aussi une image de conteneur durcie et un module NixOS durci
Je ne recommande pas Caddy. Son image Docker officielle s’exécute en tant que root par défaut [1], et il ne fournit pas non plus de fichier d’unité systemd correctement sandboxé [2]
[1]: https://github.com/caddyserver/caddy-docker/issues/104
[2]: https://github.com/caddyserver/dist/blob/master/init/caddy.s...
Édition : formulation ajustée
file_serverQuestion peut-être stupide, mais pourquoi Bitwarden autorisait-il au départ des requêtes non authentifiées vers
/attachments? Même avec un bug Nginx, si cette URL avait nécessité une authentification, la requête n’aurait-elle pas échoué ?Cela dit, Bitwarden reste responsable d’avoir déployé cette configuration risquée via Docker. Bitwarden semble d’ailleurs l’avoir reconnu et l’a corrigée par la suite
Désolé pour cette question idiote. Une propriété correcte des répertoires et des fichiers ne bloque-t-elle pas ce type de traversée ?
Si nginx ne s’exécute pas en root, comment peut-il lire autre chose que les fichiers explicitement attribués à l’utilisateur nginx ?
go-rwxsur tous les fichiers de l’app, de définir le groupe des fichiers « static » surwww-data, puis de ne donner queg+r; ainsi le serveur web ne peut pas accéder aux fichiers de l’appC’est littéralement les bases de l’hébergement d’applications, et c’est comme ça que les gens faisaient déjà il y a 20 ans
/homeIl faudra peut-être ajuster un peu plus l’appartenance aux groupes, mais ça en vaut largement la peine
Je suis peut-être en train de faire une énorme bêtise. Aïe
www-data. Si l’application génère des données sensibles, il est évidemment préférable d’utiliser un umask 077Malheureusement, nginx et les autres serveurs web doivent généralement s’exécuter en root dans une application web classique, parce qu’ils doivent écouter sur les ports 80 ou 443. Les ports inférieurs à 1024 ne peuvent être ouverts que par root
Plus d’explications ici : https://unix.stackexchange.com/questions/134301/why-does-ngi...