
Prueba de concepto para CVE-2024-21626, una vulnerabilidad de escape de contenedor en runc. Incluye scripts de verificación, dos métodos de explotación (shell inversa mediante cron y reemplazo de comandos), y análisis de la causa raíz y el parche.
| Nombre de la vulnerabilidad | Vulnerabilidad de escape de docker runc |
|---|---|
| ID de vulnerabilidad | CVE-2024-21626 |
| Fecha de divulgación | 2024-01-31 |
| Característica | / |
| Versiones afectadas | runc @ [v1.0.0-rc93,1.1.11] |
Condiciones de explotación: son un poco estrictas, requieren interacción de la víctima; personalmente creo que es un poco inútil:
Verificación de la vulnerabilidad y obtención del descriptor:
git clone https://github.com/V0WKeep3r/CVE-2024-21626-runcPOC.git
cd CVE-2024-21626-runcPOC
bash verify.sh
Como se muestra en la figura siguiente, la vulnerabilidad está presente y el descriptor de archivo es /proc/self/fd8.
verify.sh puede averiguar el valor específico de fd correspondiente al entorno de la máquina actual. Si fd no es 8, hay que modificar el WORKDIR en el Dockerfile al valor correspondiente o especificarlo con -w en docker run.
Verificación de escape/escalada de privilegios: Aquí me acerco más a un escenario práctico: poc.sh utiliza una tarea programada para obtener una reverse shell. poc2.sh usa el método de reemplazar comandos (nota: con este método hay que hacer una copia de seguridad de los archivos con antelación, para no tener dificultades para restaurarlos).
# 需要确认定时任务文件存在,不存在可以创建写,但是那样不能触发定时任务
# 只有crontab -e创建的,在crontab组的文件才会被定时执行。
docker build . -t poc1
docker run -it --rm poc1 bash /poc.sh

POC2:
docker build . -t poc2
docker run -it --rm poc2 bash /poc.sh
# 另起一个terminal
/bin/bash.copy

No lo entiendo del todo, pero combinándolo con el parche se puede entender a grandes rasgos.
Durante docker exec o docker run, se invoca la función execve de runc, pero en el proceso runc exec no se cierran los descriptores de archivo (fd), lo que provoca que los descriptores de archivo del host se filtren también al entorno del contenedor. El usuario puede utilizar estos descriptores para leer y escribir archivos del host y así completar el escape del contenedor.
Solución Actualice runc a la versión 1.12 o superior. Enlace oficial de runc: https://github.com/opencontainers/runc/releases
Análisis del parche
diff commit: https://github.com/opencontainers/runc/commit/2a4ed3e75b9e80d93d1836a9c4c1ebfa2b78870e
Cierra los fds internos justo antes de execve.
init_linux.go: después de chdir, verifica si el cwd (directorio de trabajo actual) está dentro del contenedor.
