Introduction
Quand on met en production un serveur Linux ou un cluster Kubernetes, on concentre naturellement l’effort sur le périmètre externe : pare-feu, reverse-proxy, filtrage IP et durcissement SSH. Mais une question reste souvent dans l’angle mort : que peut réellement faire un attaquant s’il parvient à exécuter une commande dans un conteneur applicatif ou sous un simple compte de service (www-data, node, app) ?
Une VM provisionnée proprement par Terraform ou Ansible peut conserver un binaire SUID oublié, un script cron modifiable par un groupe secondaire, un socket Docker monté par facilité ou un accès non filtré à l’API de métadonnées Cloud (169.254.169.254).
Pour vérifier concrètement la résistance d’un hôte ou d’un Pod après déploiement, j’utilise systématiquement LinPEAS (Linux Privilege Escalation Awesome Script), issu du projet open-source PEASS-ng.
Comment fonctionne LinPEAS ?
Contrairement à un scanner externe comme Nmap ou Nuclei, LinPEAS s’exécute directement à l’intérieur de la machine ou du conteneur cible avec les droits d’un utilisateur non privilégié. C’est un simple script Shell POSIX : il n’a besoin ni de Python, ni de Go, ni d’aucun paquet tiers pour tourner.
En quelques dizaines de secondes, il passe au crible les principaux vecteurs d’élévation de privilèges locale (Local Privilege Escalation) et d’évasion de conteneur (Container Escape) :
- Permissions système et binaires : Binaires
SUID/SGID, règlessudoerstrop larges (GTFOBins), unitéssystemdou scripts appelés parcronmodifiables par un utilisateur standard. - Capacités du noyau (Linux Capabilities) : Attribution silencieuse de
cap_setuid,cap_dac_read_search,cap_sys_adminoucap_net_rawsur des binaires commepython3,tar,perloutcpdump. - Isolation conteneurs & Kubernetes : Exposition de
/var/run/docker.sock, conteneurs lancés avec--privileged, ou jetons deServiceAccountKubernetes montés automatiquement dans/var/run/secrets/kubernetes.io/serviceaccount. - Métadonnées Cloud (IMDS) : Accès direct à
169.254.169.254(AWS, GCP, Azure) permettant de récupérer les jetons IAM temporaires du nœud hôte depuis un simple conteneur. - Secrets résiduels : Clés SSH privées, fichiers
.env, historiques shell (.bash_history) et variables d’environnement exposées dans/proc/*/environ.
1. Lancer un audit selon l’environnement réseau
Exécution directe en mémoire (serveur avec accès sortant)
Sur un environnement de pré-production ou de test disposant d’un accès HTTPS vers GitHub, l’exécution directe en mémoire évite de laisser le script sur le disque tout en redirigeant le rapport vers /tmp :
curl -fsSL https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh | sh | tee /tmp/linpeas_audit.txt
Exécution sur un VLAN isolé (sans accès Internet)
En production, les serveurs et nœuds de calcul n’ont généralement pas d’accès sortant direct vers Internet (egress filtering). La méthode la plus propre consiste à récupérer le script sur son poste d’administration, vérifier son empreinte, puis le servir temporairement sur le réseau d’administration :
1. Sur le poste d’administration :
wget -q https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh
sha256sum linpeas.sh
python3 -m http.server 8000 --bind 10.0.10.50
2. Sur la machine auditée :
curl -fsSL http://10.0.10.50:8000/linpeas.sh | sh -s -- -s > /tmp/audit.out
Pour relire le rapport à froid tout en conservant la coloration ANSI d’origine :
less -r /tmp/audit.out
2.Lire le rapport sans se perdre dans le bruit
LinPEAS est volontairement très bavard. Toute son efficacité repose sur son code couleur qui hiérarchise immédiatement ce qu’il faut regarder :
| Code couleur | Signification | Action recommandée |
|---|---|---|
| 🔴🟡 Rouge sur fond Jaune | Vecteur d’élévation de privilèges quasi certain (> 95 %) | Correction immédiate (docker.sock accessible, sudo NOPASSWD, binaire SUID exploitable, cap_setuid sur un interpréteur). |
| 🔴 Rouge | Anomalie ou exposition sensible à vérifier manuellement | Inspecter l’élément (mot de passe dans un .env, clé SSH sans passphrase, service systemd pointant vers un binaire non protégé). |
| 🟢 Vert | Protection active ou configuration saine | Rien à signaler (ASLR actif, AppArmor / SELinux en mode enforce). |
| 🔵 Bleu / Cyan | Informations de contexte | Comprendre la topologie locale (interfaces réseau, ports en écoute sur 127.0.0.1, comptes ayant un shell /bin/bash). |
3. Les 5 erreurs que l’on retrouve le plus souvent sur le terrain
Même sur des infrastructures bien tenues, cinq configurations reviennent régulièrement en rouge/jaune lors d’un premier passage de LinPEAS :
1. Le socket Docker monté dans un conteneur (/var/run/docker.sock)
On le voit souvent sur des agents de supervision, de CI/CD ou des reverse-proxys. Si LinPEAS détecte que /var/run/docker.sock est accessible en écriture depuis un conteneur, ce conteneur est virtuellement root sur l’hôte physique.
- Correction : Ne jamais monter
docker.sockdirectement dans un conteneur exposé. Si un outil a réellement besoin de lire l’état des conteneurs, placer un proxy socket en lecture seule (GETuniquement, blocage strict dePOST /containers/createet/exec) et imposer des limitescgroupsstrictes (RAM, CPU,pids_limit).
2. Les Linux Capabilities oubliées sur un binaire
Donner cap_dac_read_search à un outil de sauvegarde ou cap_setuid à Python pour éviter de le lancer en root revient à offrir un accès complet au système de fichiers ou au compte uid=0.
# Lister toutes les capabilities présentes sur le système
getcap -r / 2>/dev/null
# Retirer une capability excessive
sudo setcap -r /usr/bin/python3
3. Les Pods Kubernetes sans securityContext verrouillé
Par défaut, un conteneur Kubernetes hérite d’un jeu de capacités Linux inutilement large et autorise l’escalade de privilèges via setuid.
- Correction systématique dans les manifestes / Helm charts :
securityContext:
runAsNonRoot: true
runAsUser: 10001
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
4. L’accès ouvert à l’API de métadonnées Cloud (IMDSv1)
Depuis un Pod ou un conteneur compromis, LinPEAS interroge automatiquement http://169.254.169.254/. Si le nœud utilise encore IMDSv1 sans restriction de saut réseau, le conteneur récupère les identifiants IAM de la machine hôte.
- Correction : Activer IMDSv2 obligatoire (
HttpTokens: required,HttpPutResponseHopLimit = 1) sur AWS, ou verrouiller le Workload Identity sur GKE / AKS pour cloisonner les droits par Pod.
5. Les scripts cron modifiables hors de root
Un script exécuté toutes les nuits par root via /etc/crontab, mais stocké dans /opt/scripts/ avec des droits d’écriture pour un groupe applicatif, permet d’exécuter n’importe quelle commande au prochain déclenchement.
- Correction : Tout script appelé par
rootou par une unitésystemdsystème doit appartenir àroot:rooten0700(ou0750), dans un dossier parent lui-même verrouillé.
LinPEAS Cheatsheet
Voici les commandes que j’utilise le plus souvent lors d’un audit rapide :
| Commande | Description |
|---|---|
`curl -fsSL https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh | sh -s -- -s | tee /tmp/linpeas.txt`
| Lancer un audit rapide (-s : ignore le scan lent du disque) et enregistrer la sortie. |
`sh linpeas.sh -o system_information,container,cloud`
| Cibler uniquement les vérifications système, conteneurs et métadonnées Cloud. |
`sh linpeas.sh -a -N > /tmp/linpeas_ci.txt`
| Audit complet (-a) sans couleurs ANSI (-N) pour archivage ou analyse automatisée. |
`grep -E $'\\x1b\\[[0-9;]*103m' /tmp/linpeas.txt`
| Extraire uniquement les alertes critiques (Rouge sur fond Jaune) d'un rapport existant. |
`find / -perm -4000 -type f 2>/dev/null`
| Vérification manuelle rapide de tous les binaires SUID présents sur le serveur. |
`getcap -r / 2>/dev/null`
| Lister tous les binaires disposant de Linux Capabilities particulières. |
`ss -tulnp | grep 127.0.0.1`
| Identifier les services internes en écoute locale uniquement (potentiels rebonds). |
`shred -u /tmp/linpeas.txt`
| Supprimer proprement le rapport temporaire de la machine une fois l'audit terminé. |
Conclusion
Auditer ses serveurs de l’extérieur est indispensable, mais vérifier ce qui se passe une fois la première barrière franchie fait souvent toute la différence. Passer un coup de LinPEAS sur un nouveau gabarit de VM, un hôte Docker ou un Pod Kubernetes prend moins de deux minutes et révèle immédiatement les angles morts que la revue de code statique ne voit pas toujours.
Sources
Si vous voulez plus d’information sur l’infrastructure vous pouvez voir mon repo à ce sujet : https://github.com/ravindrajob/InfraAtHome
Dernière mise à jour : 22 octobre 2026
