
Código fuente y archivos de configuración relacionados con nuestro artículo en MISC96
Este repositorio es un complemento al artículo publicado en MISC Magazine #96.
Conseguimos elevar nuestros privilegios de forma fiable, en nuestra máquina virtual con SMEP / SMAP y KASLR habilitados. No obstante, cabe señalar que el sistema queda en un estado inestable y que es muy probable que se produzca un oops.
En la carpeta configs/, encontrarás archivos de configuración para el kernel de Linux
y Busybox, cada uno ligeramente diferente de los predeterminados.
La carpeta binaries/ contiene todos los binarios precompilados que necesitarás
para reproducir nuestro entorno de pruebas, como un rootfs completo listo para
usarse con QEMU.
linux-stable es un submódulo de git que apunta a una revisión vulnerable del kernel
de Linux. Usa git submodule update --recursive para obtenerlo (si tienes al menos
1GB libres en tu sistema...). Lo mismo aplica para busybox.
Nuestro entorno se basa en una máquina virtual QEMU x86 con una carpeta compartida
con el host mediante 9P. Una versión vulnerable del kernel (ff33952e4d23) se
compila junto con una compilación estáticamente enlazada de Busybox.
Nuestra configuración es bastante simple, ya que no necesitamos soportar ningún tipo
de arquitectura o hardware exótico. Se ha generado ejecutando make defconfig y se habilitaron algunas características para soportar la red y el
uso compartido de carpetas de QEMU:
CONFIG_BLK_MQ_VIRTIO=y
CONFIG_MEMORY_BALLOON=y
CONFIG_BALLOON_COMPACTION=y
CONFIG_NET_9P=y
CONFIG_NET_9P_VIRTIO=y
CONFIG_NET_9P_DEBUG=y
CONFIG_VIRTIO_BLK=y
CONFIG_VIRTIO_BLK_SCSI=y
CONFIG_VIRTIO_NET=y
CONFIG_HVC_DRIVER=y
CONFIG_VIRTIO_CONSOLE=y
CONFIG_HW_RANDOM_VIRTIO=y
CONFIG_VIRTIO=y
CONFIG_VIRTIO_PCI=y
CONFIG_VIRTIO_PCI_LEGACY=y
CONFIG_VIRTIO_BALLOON=y
CONFIG_VIRTIO_INPUT=y
CONFIG_VIRTIO_MMIO=y
CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y
CONFIG_9P_FS=y
CONFIG_9P_FS_POSIX_ACL=y
CONFIG_9P_FS_SECURITY=y
También se añadieron scripts de GDB y símbolos de depuración para facilitar el desarrollo de los primeros PoCs:
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF4=y
CONFIG_GDB_SCRIPTS=y
Ten en cuenta que en esta versión, KASLR está habilitado por defecto en x86. Dado que el
kernel se mapea en direcciones diferentes después de cada reinicio, GDB no podrá hacer
coincidir el archivo de símbolos con él. Entonces tienes dos opciones: realizar pruebas
sin KASLR o pasar la dirección base del kernel a symbol-file al
cargar los símbolos en GDB.
Después de compilarlo, encontrarás el bzImage en linux-stable/arch/x86/boot/bzImage.
Este archivo está presente en binaries/bzImage y nuestro archivo de configuración en
confifs/kernel.config. Para usarlo, solo tienes que copiarlo como .config
en linux-stable.
Usamos la última versión estable de Busybox, 1.28. El único ajuste que hay que cambiar es
CONFIG_STATIC, ponlo en y. Compilarlo no debería causar ningún problema.
Nuestro archivo de configuración está disponible en configs/busybox.config y un
binario compilado estáticamente en binaries/busybox. Al igual que con Linux, solo tienes que copiarlo
como .config en la carpeta de fuentes de Busybox.
Busybox ya implementa un proceso init que intentará ejecutar /etc/init.d/rcS.
Normalmente, este lo proporciona tu distribución (posiblemente con un nombre diferente),
pero ¡aquí tendremos que hacerlo nosotros mismos! Este script creará y montará
varias carpetas obligatorias del sistema (proc, sys, dev), nuestra carpeta compartida con
el host y nos llevará a un shell sin privilegios:
for i in $(seq 1 9); do mknod /dev/tty$i c 4 1; done
mknod -m 0666 /dev/null c 1 3
mknod -m 0660 /dev/ttyS0 c 4 64
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -t devtmpfs none /dev
mkdir -p /mnt/share
mount -t 9p -o trans=virtio share /mnt/share/ -oversion=9p2000.L,posixacl,sync
chmod 777 /mnt/share/
export ENV=/etc/profile
setsid cttyhack setuidgid 1000 sh
umount /proc
umount /sys
umount /dev
poweroff -f
El archivo /etc/profile no es obligatorio, pero resulta útil durante nuestras pruebas,
especialmente cuando el exploit no era fiable y se necesitaron varios intentos para
obtener privilegios de root.
El proceso detrás de la redacción del exploit está bastante documentado en MISC 96: usamos
unsafe_put_user para sondear la memoria hasta encontrar la dirección base del heap.
Luego, miles de llamadas a clone nos permiten rociar numerosas estructuras cred
en la memoria. Durante nuestras pruebas, su posición en memoria era mucho más "constante"
que al usar fork, ya que asigna menos estructuras para la nueva tarea.
Salir del hijo provocará un oops del kernel, debido a una solicitud de paginación defectuosa; esto debe manejarse correctamente.
Si quieres mejorar la fiabilidad de este exploit o añadir documentación, ¡las contribuciones son bienvenidas! También es posible que hayamos cometido errores o imprecisiones en algunos conceptos; no dudes en abrir un issue si crees que algo está mal.
Kernel de Linux
Explotación