Linux Capabilities
RootedCON est l'événement le plus pertinent en matière de cybersécurité en Espagne et l'un des plus importants en Europe. Avec pour mission de promouvoir les connaissances techniques, ce congrès est un point de rencontre bouillonnant pour les professionnels de la technologie et de la cybersécurité dans chaque discipline.\
Capacités Linux
Les capacités Linux divisent les privilèges root en unités plus petites et distinctes, permettant aux processus de disposer d'un sous-ensemble de privilèges. Cela réduit les risques en ne accordant pas inutilement des privilèges root complets.
Le Problème :
Les utilisateurs normaux ont des autorisations limitées, ce qui affecte des tâches comme l'ouverture d'un socket réseau qui nécessite un accès root.
Ensembles de Capacités :
Héritées (CapInh) :
Objectif : Détermine les capacités transmises par le processus parent.
Fonctionnalité : Lorsqu'un nouveau processus est créé, il hérite des capacités de son parent dans cet ensemble. Utile pour maintenir certains privilèges à travers les spawns de processus.
Restrictions : Un processus ne peut pas acquérir des capacités que son parent ne possédait pas.
Effectives (CapEff) :
Objectif : Représente les capacités réelles qu'un processus utilise à tout moment.
Fonctionnalité : C'est l'ensemble de capacités vérifié par le noyau pour accorder l'autorisation pour diverses opérations. Pour les fichiers, cet ensemble peut être un indicateur indiquant si les capacités autorisées du fichier doivent être considérées comme effectives.
Signification : L'ensemble effectif est crucial pour les vérifications de privilèges immédiates, agissant comme l'ensemble actif de capacités qu'un processus peut utiliser.
Autorisées (CapPrm) :
Objectif : Définit l'ensemble maximal de capacités qu'un processus peut posséder.
Fonctionnalité : Un processus peut élever une capacité de l'ensemble autorisé à son ensemble effectif, lui donnant la possibilité d'utiliser cette capacité. Il peut également supprimer des capacités de son ensemble autorisé.
Limite : Il agit comme une limite supérieure pour les capacités qu'un processus peut avoir, garantissant qu'un processus ne dépasse pas son champ de privilèges prédéfini.
Limitation (CapBnd) :
Objectif : Met un plafond sur les capacités qu'un processus peut acquérir à tout moment de son cycle de vie.
Fonctionnalité : Même si un processus a une certaine capacité dans son ensemble hérité ou autorisé, il ne peut pas acquérir cette capacité à moins qu'elle ne soit également dans l'ensemble de limitation.
Cas d'utilisation : Cet ensemble est particulièrement utile pour restreindre le potentiel d'escalade de privilèges d'un processus, ajoutant une couche de sécurité supplémentaire.
Ambiante (CapAmb) :
Objectif : Permet à certaines capacités d'être maintenues à travers un appel système
execve
, qui entraînerait normalement une réinitialisation complète des capacités du processus.Fonctionnalité : Garantit que les programmes non-SUID qui n'ont pas de capacités de fichier associées peuvent conserver certains privilèges.
Restrictions : Les capacités de cet ensemble sont soumises aux contraintes des ensembles hérités et autorisés, garantissant qu'elles ne dépassent pas les privilèges autorisés du processus.
Pour plus d'informations, consultez :
Capacités des Processus et des Binaires
Capacités des Processus
Pour voir les capacités d'un processus particulier, utilisez le fichier status dans le répertoire /proc. Comme il fournit plus de détails, limitons-le uniquement aux informations liées aux capacités Linux. Notez que pour tous les processus en cours d'exécution, les informations sur les capacités sont maintenues par thread, pour les binaires dans le système de fichiers, elles sont stockées dans des attributs étendus.
Vous pouvez trouver les capacités définies dans /usr/include/linux/capability.h
Vous pouvez trouver les capacités du processus actuel en utilisant cat /proc/self/status
ou en exécutant capsh --print
, et celles des autres utilisateurs dans /proc/<pid>/status
Ce commandement devrait renvoyer 5 lignes sur la plupart des systèmes.
CapInh = Capacités héritées
CapPrm = Capacités autorisées
CapEff = Capacités effectives
CapBnd = Ensemble de limitation
CapAmb = Ensemble de capacités ambiantes
Ces nombres hexadécimaux n'ont pas de sens. En utilisant l'utilitaire capsh, nous pouvons les décoder en noms de capacités.
Vérifions maintenant les capacités utilisées par ping
:
Bien que cela fonctionne, il existe une autre manière plus simple. Pour voir les capacités d'un processus en cours d'exécution, utilisez simplement l'outil getpcaps suivi de son identifiant de processus (PID). Vous pouvez également fournir une liste d'identifiants de processus.
Vérifions ici les capacités de tcpdump
après avoir donné suffisamment de capacités au binaire (cap_net_admin
et cap_net_raw
) pour écouter le réseau (tcpdump s'exécute dans le processus 9562):
Comme vous pouvez le constater, les capacités données correspondent aux résultats des 2 façons d'obtenir les capacités d'un binaire. L'outil getpcaps utilise l'appel système capget() pour interroger les capacités disponibles pour un thread particulier. Cet appel système n'a besoin que du PID pour obtenir plus d'informations.
Capacités des Binaires
Les binaires peuvent avoir des capacités qui peuvent être utilisées lors de l'exécution. Par exemple, il est très courant de trouver le binaire ping
avec la capacité cap_net_raw
:
Vous pouvez rechercher des binaires avec des capacités en utilisant :
Suppression des capacités avec capsh
Si nous supprimons les capacités CAP_NET_RAW pour ping, alors l'utilitaire ping ne devrait plus fonctionner.
Outre la sortie de capsh elle-même, la commande tcpdump devrait également générer une erreur.
/bin/bash: /usr/sbin/tcpdump: Operation not permitted
L'erreur montre clairement que la commande ping n'est pas autorisée à ouvrir un socket ICMP. Maintenant, nous savons avec certitude que cela fonctionne comme prévu.
Supprimer les capacités
Vous pouvez supprimer les capacités d'un binaire avec
Capacités de l'utilisateur
Apparemment, il est possible d'attribuer des capacités également aux utilisateurs. Cela signifie probablement que chaque processus exécuté par l'utilisateur pourra utiliser les capacités de l'utilisateur.
Basé sur ceci, ceci et ceci quelques fichiers doivent être configurés pour donner à un utilisateur certaines capacités, mais celui qui attribue les capacités à chaque utilisateur sera /etc/security/capability.conf
.
Exemple de fichier:
Capacités de l'environnement
En compilant le programme suivant, il est possible de créer un shell bash à l'intérieur d'un environnement qui fournit des capacités.
À l'intérieur du bash exécuté par le binaire ambiant compilé, il est possible d'observer les nouvelles capacités (un utilisateur régulier n'aura aucune capacité dans la section "actuelle").
Vous ne pouvez ajouter que des capacités présentes à la fois dans les ensembles autorisés et héritables.
Binaires conscients des capacités / Binaires ignorants des capacités
Les binaires conscients des capacités n'utiliseront pas les nouvelles capacités données par l'environnement, tandis que les binaires ignorants des capacités les utiliseront car ils ne les rejettent pas. Cela rend les binaires ignorants des capacités vulnérables à l'intérieur d'un environnement spécial qui accorde des capacités aux binaires.
Capacités de service
Par défaut, un service s'exécutant en tant que root se verra attribuer toutes les capacités, ce qui peut parfois être dangereux. Par conséquent, un fichier de configuration du service permet de spécifier les capacités que vous souhaitez lui attribuer, et l'utilisateur qui devrait exécuter le service pour éviter d'exécuter un service avec des privilèges inutiles:
Capacités dans les conteneurs Docker
Par défaut, Docker attribue quelques capacités aux conteneurs. Il est très facile de vérifier quelles sont ces capacités en exécutant :
RootedCON est l'événement le plus pertinent en matière de cybersécurité en Espagne et l'un des plus importants en Europe. Avec pour mission de promouvoir les connaissances techniques, ce congrès est un point de rencontre bouillonnant pour les professionnels de la technologie et de la cybersécurité dans chaque discipline.
Privesc/Évasion de conteneur
Les capacités sont utiles lorsque vous voulez restreindre vos propres processus après avoir effectué des opérations privilégiées (par exemple, après avoir configuré un chroot et lié à un socket). Cependant, elles peuvent être exploitées en leur transmettant des commandes ou des arguments malveillants qui sont ensuite exécutés en tant que root.
Vous pouvez forcer des capacités sur des programmes en utilisant setcap
, et les interroger en utilisant getcap
:
Le +ep
signifie que vous ajoutez la capacité ("-" la supprimerait) en tant qu'Effective et Permitted.
Pour identifier les programmes dans un système ou un dossier avec des capacités :
Exemple d'exploitation
Dans l'exemple suivant, le binaire /usr/bin/python2.6
est trouvé vulnérable à l'élévation de privilèges :
Capacités nécessaires par tcpdump
pour permettre à n'importe quel utilisateur de capturer des paquets:
Le cas spécial des capacités "vides"
D'après la documentation : Notez qu'il est possible d'attribuer des ensembles de capacités vides à un fichier de programme, et il est donc possible de créer un programme avec un ensemble d'identifiants utilisateur définis par l'utilisateur qui modifie l'identifiant utilisateur effectif et enregistré du processus qui exécute le programme en 0, mais ne confère aucune capacité à ce processus. Autrement dit, si vous avez un binaire qui :
n'est pas détenu par root
n'a pas les bits
SUID
/SGID
définisa un ensemble de capacités vide (par exemple :
getcap myelf
renvoiemyelf =ep
)
alors ce binaire s'exécutera en tant que root.
CAP_SYS_ADMIN
CAP_SYS_ADMIN
est une capacité Linux très puissante, souvent assimilée à un niveau quasi-root en raison de ses privilèges administratifs étendus, tels que le montage de périphériques ou la manipulation des fonctionnalités du noyau. Bien qu'indispensable pour les conteneurs simulant des systèmes entiers, CAP_SYS_ADMIN
pose d'importants défis en matière de sécurité, notamment dans les environnements conteneurisés, en raison de son potentiel d'escalade de privilèges et de compromission du système. Par conséquent, son utilisation nécessite des évaluations de sécurité rigoureuses et une gestion prudente, avec une forte préférence pour la suppression de cette capacité dans les conteneurs spécifiques à une application afin de respecter le principe du moindre privilège et de réduire au minimum la surface d'attaque.
Exemple avec un binaire
En utilisant python, vous pouvez monter un fichier passwd modifié sur le vrai fichier passwd:
Et enfin monter le fichier passwd
modifié sur /etc/passwd
:
Et vous pourrez su
en tant que root en utilisant le mot de passe "password".
Exemple avec l'environnement (évasion de Docker)
Vous pouvez vérifier les capacités activées à l'intérieur du conteneur Docker en utilisant :
À l'intérieur de la sortie précédente, vous pouvez voir que la capacité SYS_ADMIN est activée.
Mount
Cela permet au conteneur docker de monter le disque hôte et d'y accéder librement:
Accès complet
Dans la méthode précédente, nous avons réussi à accéder au disque hôte de Docker. Au cas où vous constateriez que l'hôte exécute un serveur ssh, vous pourriez créer un utilisateur à l'intérieur du disque de l'hôte Docker et y accéder via SSH:
CAP_SYS_PTRACE
Cela signifie que vous pouvez échapper au conteneur en injectant un shellcode à l'intérieur d'un processus s'exécutant dans l'hôte. Pour accéder aux processus s'exécutant dans l'hôte, le conteneur doit être exécuté au moins avec --pid=host
.
CAP_SYS_PTRACE
accorde la capacité d'utiliser les fonctionnalités de débogage et de traçage des appels système fournies par ptrace(2)
et les appels d'attachement de mémoire croisée comme process_vm_readv(2)
et process_vm_writev(2)
. Bien que puissant à des fins de diagnostic et de surveillance, si CAP_SYS_PTRACE
est activé sans mesures restrictives comme un filtre seccomp sur ptrace(2)
, cela peut sérieusement compromettre la sécurité du système. Plus précisément, il peut être exploité pour contourner d'autres restrictions de sécurité, notamment celles imposées par seccomp, comme le démontrent des preuves de concept (PoC) comme celle-ci.
Exemple avec un binaire (python)
Exemple avec binaire (gdb)
gdb
avec la capacité ptrace
:
Créez un shellcode avec msfvenom pour l'injecter en mémoire via gdb
Déboguer un processus root avec gdb et copier-coller les lignes gdb précédemment générées :
Exemple avec l'environnement (évasion de Docker) - Autre abus de gdb
Si GDB est installé (ou vous pouvez l'installer avec apk add gdb
ou apt install gdb
par exemple) vous pouvez déboguer un processus depuis l'hôte et le faire appeler la fonction system
. (Cette technique nécessite également la capacité SYS_ADMIN
).
Vous ne pourrez pas voir la sortie de la commande exécutée mais elle sera exécutée par ce processus (donc obtenez un shell inversé).
Si vous obtenez l'erreur "No symbol "system" in current context.", vérifiez l'exemple précédent en chargeant un shellcode dans un programme via gdb.
Exemple avec l'environnement (évasion de Docker) - Injection de shellcode
Vous pouvez vérifier les capacités activées à l'intérieur du conteneur Docker en utilisant :
Lister les processus en cours d'exécution sur l'hôte ps -eaf
Obtenir l'architecture
uname -m
Trouver un shellcode pour l'architecture (https://www.exploit-db.com/exploits/41128)
Trouver un programme pour injecter le shellcode dans la mémoire d'un processus (https://github.com/0x00pf/0x00sec_code/blob/master/mem_inject/infect.c)
Modifier le shellcode à l'intérieur du programme et le compiler
gcc inject.c -o inject
Injectez et obtenez votre shell:
./inject 299; nc 172.17.0.1 5600
CAP_SYS_MODULE
CAP_SYS_MODULE
permet à un processus de charger et décharger des modules noyaux (appels système init_module(2)
, finit_module(2)
et delete_module(2)
), offrant un accès direct aux opérations de base du noyau. Cette capacité présente des risques de sécurité critiques, car elle permet une élévation de privilèges et une compromission totale du système en autorisant des modifications du noyau, contournant ainsi tous les mécanismes de sécurité Linux, y compris les modules de sécurité Linux et l'isolation des conteneurs. Cela signifie que vous pouvez insérer/supprimer des modules noyaux dans/du noyau de la machine hôte.
Exemple avec un binaire
Dans l'exemple suivant, le binaire python
possède cette capacité.
Par défaut, la commande modprobe
vérifie la liste des dépendances et les fichiers de mappage dans le répertoire /lib/modules/$(uname -r)
.
Pour exploiter cela, créons un faux dossier lib/modules :
Ensuite, compilez le module du noyau que vous pouvez trouver 2 exemples ci-dessous et copiez le dans ce dossier :
Enfin, exécutez le code Python nécessaire pour charger ce module de noyau :
Exemple 2 avec binaire
Dans l'exemple suivant, le binaire kmod
possède cette capacité.
Cela signifie qu'il est possible d'utiliser la commande insmod
pour insérer un module noyau. Suivez l'exemple ci-dessous pour obtenir un shell inversé en abusant de ce privilège.
Exemple avec l'environnement (évasion de Docker)
Vous pouvez vérifier les capacités activées à l'intérieur du conteneur Docker en utilisant :
À l'intérieur de la sortie précédente, vous pouvez voir que la capacité SYS_MODULE est activée.
Créez le module noyau qui va exécuter un shell inversé et le Makefile pour le compiler :
L'espace vide avant chaque mot make dans le Makefile doit être une tabulation, pas des espaces!
Exécutez make
pour le compiler.
Enfin, démarrez nc
à l'intérieur d'un shell et chargez le module depuis un autre pour capturer le shell dans le processus nc:
Le code de cette technique a été copié depuis le laboratoire "Abusing SYS_MODULE Capability" de https://www.pentesteracademy.com/
Un autre exemple de cette technique peut être trouvé sur https://www.cyberark.com/resources/threat-research-blog/how-i-hacked-play-with-docker-and-remotely-ran-code-on-the-host
CAP_DAC_READ_SEARCH
CAP_DAC_READ_SEARCH permet à un processus de contourner les autorisations de lecture des fichiers et de lecture et d'exécution des répertoires. Son utilisation principale est la recherche de fichiers ou la lecture de fichiers. Cependant, il permet également à un processus d'utiliser la fonction open_by_handle_at(2)
, qui peut accéder à n'importe quel fichier, y compris ceux en dehors de l'espace de nom de montage du processus. Le handle utilisé dans open_by_handle_at(2)
est censé être un identifiant non transparent obtenu via name_to_handle_at(2)
, mais il peut inclure des informations sensibles comme des numéros d'inode vulnérables à la manipulation. Le potentiel d'exploitation de cette capacité, en particulier dans le contexte des conteneurs Docker, a été démontré par Sebastian Krahmer avec l'exploit shocker, tel qu'analysé ici. Cela signifie que vous pouvez contourner les vérifications d'autorisation de lecture de fichiers et les vérifications d'autorisation de lecture/exécution de répertoires.
Exemple avec un binaire
Le binaire pourra lire n'importe quel fichier. Ainsi, si un fichier comme tar possède cette capacité, il pourra lire le fichier shadow:
Exemple avec binary2
Dans ce cas, supposons que le binaire python
a cette capacité. Pour lister les fichiers root, vous pourriez faire :
Et pour lire un fichier, vous pourriez faire :
Exemple dans l'environnement (évasion de Docker)
Vous pouvez vérifier les capacités activées à l'intérieur du conteneur Docker en utilisant :
À l'intérieur de la sortie précédente, vous pouvez voir que la capacité DAC_READ_SEARCH est activée. Par conséquent, le conteneur peut déboguer les processus.
Vous pouvez apprendre comment fonctionne l'exploitation suivante sur https://medium.com/@fun_cuddles/docker-breakout-exploit-analysis-a274fff0e6b3 mais en résumé, CAP_DAC_READ_SEARCH nous permet non seulement de parcourir le système de fichiers sans vérifications de permission, mais supprime également explicitement toutes les vérifications à open_by_handle_at(2) et pourrait permettre à notre processus d'accéder à des fichiers sensibles ouverts par d'autres processus.
L'exploit original qui abuse de ces autorisations pour lire des fichiers de l'hôte peut être trouvé ici : http://stealth.openwall.net/xSports/shocker.c, ce qui suit est une version modifiée qui vous permet d'indiquer le fichier que vous souhaitez lire en premier argument et de le sauvegarder dans un fichier.
L'exploit doit trouver un pointeur vers quelque chose monté sur l'hôte. L'exploit original utilisait le fichier /.dockerinit et cette version modifiée utilise /etc/hostname. Si l'exploit ne fonctionne pas, vous devrez peut-être définir un fichier différent. Pour trouver un fichier monté sur l'hôte, exécutez simplement la commande mount :
Le code de cette technique a été copié du laboratoire "Abusing DAC_READ_SEARCH Capability" de https://www.pentesteracademy.com/
RootedCON est l'événement de cybersécurité le plus pertinent en Espagne et l'un des plus importants en Europe. Avec pour mission de promouvoir les connaissances techniques, ce congrès est un point de rencontre bouillonnant pour les professionnels de la technologie et de la cybersécurité dans chaque discipline.
CAP_DAC_OVERRIDE
Cela signifie que vous pouvez contourner les vérifications de permission en écriture sur n'importe quel fichier, vous pouvez donc écrire n'importe quel fichier.
Il y a beaucoup de fichiers que vous pouvez écraser pour escalader les privilèges, vous pouvez trouver des idées ici.
Exemple avec un binaire
Dans cet exemple, vim possède cette capacité, vous pouvez donc modifier n'importe quel fichier comme passwd, sudoers ou shadow:
Exemple avec le binaire 2
Dans cet exemple, le binaire python
aura cette capacité. Vous pourriez utiliser python pour remplacer n'importe quel fichier:
Exemple avec environnement + CAP_DAC_READ_SEARCH (Évasion de Docker)
Vous pouvez vérifier les capacités activées à l'intérieur du conteneur Docker en utilisant :
Tout d'abord, lisez la section précédente qui exploite la capacité DAC_READ_SEARCH pour lire des fichiers arbitraires de l'hôte et compilez l'exploit. Ensuite, compilez la version suivante de l'exploit shocker qui vous permettra de écrire des fichiers arbitraires dans le système de fichiers de l'hôte :
Pour échapper du conteneur Docker, vous pourriez télécharger les fichiers /etc/shadow
et /etc/passwd
de l'hôte, ajouter un nouvel utilisateur et utiliser shocker_write
pour les écraser. Ensuite, accédez via ssh.
Le code de cette technique a été copié du laboratoire "Abusing DAC_OVERRIDE Capability" de https://www.pentesteracademy.com
CAP_CHOWN
Cela signifie qu'il est possible de changer la propriété de n'importe quel fichier.
Exemple avec un binaire
Supposons que le binaire python
ait cette capacité, vous pouvez changer le propriétaire du fichier shadow, changer le mot de passe root et escalader les privilèges:
Ou avec le binaire ruby
ayant cette capacité :
CAP_FOWNER
Cela signifie qu'il est possible de modifier les autorisations de n'importe quel fichier.
Exemple avec un binaire
Si Python a cette capacité, vous pouvez modifier les autorisations du fichier shadow, changer le mot de passe root, et escalader les privilèges:
CAP_SETUID
Cela signifie qu'il est possible de définir l'identifiant d'utilisateur effectif du processus créé.
Exemple avec un binaire
Si python a cette capacité, vous pouvez très facilement en abuser pour escalader les privilèges vers root:
Une autre méthode :
CAP_SETGID
Cela signifie qu'il est possible de définir l'identifiant de groupe effectif du processus créé.
Il y a beaucoup de fichiers que vous pouvez écraser pour escalader les privilèges, vous pouvez trouver des idées ici.
Exemple avec un binaire
Dans ce cas, vous devriez chercher des fichiers intéressants qu'un groupe peut lire car vous pouvez vous faire passer pour n'importe quel groupe:
Une fois que vous avez trouvé un fichier que vous pouvez exploiter (en le lisant ou en l'écrivant) pour escalader les privilèges, vous pouvez obtenir un shell en vous faisant passer pour le groupe intéressant avec :
Dans ce cas, le groupe shadow a été impersonné afin de pouvoir lire le fichier /etc/shadow
:
Si docker est installé, vous pourriez usurper le groupe docker et l'exploiter pour communiquer avec le socket docker et escalader les privilèges.
CAP_SETFCAP
Cela signifie qu'il est possible de définir des capacités sur des fichiers et des processus
Exemple avec un binaire
Si Python a cette capacité, vous pouvez facilement l'exploiter pour escalader les privilèges vers root :
Notez que si vous définissez une nouvelle capacité pour le binaire avec CAP_SETFCAP, vous perdrez cette capacité.
Une fois que vous avez la capacité SETUID, vous pouvez aller dans sa section pour voir comment escalader les privilèges.
Exemple avec l'environnement (évasion de Docker)
Par défaut, la capacité CAP_SETFCAP est donnée au processus à l'intérieur du conteneur Docker. Vous pouvez vérifier cela en faisant quelque chose comme:
Cette capacité permet de donner toute autre capacité aux binaires, donc nous pourrions envisager une évasion du conteneur en abusant de l'une des autres failles de capacité mentionnées sur cette page. Cependant, si vous essayez de donner par exemple les capacités CAP_SYS_ADMIN et CAP_SYS_PTRACE au binaire gdb, vous constaterez que vous pouvez les donner, mais le binaire ne pourra pas s'exécuter après cela:
Depuis la documentation : Permitted : Il s'agit d'un sous-ensemble limitant pour les capacités effectives que le thread peut assumer. C'est également un sous-ensemble limitant pour les capacités qui peuvent être ajoutées à l'ensemble hérité par un thread qui n'a pas la capacité CAP_SETPCAP dans son ensemble effectif. Il semble que les capacités Permitted limitent celles qui peuvent être utilisées. Cependant, Docker accorde également par défaut le CAP_SETPCAP, donc vous pourriez être en mesure de définir de nouvelles capacités à l'intérieur des capacités héritées. Cependant, dans la documentation de cette capacité : CAP_SETPCAP : [...] ajoute toute capacité de l'ensemble de délimitation du thread appelant à son ensemble hérité. Il semble que nous ne puissions ajouter que des capacités de l'ensemble de délimitation à l'ensemble hérité. Ce qui signifie que nous ne pouvons pas ajouter de nouvelles capacités comme CAP_SYS_ADMIN ou CAP_SYS_PTRACE dans l'ensemble hérité pour escalader les privilèges.
CAP_SYS_RAWIO
CAP_SYS_RAWIO fournit un certain nombre d'opérations sensibles, y compris l'accès à /dev/mem
, /dev/kmem
ou /proc/kcore
, la modification de mmap_min_addr
, l'accès aux appels système ioperm(2)
et iopl(2)
, et diverses commandes de disque. L'ioctl(2)
FIBMAP est également activé via cette capacité, ce qui a causé des problèmes dans le passé. Selon la page de manuel, cela permet également au détenteur de réaliser de manière descriptive une gamme d'opérations spécifiques à un périphérique sur d'autres périphériques
.
Cela peut être utile pour l'escalade de privilèges et l'évasion de Docker.
CAP_KILL
Cela signifie qu'il est possible de tuer n'importe quel processus.
Exemple avec un binaire
Supposons que le binaire python
a cette capacité. Si vous pouviez également modifier la configuration de certains services ou sockets (ou tout fichier de configuration lié à un service), vous pourriez y introduire une porte dérobée, puis tuer le processus lié à ce service et attendre que le nouveau fichier de configuration soit exécuté avec votre porte dérobée.
Privesc avec kill
Si vous avez des capacités de kill et qu'il y a un programme node en cours d'exécution en tant que root (ou en tant qu'un utilisateur différent), vous pourriez probablement lui envoyer le signal SIGUSR1 et le faire ouvrir le débogueur node où vous pouvez vous connecter.
RootedCON est l'événement le plus pertinent en matière de cybersécurité en Espagne et l'un des plus importants en Europe. Avec pour mission de promouvoir les connaissances techniques, ce congrès est un point de rencontre bouillonnant pour les professionnels de la technologie et de la cybersécurité dans chaque discipline.
CAP_NET_BIND_SERVICE
Cela signifie qu'il est possible d'écouter sur n'importe quel port (même sur des ports privilégiés). Vous ne pouvez pas escalader directement les privilèges avec cette capacité.
Exemple avec un binaire
Si python
a cette capacité, il pourra écouter sur n'importe quel port et même se connecter depuis ce port à n'importe quel autre port (certains services nécessitent des connexions à partir de ports spécifiques privilégiés)
Linux Capabilities
Introduction
Linux capabilities provide a fine-grained access control mechanism that allows specific privileges to be assigned to a process. This can be used to reduce the privileges of a process, making it more secure by limiting the damage that can be done if the process is compromised.
Viewing Capabilities
To view the capabilities of a process, you can use the getpcaps
command from the libcap
package:
Modifying Capabilities
You can modify the capabilities of a process using the setpcaps
command from the libcap
package:
Examples
To drop all capabilities from a process:
To add a specific capability to a process:
Common Capabilities
Some common capabilities include:
CAP_DAC_OVERRIDE
: Bypass file read/write permission checksCAP_DAC_READ_SEARCH
: Bypass file read permission checksCAP_NET_RAW
: Use RAW and PACKET socketsCAP_SYS_ADMIN
: Perform a range of system administration tasks
Conclusion
Linux capabilities are a powerful tool for fine-tuning the privileges of processes, enhancing the security of a system by limiting the scope of potential attacks. Understanding how to view and modify capabilities can help in hardening a system against privilege escalation attacks.
CAP_NET_RAW
CAP_NET_RAW permet aux processus de créer des sockets RAW et PACKET, leur permettant de générer et d'envoyer des paquets réseau arbitraires. Cela peut entraîner des risques de sécurité dans les environnements conteneurisés, tels que le spoofing de paquets, l'injection de trafic et le contournement des contrôles d'accès réseau. Des acteurs malveillants pourraient exploiter cela pour perturber le routage des conteneurs ou compromettre la sécurité du réseau hôte, surtout sans protections adéquates de pare-feu. De plus, CAP_NET_RAW est crucial pour les conteneurs privilégiés afin de prendre en charge des opérations telles que le ping via des requêtes ICMP RAW.
Cela signifie qu'il est possible d'intercepter le trafic. Vous ne pouvez pas escalader directement les privilèges avec cette capacité.
Exemple avec un binaire
Si le binaire tcpdump
possède cette capacité, vous pourrez l'utiliser pour capturer des informations réseau.
Notez que si l'environnement offre cette capacité, vous pourriez également utiliser tcpdump
pour intercepter le trafic.
Exemple avec le binaire 2
L'exemple suivant est un code python2
qui peut être utile pour intercepter le trafic de l'interface "lo" (localhost). Le code provient du laboratoire "The Basics: CAP-NET_BIND + NET_RAW" de https://attackdefense.pentesteracademy.com/
CAP_NET_ADMIN + CAP_NET_RAW
La capacité CAP_NET_ADMIN confère au titulaire le pouvoir de modifier les configurations réseau, y compris les paramètres du pare-feu, les tables de routage, les autorisations de socket et les paramètres d'interface réseau dans les espaces de noms réseau exposés. Elle permet également d'activer le mode promiscuous sur les interfaces réseau, permettant ainsi de renifler les paquets à travers les espaces de noms.
Exemple avec un binaire
Supposons que le binaire python ait ces capacités.
CAP_LINUX_IMMUTABLE
Cela signifie qu'il est possible de modifier les attributs d'inode. Vous ne pouvez pas escalader les privilèges directement avec cette capacité.
Exemple avec un binaire
Si vous constatez qu'un fichier est immuable et que Python a cette capacité, vous pouvez supprimer l'attribut immuable et rendre le fichier modifiable :
Notez que généralement, cet attribut immuable est défini et supprimé en utilisant :
CAP_SYS_CHROOT
CAP_SYS_CHROOT permet l'exécution de l'appel système chroot(2)
, ce qui peut potentiellement permettre l'évasion des environnements chroot(2)
à travers des vulnérabilités connues :
CAP_SYS_BOOT
CAP_SYS_BOOT permet non seulement l'exécution de l'appel système reboot(2)
pour redémarrer le système, y compris des commandes spécifiques comme LINUX_REBOOT_CMD_RESTART2
adaptées à certaines plateformes matérielles, mais il permet également l'utilisation de kexec_load(2)
et, à partir de Linux 3.17, kexec_file_load(2)
pour charger de nouveaux noyaux de crash signés respectivement.
CAP_SYSLOG
CAP_SYSLOG a été séparé du plus large CAP_SYS_ADMIN dans Linux 2.6.37, accordant spécifiquement la capacité d'utiliser l'appel syslog(2)
. Cette capacité permet de visualiser les adresses du noyau via /proc
et des interfaces similaires lorsque le paramètre kptr_restrict
est à 1, contrôlant l'exposition des adresses du noyau. Depuis Linux 2.6.39, la valeur par défaut pour kptr_restrict
est 0, ce qui signifie que les adresses du noyau sont exposées, bien que de nombreuses distributions définissent ceci à 1 (masquer les adresses sauf pour uid 0) ou 2 (toujours masquer les adresses) pour des raisons de sécurité.
De plus, CAP_SYSLOG permet d'accéder à la sortie dmesg
lorsque dmesg_restrict
est défini sur 1. Malgré ces changements, CAP_SYS_ADMIN conserve la capacité d'effectuer des opérations syslog
en raison de précédents historiques.
CAP_MKNOD
CAP_MKNOD étend la fonctionnalité de l'appel système mknod
au-delà de la création de fichiers réguliers, de FIFOs (tuyaux nommés) ou de sockets de domaine UNIX. Il permet spécifiquement la création de fichiers spéciaux, qui incluent :
S_IFCHR : Fichiers spéciaux de caractères, qui sont des périphériques comme les terminaux.
S_IFBLK : Fichiers spéciaux de blocs, qui sont des périphériques comme les disques.
Cette capacité est essentielle pour les processus qui nécessitent la capacité de créer des fichiers de périphériques, facilitant l'interaction directe avec le matériel via des périphériques de caractères ou de blocs.
Il s'agit d'une capacité par défaut de Docker (https://github.com/moby/moby/blob/master/oci/caps/defaults.go#L6-L19).
Cette capacité permet des élévations de privilèges (via une lecture complète du disque) sur l'hôte, dans ces conditions :
Avoir un accès initial à l'hôte (non privilégié).
Avoir un accès initial au conteneur (privilégié (EUID 0), et capacité
CAP_MKNOD
effective).L'hôte et le conteneur doivent partager le même espace de noms utilisateur.
Étapes pour Créer et Accéder à un Périphérique de Bloc dans un Conteneur :
Sur l'Hôte en tant qu'Utilisateur Standard :
Déterminez votre ID utilisateur actuel avec
id
, par exemple,uid=1000(utilisateurstandard)
.Identifiez le périphérique cible, par exemple,
/dev/sdb
.
À l'Intérieur du Conteneur en tant que
root
:
De retour sur l'hôte :
CAP_SETPCAP
CAP_SETPCAP permet à un processus de modifier les ensembles de capacités d'un autre processus, permettant l'ajout ou la suppression de capacités des ensembles effectifs, héritables et autorisés. Cependant, un processus ne peut modifier que les capacités qu'il possède dans son propre ensemble autorisé, garantissant qu'il ne peut pas élever les privilèges d'un autre processus au-delà des siens. Les mises à jour récentes du noyau ont renforcé ces règles, restreignant CAP_SETPCAP
pour ne diminuer que les capacités dans son propre ensemble autorisé ou celui de ses descendants, visant à atténuer les risques de sécurité. L'utilisation nécessite d'avoir CAP_SETPCAP
dans l'ensemble effectif et les capacités cibles dans l'ensemble autorisé, en utilisant capset()
pour les modifications. Cela résume la fonction principale et les limitations de CAP_SETPCAP
, mettant en évidence son rôle dans la gestion des privilèges et l'amélioration de la sécurité.
CAP_SETPCAP
est une capacité Linux qui permet à un processus de modifier les ensembles de capacités d'un autre processus. Il accorde la possibilité d'ajouter ou de supprimer des capacités des ensembles de capacités effectifs, héritables et autorisés d'autres processus. Cependant, il existe certaines restrictions quant à l'utilisation de cette capacité.
Un processus avec CAP_SETPCAP
ne peut accorder ou supprimer que les capacités présentes dans son propre ensemble de capacités autorisées. En d'autres termes, un processus ne peut pas accorder une capacité à un autre processus s'il ne possède pas cette capacité lui-même. Cette restriction empêche un processus d'élever les privilèges d'un autre processus au-delà de son propre niveau de privilège.
De plus, dans les versions récentes du noyau, la capacité CAP_SETPCAP
a été encore plus restreinte. Elle ne permet plus à un processus de modifier arbitrairement les ensembles de capacités d'autres processus. Au lieu de cela, elle autorise uniquement un processus à réduire les capacités dans son propre ensemble de capacités autorisées ou dans l'ensemble de capacités autorisées de ses descendants. Ce changement a été introduit pour réduire les risques potentiels de sécurité associés à la capacité.
Pour utiliser CAP_SETPCAP
de manière efficace, vous devez avoir la capacité dans votre ensemble de capacités effectives et les capacités cibles dans votre ensemble de capacités autorisées. Vous pouvez ensuite utiliser l'appel système capset()
pour modifier les ensembles de capacités d'autres processus.
En résumé, CAP_SETPCAP
permet à un processus de modifier les ensembles de capacités d'autres processus, mais il ne peut pas accorder des capacités qu'il ne possède pas lui-même. De plus, en raison de préoccupations de sécurité, sa fonctionnalité a été limitée dans les versions récentes du noyau pour permettre uniquement de réduire les capacités dans son propre ensemble de capacités autorisées ou dans les ensembles de capacités autorisées de ses descendants.
Références
La plupart de ces exemples ont été tirés de certains laboratoires de https://attackdefense.pentesteracademy.com/, donc si vous souhaitez pratiquer ces techniques de privilège, je recommande ces laboratoires.
Autres références:
RootedCON est l'événement le plus pertinent en matière de cybersécurité en Espagne et l'un des plus importants en Europe. Avec pour mission de promouvoir les connaissances techniques, ce congrès est un point de rencontre bouillonnant pour les professionnels de la technologie et de la cybersécurité dans chaque discipline.
Last updated