
Preuve de concept d'exploitation pour CVE-2026-41651, une élévation de privilèges locale TOCTOU dans PackageKit, avec analyse technique, logique de détection et recommandations de remédiation.
Classification : Artefact d'évaluation Purple Team
Usage autorisé uniquement. Ce document et le script de test qui l'accompagne sont destinés exclusivement à la validation de sécurité interne sur des systèmes pour lesquels une autorisation écrite a été obtenue.

| Champ | Valeur |
|---|---|
| ID CVE | CVE-2026-41651 |
| CWE | CWE-367 — Condition de concurrence TOCTOU (Time-of-check Time-of-use) |
| Composant | PackageKit (packagekitd, service D-Bus) |
| Versions concernées | PackageKit ≤ 1.3.4 |
| Corrigé dans | PackageKit 1.3.5 |
| Impact | Élévation de privilèges locale → root |
| Vecteur d'attaque | Local / D-Bus (session utilisateur non privilégiée) |
| Divulgué | 2026-04-22 (Deutsche Telekom Red Team) |
| Avis de sécurité | GHSA-f55j-vvr9-69xv |
| Commit de correction | 76cfb675fb31acc3ad5595d4380bfff56d2a8697 |
PackageKit est une couche d'abstraction D-Bus pour la gestion de paquets système, présente par défaut sur les environnements de bureau GNOME sous Debian, Ubuntu, Fedora, RHEL, SUSE et Arch Linux. Comme il assure la médiation des opérations de paquets privilégiées au nom des utilisateurs non privilégiés, une faille dans son flux d'autorisation a un impact root à l'échelle du système.
pk-transaction.c (avant 1.3.5) n'appliquait pas de garde d'état sur la ré-invocation des méthodes d'action. Un client D-Bus pouvait appeler InstallFiles (ou d'autres méthodes d'action) plusieurs fois sur le même objet de transaction après que celle-ci était déjà passée hors de l'état PK_TRANSACTION_STATE_NEW.
Attaquant (non privilégié)
│
├─① CreateTransaction() → PackageKit renvoie le chemin de l'objet de transaction (tid)
│
├─② InstallFiles(tid, FLAG_SIMULATE=4, [dummy.pkg])
│ PackageKit met en file une vérification d'autorisation polkit pour dummy.pkg.
│ Aucune installation n'a lieu pour l'instant — SIMULATE signifie essai à blanc uniquement.
│
├─③ InstallFiles(tid, FLAG_NONE=0, [payload.pkg]) ← fenêtre TOCTOU
│ Ré-invoque sur le même tid avant la résolution de l'autorisation.
│ Les versions vulnérables écrasent les paramètres mis en file avec payload.pkg.
│
└─④ polkit accorde l'autorisation (approbation utilisateur ou autorisation automatique)
packagekitd installe payload.pkg en tant que root.
Script postinst/post de payload : install -m 4755 /bin/bash /tmp/.suid_bash
L'attaquant exécute /tmp/.suid_bash -p → shell root.
Les étapes ② et ③ sont envoyées comme appels D-Bus asynchrones non bloquants sur la même connexion et vidées dans une seule écriture. Les deux messages arrivent à packagekitd avant qu'il ne puisse traiter ② et faire avancer la machine à états, laissant la fenêtre TOCTOU ouverte. Le correctif dans 1.3.5 ajoute une vérification d'état explicite qui renvoie PK_TRANSACTION_ERROR_INVALID_STATE sur toute ré-invocation après PK_TRANSACTION_STATE_NEW.
Fichier : cve-2026-41651-purpleteam.py
Langage : Python 3
Dépendances : python3-gi (introspection GObject / liaisons GLib/Gio)
Démontre l'exploitabilité de CVE-2026-41651 sur un système de test préparé dans le but de :
| Phase | Action |
|---|---|
| Configuration | Sonde /proc/mounts pour sélectionner un répertoire de dépôt SUID/exec-capable, définit umask(022), applique un chmod explicite sur tous les artefacts de construction, puis construit un paquet factice et un paquet de charge utile dans /tmp |
| Exploitation | Ouvre une connexion D-Bus système, crée une transaction PackageKit, déclenche la course à deux appels |
| Charge utile | Le script post-installation du paquet copie /bin/bash vers <drop_dir>/.suid_bash avec le mode 04755, propriétaire root. Le répertoire de dépôt est résolu au moment de l'exécution (voir Prise en charge des environnements durcis) |
| Élévation | Interroge la présence du binaire SUID (délai de 90 s), puis execl dedans avec -p pour un shell root |
| Nettoyage | Supprime les fichiers temporaires .deb/.rpm à la sortie (succès ou échec) |
Les systèmes durcis par défaut peuvent bloquer l'exploit à deux points indépendants. Le script gère les deux automatiquement.
027 / 077)Un umask hérité du processus de 027 ou 077 fait que mkdir() produit des répertoires 750 ou 700. dpkg-deb et rpmbuild doivent tous deux parcourir l'arborescence de construction complète — si un répertoire est illisible, la construction échoue silencieusement.
Correctif appliqué : os.umask(0o022) est appelé au démarrage avant la création de tout fichier ou répertoire. De plus, chaque répertoire et fichier de l'arborescence de construction reçoit un chmod explicite immédiatement après sa création (0o755 pour les répertoires et scripts, 0o644 pour les fichiers de données), garantissant ainsi les permissions correctes quel que soit l'umask hérité.
nosuid / noexec sur /tmp| Indicateur | Effet sur l'exploit |
|---|---|
nosuid | Le noyau supprime silencieusement le bit SUID de tout fichier stocké sur ce système de fichiers — le bash copié ne devient jamais root |
noexec | Le binaire SUID ne peut pas être exécuté du tout |