
Exploit d'escalade de privilèges sous Linux via snapd (CVE-2019-7304)
En janvier 2019, les versions actuelles d'Ubuntu Linux se sont révélées vulnérables à une élévation de privilèges locale due à un bogue dans l'API snapd. Ce dépôt contient la POC d'exploit originale, mise à disposition pour la recherche et l'éducation. Pour une explication détaillée de la vulnérabilité et de l'exploit, veuillez consulter l'article de blog ici.
Ubuntu est livré avec snapd par défaut, mais toute distribution devrait être exploitable si elle a ce paquet installé. Vous pouvez facilement vérifier si votre système est vulnérable. Exécutez la commande ci-dessous. Si votre snapd est 2.37.1 ou plus récent, vous êtes en sécurité.
$ snap version
...
snapd 2.37.1
...
Notez que certains systèmes renvoient la version du paquet de distribution de snapd lorsque vous exécutez cette commande, contrairement à la version amont présentée dans l'exemple ci-dessus. Si votre version de snapd comporte une référence à un numéro de version Ubuntu qui lui est ajouté (exemple : 2.34.2ubuntu0.1 ou 2.35.5+18.10.1), veuillez consulter ce lien pour déterminer si vous exécutez une version corrigée.
Cet exploit contourne les vérifications de contrôle d'accès pour utiliser une fonction API restreinte (POST /v2/create-user) du service snapd local. Cela interroge l'Ubuntu SSO pour un nom d'utilisateur et une clé SSH publique d'une adresse e-mail fournie, puis crée un utilisateur local basé sur ces valeurs.
Une exploitation réussie pour cette version nécessite une connexion Internet sortante et un service SSH accessible via localhost.
Pour exploiter, créez d'abord un compte sur Ubuntu SSO. Après l'avoir confirmé, modifiez votre profil et téléchargez une clé publique SSH. Ensuite, exécutez l'exploit comme ceci (avec la clé privée SSH correspondant à la clé publique que vous avez téléchargée) :
python3 ./dirty_sockv1.py -u "[email protected]" -k "id_rsa"
[+] Slipped dirty sock on random socket file: /tmp/ktgolhtvdk;uid=0;
[+] Binding to socket file...
[+] Connecting to snapd API...
[+] Sending payload...
[+] Success! Enjoy your new account with sudo rights!
[Script will automatically ssh to localhost with the SSH key here]
Cet exploit contourne les vérifications de contrôle d'accès pour utiliser une fonction API restreinte (POST /v2/snaps) du service snapd local. Cela permet l'installation de snaps arbitraires. Les snaps en "devmode" contournent le sandbox et peuvent inclure un "install hook" qui est exécuté dans le contexte de root lors de l'installation.
dirty_sockv2 exploite la vulnérabilité pour installer un snap "devmode" vide incluant un hook qui ajoute un nouvel utilisateur au système local. Cet utilisateur aura les permissions d'exécuter des commandes sudo.
Contrairement à la version une, celle-ci ne nécessite pas que le service SSH soit en cours d'exécution. Elle fonctionnera également sur les versions plus récentes d'Ubuntu sans connexion Internet du tout, ce qui la rend résistante aux changements et efficace dans des environnements restreints.
Note pour clarification : Cette version de l'exploit ne se cache pas à l'intérieur d'un snap malveillant. Au lieu de cela, elle utilise un snap malveillant comme mécanisme de livraison pour la charge utile de création d'utilisateur. Cela est possible grâce au même bogue uid=0 que la version 1
Cet exploit devrait également être efficace sur les systèmes non-Ubuntu qui ont installé snapd mais qui ne supportent pas l'API "create-user" en raison d'une syntaxe de shell Linux incompatible.
Certains systèmes Ubuntu plus anciens (comme 16.04) peuvent ne pas avoir les composants snapd installés nécessaires au sideloading. Si c'est le cas, cette version de l'exploit peut déclencher l'installation de ces dépendances. Pendant cette installation, snapd peut se mettre à niveau vers une version non vulnérable. Les tests montrent que l'exploit reste réussi dans ce scénario. Voir la section de dépannage pour plus de détails.
Pour exploiter, exécutez simplement le script sans arguments sur un système vulnérable.
python3 ./dirty_sockv2.py
[+] Slipped dirty sock on random socket file: /tmp/gytwczalgx;uid=0;
[+] Binding to socket file...
[+] Connecting to snapd API...
[+] Deleting trojan snap (and sleeping 5 seconds)...
[+] Installing the trojan snap (and sleeping 8 seconds)...
[+] Deleting trojan snap (and sleeping 5 seconds)...
********************
Success! You can now `su` to the following account and use sudo:
username: dirty_sock
password: dirty_sock
********************
Si vous utilisez la version deux et que l'exploit se termine mais que vous ne voyez pas votre nouveau compte, cela peut être dû à des mises à jour snap en arrière-plan. Vous pouvez les visualiser en exécutant snap changes puis snap change #, en référençant la ligne montrant l'installation du snap dirty_sock. Finalement, celles-ci devraient se terminer et votre compte devrait être utilisable.
La version 1 semble être la plus facile et la plus rapide, si votre environnement le supporte (service SSH en cours d'exécution et accessible depuis localhost).
Les systèmes non vulnérables afficheront quelque chose comme ceci :
[!] System may not be vulnerable, here is the API reply:
HTTP/1.1 401 Unauthorized
Content-Type: application/json
Date: Mon, 18 Feb 2019 07:07:12 GMT
Content-Length: 119
{"type":"error","status-code":401,"status":"Unauthorized",
"result":{"message":"access denied","kind":"login-required"}}
Veuillez ouvrir des issues pour tout problème étrange.
Le problème a été signalé directement à l'équipe snapd via le bug tracker d'Ubuntu. Vous pouvez lire le fil complet ici.
J'ai été très impressionné par la réponse de Canonical à ce problème. L'équipe a été formidable à travailler, et dans l'ensemble l'expérience me fait me sentir très bien d'être moi-même un utilisateur Ubuntu.
Liens d'avis public :
Note : Je publie des informations uniquement sur ce dépôt GitHub, mon blog sur initblog.com, et le blog de mon équipe sur shenaniganslabs.io. Tout site se faisant passer pour une source officielle est malheureusement hors de mon contrôle.