У цій статті розглядається фундаментальна модель безпеки Docker: як працює ізоляція контейнерів, яку роль відіграють namespaces, cgroups та системні обмеження, а також чому доступ до Docker-демона фактично дорівнює повному контролю над хостом. Окрема увага приділяється типовим конфігураційним помилкам, які трапляються навіть у досвідчених команд, і пояснюється, чому вони становлять реальну загрозу.
Двигун Docker використовує простори імен та групи C ядра Linux для ізоляції контейнерів, пропонуючи базовий рівень безпеки. Додатковий захист забезпечується за допомогою Capabilities dropping , Seccomp та SELinux/AppArmor , що покращує ізоляцію контейнерів. Плагін автентифікації може додатково обмежити дії користувача.
Доступ до Docker-двигуна можна отримати локально через Unix-сокет або віддалено за допомогою HTTP. Для віддаленого доступу важливо використовувати HTTPS та TLS , щоб забезпечити конфіденційність, цілісність та автентифікацію.
Двигун Docker за замовчуванням прослуховує сокет Unix за адресою unix:///var/run/docker.sock. У системах Ubuntu параметри запуску Docker визначені в /etc/default/docker. Щоб увімкнути віддалений доступ до API та клієнта Docker, відкрийте демон Docker через HTTP-сокет, додавши такі налаштування:
DOCKER_OPTS="-D -H unix:///var/run/docker.sock -H tcp://192.168.56.101:2376" sudo service docker restart
Однак, з міркувань безпеки не рекомендується розкривати демон Docker через HTTP. Бажано захищати з’єднання за допомогою HTTPS. Існує два основних підходи до захисту з’єднання:
Клієнт перевіряє особу сервера.
І клієнт, і сервер взаємно автентифікують ідентичність один одного.
Сертифікати використовуються для підтвердження ідентичності сервера. Докладні приклади обох методів див. у цьому посібнику .
Образи контейнерів можна зберігати як у приватних, так і в публічних репозиторіях. Docker пропонує кілька варіантів зберігання образів контейнерів:
Docker Hub : Публічний реєстр від Docker.
Docker Registry : проект з відкритим кодом, що дозволяє користувачам розміщувати власний реєстр.
Docker Trusted Registry : комерційна пропозиція Docker для реєстру, що включає автентифікацію користувачів на основі ролей та інтеграцію зі службами каталогів LDAP.
Контейнери можуть мати вразливості безпеки або через базовий образ, або через програмне забезпечення, встановленого поверх базового образу. Docker працює над проектом під назвою Nautilus , який виконує сканування безпеки контейнерів та перераховує вразливості. Nautilus працює, порівнюючи кожен шар образу контейнера з репозиторієм вразливостей, щоб виявити діри безпеки.
Для отримання додаткової інформації прочитайте це.
docker scanЦя docker scanкоманда дозволяє сканувати існуючі образи Docker за назвою образу або ідентифікатором. Наприклад, виконайте таку команду, щоб сканувати образ hello-world:
docker scan hello-world Testing hello-world... Organization: docker-desktop-test Package manager: linux Project name: docker-image|hello-world Docker image: hello-world Licenses: enabled ✓ Tested 0 dependencies for known issues, no vulnerable paths found. Note that we do not currently have vulnerability data for your image.
trivy -q -f json <container_name>:<tag>
snyk container test <image> --json-file-output=<output file> --severity-threshold=high
clair-scanner -w example-alpine.yaml --ip YOUR_LOCAL_IP alpine:3.5
Підписання образів Docker забезпечує безпеку та цілісність образів, що використовуються в контейнерах. Ось стислий опис:
Docker Content Trust використовує проект Notary, заснований на The Update Framework (TUF), для керування підписанням образів. Для отримання додаткової інформації див. Нотаріус та TUF .
Щоб активувати довіру до контенту Docker, встановіть
export DOCKER_CONTENT_TRUST=1. Ця функція вимкнена за замовчуванням у Docker версії 1.10 та пізніших.
Якщо цю функцію ввімкнено, можна завантажувати лише підписані образи. Початкове надсилання образу вимагає встановлення парольних фраз для кореневого ключів та ключів тегування, а Docker також підтримує Yubikey для підвищення безпеки. Докладніше див. тут .
Спроба отримати непідписане зображення з увімкненою довірою до вмісту призводить до помилки «Немає даних про довіру для останньої версії».
Для надсилання образів після першого, Docker запитує пароль ключа репозиторію для підписання образу.
Щоб створити резервну копію своїх закритих ключів, скористайтеся командою:
tar -zcvf private_keys_backup.tar.gz ~/.docker/trust/private
Під час зміни хостів Docker необхідно перемістити кореневий ключ та ключ репозиторію для підтримки роботи.
Огляд функцій безпеки контейнерів
Основні характеристики ізоляції процесу
У контейнерних середовищах ізоляція проектів та їхніх процесів має першорядне значення для безпеки та управління ресурсами. Ось спрощене пояснення ключових концепцій:
Простори імен
Мета : Забезпечити ізоляцію ресурсів, таких як процеси, мережа та файлові системи. Зокрема, в Docker простори імен відокремлюють процеси контейнера від хоста та інших контейнерів.
Використання
unshare:unshareКоманда (або базовий системний виклик) використовується для створення нових просторів імен, забезпечуючи додатковий рівень ізоляції. Однак, хоча Kubernetes не блокує це по суті, Docker це робить.
Обмеження : Створення нових просторів імен не дозволяє процесу повернутися до просторів імен хоста за замовчуванням. Щоб проникнути в простори імен хоста, зазвичай потрібен доступ до
/procкаталогу хоста, використовуючиnsenterдля входу.
Контрольні групи (CGroups)
Функція : В основному використовується для розподілу ресурсів між процесами.
Аспект безпеки : Самі CGroups не пропонують ізоляційної безпеки, за винятком
release_agentфункції, яка, якщо її неправильно налаштувати, потенційно може бути використана для несанкціонованого доступу.
Падіння можливостей
Важливість : Це вирішальна функція безпеки для ізоляції процесів.
Функціональність : обмежує дії, які може виконувати root-процес, відкидаючи певні можливості. Навіть якщо процес працює з root-правами, відсутність необхідних можливостей перешкоджає йому виконувати привілейовані дії, оскільки системні виклики завершаться невдачею через недостатні дозволи.
Ось можливості, що залишилися після того, як процес відкине інші:
Current: cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap=ep
Секкомп
Це ввімкнено за замовчуванням у Docker. Це допомагає ще більше обмежити системні виклики , які може викликати процес. Профіль Docker Seccomp за замовчуванням можна знайти за адресою https://github.com/moby/moby/blob/master/profiles/seccomp/default.json
AppArmor
У Docker є шаблон, який можна активувати: https://github.com/moby/moby/tree/master/profiles/apparmor
Це дозволить зменшити можливості, системні виклики, доступ до файлів і папок.
Простори імен – це функція ядра Linux, яка розділяє ресурси ядра таким чином, що один набір процесів бачить один набір ресурсів , а інший набір процесів – інший . Ця функція працює за принципом використання одного й того ж простору імен для набору ресурсів і процесів, але ці простори імен посилаються на різні ресурси. Ресурси можуть існувати в кількох просторах.
Docker використовує такі простори імен ядра Linux для досягнення ізоляції контейнерів:
простір імен pid
простір імен монтування
мережевий простір імен
простір імен ipc
Простір імен UTS
Щоб отримати докладнішу інформацію про простори імен, перегляньте наступну сторінку.
Функція ядра Linux cgroups надає можливість обмежувати ресурси, такі як процесор, пам’ять, введення-виведення, пропускну здатність мережі, серед набору процесів. Docker дозволяє створювати контейнери за допомогою функції cgroup, яка дозволяє контролювати ресурси для конкретного контейнера.
Нижче наведено контейнер, створений з обмеженим обсягом пам’яті користувача до 500 МБ, обмеженим обсягом пам’яті ядра до 50 МБ, спільним використанням процесора до 512 МБ та blkioweight до 400. Частка процесора – це коефіцієнт, який контролює використання процесора контейнером. Він має значення за замовчуванням 1024 та діапазон від 0 до 1024. Якщо три контейнери мають однакову частку процесора 1024, кожен контейнер може використовувати до 33% процесора у разі конфлікту за ресурси процесора. blkio-weight – це коефіцієнт, який контролює введення-виведення контейнера. Він має значення за замовчуванням 500 та діапазон від 10 до 1000.
docker run -it -m 500M --kernel-memory 50M --cpu-shares 512 --blkio-weight 400 --name ubuntu1 ubuntu bash
Щоб отримати контрольну групу контейнера, ви можете зробити наступне:
docker run -dt --rm denial sleep 1234 #Run a large sleep inside a Debian container ps -ef | grep 1234 #Get info about the sleep process ls -l /proc/<PID>/ns #Get the Group and the namespaces (some may be uniq to the hosts and some may be shred with it)
Для отримання додаткової інформації перевірте: CGroups
Можливості дозволяють точніше контролювати можливості, які можна дозволити користувачеві root. Docker використовує функцію можливостей ядра Linux для обмеження операцій, які можна виконувати всередині контейнера незалежно від типу користувача.
Коли запускається Docker-контейнер, процес втрачає конфіденційні можливості, які він міг би використовувати для виходу з ізоляції . Це робиться для того, щоб процес не зміг виконувати конфіденційні дії та виходити з ізоляції.
Це функція безпеки, яка дозволяє Docker обмежувати системні виклики , які можна використовувати всередині контейнера.
AppArmor — це вдосконалення ядра, яке дозволяє обмежити контейнери обмеженим набором ресурсів з профілями для кожної програми .
Система міток : SELinux призначає унікальну мітку кожному процесу та об’єкту файлової системи.
Застосування політик : Застосовує політики безпеки, що визначають, які дії мітка процесу може виконувати над іншими мітками в системі.
Мітки процесів контейнера : Коли механізми контейнерів ініціюють процеси контейнера, їм зазвичай призначається обмежена мітка SELinux, зазвичай
container_t.
Маркування файлів у контейнерах : Файли в контейнері зазвичай позначаються як
container_file_t.
Правила політики : Політика SELinux в першу чергу гарантує, що процеси з
container_tміткою можуть взаємодіяти (читати, записувати, виконувати) лише з файлами, позначеними якcontainer_file_t.
Цей механізм гарантує, що навіть якщо процес у контейнері скомпрометовано, він обмежується взаємодією лише з об’єктами, які мають відповідні мітки, що значно обмежує потенційну шкоду від таких порушень.
У Docker плагін авторизації відіграє вирішальну роль у безпеці, вирішуючи, чи дозволяти, чи блокувати запити до демона Docker. Це рішення приймається шляхом вивчення двох ключових контекстів:
Контекст автентифікації : сюди входить вичерпна інформація про користувача, наприклад, хто він і як він пройшов автентифікацію.
Контекст команди : Він містить усі відповідні дані, пов’язані з поданим запитом.
Ці контексти допомагають забезпечити обробку лише легітимних запитів від автентифікованих користувачів, що підвищує безпеку операцій Docker.
Якщо ви не обмежуєте належним чином ресурси, які може використовувати контейнер, скомпрометований контейнер може призвести до DoS-аварії на хості, на якому він працює.
# stress-ng sudo apt-get install -y stress-ng && stress-ng --vm 1 --vm-bytes 1G --verify -t 5m # While loop docker run -d --name malicious-container -c 512 busybox sh -c 'while true; do :; done'
nc -lvp 4444 >/dev/null & while true; do cat /dev/urandom | nc <target IP> 4444; done
–привілейований прапор: На наступній сторінці ви можете дізнатися, що
--privilegedозначає цей прапор.
–security-opt: немає-нових-привілеїв
Якщо ви запускаєте контейнер, до якого зловмисник отримує доступ як користувач з низькими привілеями, і у вас неправильно налаштований бінарний файл suid , зловмисник може зловживати ним та підвищувати привілеї всередині контейнера. Це може дозволити йому втекти з нього.
Запуск контейнера з no-new-privilegesувімкненою опцією запобіжить такому підвищенню привілеїв .
docker run -it --security-opt=no-new-privileges:true nonewpriv
#You can manually add/drop capabilities with --cap-add --cap-drop # You can manually disable seccomp in docker with --security-opt seccomp=unconfined # You can manually disable seccomp in docker with --security-opt apparmor=unconfined # You can manually disable selinux in docker with --security-opt label:disable
Щоб переглянути більше --security-optопцій, перегляньте: https://docs.docker.com/engine/reference/run/#security-configuration
Вкрай важливо уникати вбудовування секретів безпосередньо в образи Docker або використання змінних середовища, оскільки ці методи розкривають вашу конфіденційну інформацію будь-кому, хто має доступ до контейнера, через такі команди, як docker inspectабо exec.
Томи Docker є безпечнішою альтернативою, рекомендованою для доступу до конфіденційної інформації. Їх можна використовувати як тимчасову файлову систему в пам’яті, що зменшує ризики, пов’язані з docker inspectведенням журналу. Однак користувачі root та ті, хто має execдоступ до контейнера, все ще можуть отримати доступ до секретних даних.
Секрети Docker пропонують ще безпечніший метод обробки конфіденційної інформації. Для екземплярів, що потребують секретів під час збірки образу, BuildKit пропонує ефективне рішення з підтримкою секретів під час збірки, що підвищує швидкість збірки та надає додаткові функції.
Щоб використовувати BuildKit, його можна активувати трьома способами:
Через змінну середовища:
export DOCKER_BUILDKIT=1
Додаючи префікси до команд:
DOCKER_BUILDKIT=1 docker build .
Увімкнувши його за замовчуванням у конфігурації Docker:
{ "features": { "buildkit": true } }, а потім перезапустіть Docker.
BuildKit дозволяє використовувати секрети під час збірки з опцією --secret, що гарантує, що ці секрети не будуть включені до кешу збірки образу або кінцевого образу, за допомогою команди типу:
docker build --secret my_key=my_value ,src=path/to/my_secret_file .
Для секретів, необхідних у запущеному контейнері, Docker Compose та Kubernetes пропонують надійні рішення. Docker Compose використовує secretsключ у визначенні сервісу для вказівки секретних файлів, як показано в docker-compose.ymlприкладі:
version: "3.7"
services:
my_service:
image: centos:7
entrypoint: "cat /run/secrets/my_secret"
secrets:
- my_secret
secrets:
my_secret:
file: ./my_secret_file.txt
Ця конфігурація дозволяє використовувати секрети під час запуску сервісів за допомогою Docker Compose.
У середовищах Kubernetes секрети підтримуються вбудовано та можуть бути додатково керовані за допомогою таких інструментів, як Helm-Secrets . Керування доступом на основі ролей (RBAC) у Kubernetes підвищує безпеку керування секретами, подібно до Docker Enterprise.
gVisor — це ядро застосунку, написане на Go, яке реалізує значну частину поверхні системи Linux. Воно включає середовище виконання Open Container Initiative (OCI)runsc під назвою , яке забезпечує ізоляційну межу між застосунком та ядром хоста . Середовище runscвиконання інтегрується з Docker та Kubernetes, що спрощує запуск ізольованих контейнерів.
GitHub – google/gvisor: Ядро застосунку для контейнерів
Kata Containers — це спільнота з відкритим кодом, яка працює над створенням безпечного середовища виконання контейнерів з легкими віртуальними машинами, що відчуваються та працюють як контейнери, але забезпечують сильнішу ізоляцію робочого навантаження, використовуючи технологію віртуалізації обладнання як другий рівень захисту.
Не використовуйте
--privilegedпрапорець і не монтуйте Docker-сокет всередині контейнера . Docker-сокет дозволяє створювати контейнери, тому це простий спосіб отримати повний контроль над хостом, наприклад, запустивши інший контейнер з цим--privilegedпрапорцем.
Не запускайте систему від імені root всередині контейнера. Використовуйте іншого користувача та простори імен користувачів . Кореневий доступ у контейнері такий самий, як і на хості, якщо його не перепризначити просторами імен користувачів. Він лише незначно обмежений, головним чином, просторами імен Linux, можливостями та контрольними групами.
Відкиньте всі можливості (
--cap-drop=all) та ввімкніть лише ті, що потрібні (--cap-add=...). Багато робочих навантажень не потребують жодних можливостей, а їх додавання збільшує масштаб потенційної атаки.
Використовуйте параметр безпеки «no-new-privileges» , щоб запобігти отриманню процесами додаткових привілеїв, наприклад, через бінарні файли suid.
Обмеження ресурсів, доступних контейнеру . Обмеження ресурсів можуть захистити машину від атак типу “відмова в обслуговуванні”.
Налаштуйте профілі seccomp , AppArmor (або SELinux) , щоб обмежити дії та системні виклики, доступні для контейнера, до необхідного мінімуму.
Використовуйте офіційні образи Docker та вимагайте підписи або створюйте власні на їх основі. Не успадковуйте та не використовуйте образи з бекдором . Також зберігайте кореневі ключі та пароль у безпечному місці. Docker планує керувати ключами за допомогою UCP.
Регулярно перебудовуйте образи, щоб застосовувати виправлення безпеки до хоста та образів.
Розумно керуйте своїми секретами , щоб зловмиснику було важко отримати до них доступ.
Якщо ви надаєте доступ демону Docker, використовуйте HTTPS з автентифікацією клієнта та сервера.
У вашому Dockerfile надайте перевагу COPY замість ADD . ADD автоматично витягує zip-файли та може копіювати файли з URL-адрес. COPY не має таких можливостей. По можливості уникайте використання ADD, щоб не стати вразливим до атак через віддалені URL-адреси та zip-файли.
Майте окремі контейнери для кожної мікропослуги
Не розміщуйте ssh всередину контейнера, для підключення до контейнера через ssh можна використовувати “docker exec”.
Мати менші зображення контейнерів
Якщо ви знаходитесь всередині контейнера Docker або маєте доступ до користувача в групі Docker , ви можете спробувати уникнути зміни та підвищити привілеї :
Docker Breakout / Ескалація привілеїв
Якщо у вас є доступ до сокета Docker або до користувача в групі Docker, але ваші дії обмежені плагіном Docker Auth , перевірте, чи можна його обійти:
AuthZ та AuthN – плагін авторизації доступу до Docker
Інструмент docker-bench-security – це скрипт, який перевіряє десятки поширених рекомендацій щодо розгортання контейнерів Docker у продакшені. Усі тести автоматизовані та базуються на CIS Docker Benchmark версії 1.3.1 .
Вам потрібно запустити інструмент з хоста, на якому працює docker, або з контейнера з достатніми привілеями. Дізнайтеся, як його запустити, у файлі README: https://github.com/docker/docker-bench-security .
Виглядає що стаття була частково згенерована з AI
– деякі посилання введуть в нікуди
– docker scan вже не актуальний