Для работы с виртуальными средами можно использовать разные решения, но самым популярным до сих пор остается Docker. Его работа основана на изоляции сред, которые крепятся к единому PID, создавая окружение для работающего ПО. В итоге эта гостевая среда на хостовой ОС отображается, как совокупность процессов, которые дополнительно ограничены через Cgroups.
Поэтому и работа с пользователями у контейнеров и хостовой машины тоже происходит через ядро, а точнее их авторизация.
Так вот, в изолированной среде аутентификацию на основе файлов пройти легко, из-за того, что /etc/shadow в распоряжении владельца. А дальнейшей аутентификации на уровне ядра не происходит, только разграничение прав! Соответственно, нужно обезопасить свою хостовую ОС от побега из контейнера нарушителей, которые могли попасть через условный веб!
Как Docker управляет пользователями?
Чтобы раскрыть алгоритм работы с пользователями в виртуальных средах, рассмотрим схему. Изначально, разработчики предвидели потенциальную проблему с нелегитимным доступом у сред, которые разделяют общее ядро. Поэтому решили проблему, добавив маппинг пользователей в инструменты.
Рассмотрим два сценария по схеме: первый без User mapper и второй уже вместе с ним. Так как в контейнере создается отдельная среда с изолированной файловой системой, то пользовательские ID гостевой среды с хостовой могут совпадать. А это значит, что поддельный root в гостевой среде имеет аналогичные права root в хостовой. Данные возможности повлекут ущерб системе, при условии, что подключены тома хостовой.
Атака из контейнера, при развертывании пользователя
Рассмотрим классическое создание пользователя в контейнере. Для этого перейдем к машине и предустановим Docker:
systemctl status docker
Убедимся, что служба запущена и пропишем два файла: Dockerfile и Docker-compose.
# Установка нужных пакетов
RUN apt-get update && apt-get install -y sudo
# Добавляем нового пользователя с помощью переменных окружения
RUN groupadd -g 10000 usergroup && \
useradd -u 10000 -g usergroup -m -s /bin/bash user1 && \
echo "user1 ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
# Установка прав доступа для пользователя
USER user1
WORKDIR /home/user1
CMD ["/bin/bash"]
В данном Dockerfile мы напрямую задали необходимые нам UID и GID пользователя, который будет изолирован в своей среде. Doc ker-compose, который позволит нам создать контейнер выглядит следующим образом:
services:
ubuntu:
build:
context: .
dockerfile: Dockerfile
container_name: ubuntu_container
tty: true
volumes:
- /tmp:/home/user/tmp
Запустим сборку этого образа с контейнером и затем проверим действительно ли был создан пользователь:
Отлично, пользователь в контейнере user1! Но у него оказались умышленно, либо нет от разработчика повышенные права. А еще и прикрепили директорию хоста в работе, при развертывании. Поэтому был создан файл с повышенным правами от лица root на хосте:
Базовым решением будет ограничить полностью подключаемые тома хоста и вместо них использовать виртуальные, либо же открывать возможность использования хостовых файлов только в режиме readonly! Избегая таких директорий, как /etc/shadow.
- /tmp:/home/user/tmp:ro
Так гостевой root не сможет навредить системе, но если все же необходимо добавить системные директории по какой-либо причине, то как раз в игру вступает User Mapper.
Как маппировать пользователей из контейнера?
При нехватке собственных мощностей можно воспользоваться облачными серверами от Serverspace, для этого перейдем к созданию сервера, на любой из двух платформ vStack cloud или же VMware cloud. Нажмем на кнопку Создать сервер и выберем конфигурацию, подходящую под наши задачи, затем нажмем кнопку Создать:
User Mapper перед отправкой системных вызовов меняет UID и GID. К примеру, чтобы root из гостевой среды перестал иметь повышенные права в хостовой, необходимо просто маппировать первого на пользователя с более низкими привилегиями. Для этого открой файл конфигурации /etc/docker/daemon.json и добавь:
"userns-remap": "dockremap"
}
Данная строка говорит, о том что все пользователи гостевой среды будут представлены на хостовой под пользователем dockremap. Создадим его и добавим в нужную группу, где по умолчанию, у него не будет привилегированных прав:
sudo useradd -g dockremap dockremap
И проверим работу маппинга, создав от лица гостевого root новый файл в общей директории:
В результате новосозданный файл получил атрибуты не root, а именно того ограниченного пользователя, которого задали мы. Но и этого способа есть свои минусы, дополнительная среда, при маппировании слегка нагружает работу хостовой ОС. Поэтому данным инструментом можно пользоваться только в случае необходимости работы с хостовыми данными, в других можно обойтись средой контейнера, либо виртуальных томов!