Bypass FS protections: read-only / no-exec / Distroless
Last updated
Last updated
Si vous êtes intéressé par une carrière en piratage et pirater l'impossible - nous recrutons ! (maîtrise du polonais écrit et parlé requis).
Dans les vidéos suivantes, vous trouverez les techniques mentionnées sur cette page expliquées plus en détail :
Il est de plus en plus courant de trouver des machines Linux montées avec une protection de système de fichiers en lecture seule (ro), notamment dans les conteneurs. Cela est dû au fait qu'il est aussi facile de lancer un conteneur avec un système de fichiers en ro en définissant readOnlyRootFilesystem: true
dans le securitycontext
:
Cependant, même si le système de fichiers est monté en ro, /dev/shm
restera inscriptible, donc nous pouvons écrire sur le disque. Cependant, ce dossier sera monté avec une protection no-exec, donc si vous téléchargez un binaire ici, vous ne pourrez pas l'exécuter.
D'un point de vue d'équipe rouge, cela rend compliqué le téléchargement et l'exécution de binaires qui ne sont pas déjà présents dans le système (comme des portes dérobées ou des outils d'énumération comme kubectl
).
Notez que j'ai mentionné les binaires, vous pouvez exécuter n'importe quel script tant que l'interpréteur est présent dans la machine, comme un script shell si sh
est présent ou un script python si python
est installé.
Cependant, cela ne suffit pas pour exécuter votre porte dérobée binaire ou d'autres outils binaires dont vous pourriez avoir besoin d'exécuter.
Si vous souhaitez exécuter un binaire mais que le système de fichiers ne le permet pas, la meilleure façon de le faire est en l'exécutant depuis la mémoire, car les protections ne s'appliquent pas là.
Si vous disposez de moteurs de script puissants dans la machine, tels que Python, Perl ou Ruby, vous pourriez télécharger le binaire à exécuter depuis la mémoire, le stocker dans un descripteur de fichier en mémoire (create_memfd
syscall), qui ne sera pas protégé par ces protections, puis appeler un appel système exec
en indiquant le fd comme fichier à exécuter.
Pour cela, vous pouvez facilement utiliser le projet fileless-elf-exec. Vous pouvez lui passer un binaire et il générera un script dans le langage indiqué avec le binaire compressé et encodé en b64 avec les instructions pour le décoder et le décompresser dans un fd créé en appelant la syscall create_memfd
et un appel à l'appel système exec pour l'exécuter.
Cela ne fonctionne pas dans d'autres langages de script comme PHP ou Node car ils n'ont pas de moyen par défaut d'appeler des appels système bruts à partir d'un script, il n'est donc pas possible d'appeler create_memfd
pour créer le fd en mémoire pour stocker le binaire.
De plus, la création d'un fd régulier avec un fichier dans /dev/shm
ne fonctionnera pas, car vous ne serez pas autorisé à l'exécuter en raison de la protection no-exec qui s'appliquera.
DDexec / EverythingExec est une technique qui vous permet de modifier la mémoire de votre propre processus en écrasant son /proc/self/mem
.
Par conséquent, en contrôlant le code d'assemblage qui est exécuté par le processus, vous pouvez écrire un shellcode et "muter" le processus pour exécuter n'importe quel code arbitraire.
DDexec / EverythingExec vous permettra de charger et d'exécuter votre propre shellcode ou n'importe quel binaire depuis la mémoire.
Pour plus d'informations sur cette technique, consultez le Github ou :
Memexec est la prochaine étape naturelle de DDexec. C'est un shellcode demonisé DDexec, donc chaque fois que vous voulez exécuter un binaire différent, vous n'avez pas besoin de relancer DDexec, vous pouvez simplement exécuter le shellcode memexec via la technique DDexec et ensuite communiquer avec ce démon pour transmettre de nouveaux binaires à charger et exécuter.
Vous pouvez trouver un exemple de l'utilisation de memexec pour exécuter des binaires à partir d'un shell PHP inversé dans https://github.com/arget13/memexec/blob/main/a.php.
Dans un but similaire à DDexec, la technique memdlopen permet une manière plus facile de charger des binaires en mémoire pour les exécuter ultérieurement. Cela pourrait même permettre de charger des binaires avec des dépendances.
Les conteneurs Distroless contiennent uniquement les composants strictement nécessaires pour exécuter une application ou un service spécifique, tels que des bibliothèques et des dépendances d'exécution, mais excluent des composants plus importants comme un gestionnaire de paquets, un shell ou des utilitaires système.
L'objectif des conteneurs Distroless est de réduire la surface d'attaque des conteneurs en éliminant les composants inutiles et en minimisant le nombre de vulnérabilités exploitables.
Dans un conteneur Distroless, vous pourriez ne pas trouver même sh
ou bash
pour obtenir un shell classique. Vous ne trouverez pas non plus des binaires tels que ls
, whoami
, id
... tout ce que vous exécutez habituellement dans un système.
Par conséquent, vous ne pourrez pas obtenir un shell inversé ou énumérer le système comme vous le faites habituellement.
Cependant, si le conteneur compromis exécute par exemple une application web Flask, alors Python est installé, et donc vous pouvez obtenir un shell Python inversé. S'il exécute Node, vous pouvez obtenir un shell Node, et de même avec la plupart des langages de script.
En utilisant le langage de script, vous pourriez énumérer le système en utilisant les capacités du langage.
S'il n'y a pas de protections lecture seule/sans exécution
, vous pourriez abuser de votre shell inversé pour écrire dans le système de fichiers vos binaires et les exécuter.
Cependant, dans ce type de conteneurs, ces protections existent généralement, mais vous pourriez utiliser les techniques d'exécution en mémoire précédentes pour les contourner.
Vous pouvez trouver des exemples sur la façon d'exploiter certaines vulnérabilités RCE pour obtenir des shells inversés de langages de script et exécuter des binaires en mémoire dans https://github.com/carlospolop/DistrolessRCE.
Si vous êtes intéressé par une carrière en piratage et pirater l'impossible - nous recrutons ! (polonais écrit et parlé couramment requis).