Доступы и секреты в инсталляции Directum RX: инвентаризация за один день
Как за один рабочий день составить список всех, кто может войти в контур Directum RX, и всех мест, где лежат пароли и ключи. Учётки и ключи SSH на серверах, sudo и группа docker, роли PostgreSQL, пользователи RabbitMQ и Elasticsearch, администраторы RX и Keycloak, пароли в файлах, истории команд, переменных контейнеров и репозиториях. Что делать с найденным.
Коротко. Утро на серверах: учётки, ключи SSH,
sudo, группаdocker, последние входы. День на системах: роли PostgreSQL иpg_hba.conf, пользователи брокера и поиска, администраторы RX и Keycloak. Вечер на секретах: права на файлы конфигурации, истории команд, переменные контейнеров, сканер секретов по репозиториям. Найденное в истории и репозиториях меняется, ушедшие отключаются в тот же день, таблица становится реестром со сверкой раз в квартал.
На вопрос «у кого есть доступ к серверам и базе Directum RX» обычно отвечают списком из трёх фамилий. Если
пройти по серверам, находятся ключи SSH сотрудников, уволенных два года назад, общая учётка admin с паролем,
который знает весь отдел, пароль суперпользователя базы в истории команд и учётные данные брокера в репозитории.
Ниже порядок, который позволяет за один день собрать полную картину, не имея ничего, кроме доступа администратора
и общедоступных утилит.
Симптом
- Никто не может уверенно сказать, кто сейчас может зайти на сервер базы.
- Пароли сервисных учёток не менялись с установки, потому что неизвестно, где они ещё записаны.
- После ухода администратора или смены подрядчика неясно, какие доступы закрыть.
- Проверяющий просит перечень учётных записей с правами администратора, а составить его не из чего.
Почему так
Доступы в контуре RX живут на нескольких уровнях, и у каждого свой способ их выдавать: учётки ОС и ключи SSH, роли в СУБД, пользователи брокера и поиска, администраторы в самой RX и в провайдере входа. Выдают их в спешке при установке и при авариях, а отзывают редко. Секреты расползаются тем же путём: пароль вписали в файл конфигурации, потом в скрипт, потом в команду, которая осталась в истории.
Цель инвентаризации практическая: таблица, где про каждый доступ и каждый секрет известно, чей он, зачем нужен и когда менялся.
Подготовка
Список серверов контура: серверы RX, база и её реплики, брокер, поиск, хранилище, прокси, сервер резервного
копирования, узел администрирования. Команды ниже удобно выполнять сразу на всех через Ansible в режиме
ad-hoc или через pssh: это чтение, ничего не меняется.
Результат сводится в одну таблицу:
| Система | Учётка или секрет | Тип (человек, сервис, общая) | Права | Владелец | Последнее использование или смена | Решение |
|---|---|---|---|---|---|---|
Утро: серверы
Кто может войти
# Учётки с оболочкой входа
getent passwd | awk -F: '$7 !~ /(nologin|false)$/ {print $1, $3, $6, $7}'
# Ключи SSH: у кого и сколько
for f in /root/.ssh/authorized_keys /home/*/.ssh/authorized_keys; do
[ -f "$f" ] && awk -v f="$f" '!/^#/ && NF {print f, $NF}' "$f"
done
# Когда входили
lastlog | grep -v 'Never logged in'
last -n 30 -w
В конце строки ключа обычно комментарий с именем и машиной. Ключи без комментария или с именами вида
user@laptop придётся опознавать по отпечатку (ssh-keygen -lf), спрашивая коллег.
Кто может стать root
grep -rh -v '^#' /etc/sudoers /etc/sudoers.d/ 2>/dev/null | grep -v '^$'
getent group sudo wheel docker
Участник группы docker фактически имеет права root: он может запустить контейнер с корнем файловой системы
хоста. В списке администраторов он должен стоять наравне с теми, у кого есть sudo.
Отдельно проверьте настройки самого SSH: разрешён ли вход под root и по паролю
(sshd -T | grep -E 'permitrootlogin|passwordauthentication').
День: системы рядом с RX
PostgreSQL
SELECT rolname, rolsuper, rolcreaterole, rolcreatedb, rolcanlogin, rolvaliduntil
FROM pg_roles WHERE rolcanlogin ORDER BY rolsuper DESC, rolname;
SELECT line_number, type, database, user_name, address, auth_method
FROM pg_hba_file_rules ORDER BY line_number;
Что искать: учётки людей с правами суперпользователя, общие учётки, правила trust в pg_hba.conf (вход
без пароля) для чего-то кроме локальных подключений, метод md5 там, где можно scram-sha-256. Учётке, под которой
работает RX, нужны права, которые требует документация вашей версии, и не больше. Учётки резервного копирования
и мониторинга обычно обходятся без прав суперпользователя: для них есть встроенные роли
(pg_monitor, pg_read_all_settings и другие).
RabbitMQ и Elasticsearch
rabbitmqctl list_users
rabbitmqctl list_permissions -p /
Учётка guest по умолчанию пускается только с самого сервера брокера. Если ограничение снято (loopback_users),
это находка. Пользователи с тегом administrator перечисляются поимённо.
В Elasticsearch с включённой безопасностью список пользователей и ролей даёт API _security/user. Если
безопасность выключена, любой, кто достучался до порта, читает и удаляет индексы: это отдельная находка
с высоким приоритетом.
RX и провайдер входа
- Члены роли администраторов в самой RX, а также учётки, под которыми работают интеграции и служебные процессы.
- Администраторы Keycloak или другого провайдера входа, если он используется. Отдельно: открыта ли консоль администратора из внешней сети.
- Кто может входить в Directum Launcher и инструменты развёртывания.
После обеда: секреты
Файлы конфигурации
Строки подключения к базе, брокеру, поиску и хранилищу хранятся в файлах конфигурации на серверах. Хранить их там нормально, проверять нужно, кто может эти файлы прочитать:
# Файлы с паролями, которые читают все
grep -rIl -i -E 'password|passwd|secret|token' /etc /opt /srv 2>/dev/null \
| xargs -r ls -l 2>/dev/null | awk '$1 ~ /r..$/'
Права -rw-r--r-- у файла со строкой подключения означают, что пароль базы доступен любой учётке на сервере.
Истории команд и переменные окружения
grep -H -i -E 'password|passwd|PGPASSWORD|token' /root/.bash_history /home/*/.bash_history 2>/dev/null
grep -H -v '^#' /root/.pgpass /home/*/.pgpass 2>/dev/null
# Переменные окружения контейнеров видны всем, у кого есть доступ к docker
docker ps -q | xargs -r docker inspect --format '{{.Name}} {{range .Config.Env}}{{println .}}{{end}}' \
| grep -i -E 'pass|secret|token|key'
Каждый пароль, найденный в истории команд, считается скомпрометированным: он менялся раньше или нет, его нужно сменить.
Репозитории и общие папки
Плейбуки, скрипты и инструкции администраторов проверяются сканером секретов. Он ищет и в текущих файлах, и во всей истории коммитов:
gitleaks git /путь/к/репозиторию --report-path leaks.json
trufflehog filesystem /путь/к/общей/папке
Пароль, который когда-то был закоммичен и потом удалён, остаётся в истории репозитория. Удаление из истории не отменяет того, что его видели все, у кого был клон: такой пароль тоже меняется.
Сертификаты и ключи
find / -xdev \( -name '*.key' -o -name '*.pem' -o -name '*.pfx' -o -name '*.p12' \) 2>/dev/null | xargs -r ls -l
Закрытые ключи с правами на чтение для всех и копии ключей в домашних каталогах заносятся в таблицу. Заодно выписываются сроки действия сертификатов: это пригодится для мониторинга.
Что сделать с найденным
- Закрыть доступы людей, которые ушли. Ключи SSH, учётки ОС, роли в базе, администраторы RX и Keycloak. Это делается в тот же день.
- Сменить скомпрометированные пароли. Найденные в истории команд, в репозиториях, в файлах с открытым чтением. Порядок смены для сервисных учёток RX: сначала новый пароль в настройках всех клиентов, потом в самой системе, иначе сервисы потеряют подключение. Удобнее, когда система позволяет на время держать два пароля или две учётки.
- Разделить общие учётки на личные. Общая учётка
adminозначает, что в журнале не видно, кто что делал. - Сузить права. Суперпользователь базы только у администраторов СУБД, группа
dockerтолько у тех, кому нужен root, роли брокера по виртуальным хостам. - Перенести секреты в хранилище. Зашифрованные файлы в репозитории или внешнее хранилище секретов,
права
0600на файлы конфигурации. Как это устроить вместе с изменениями через репозиторий, рассказано в статье про GitOps. - Повторять. Таблица из инвентаризации становится реестром доступов. Сверка раз в квартал и при каждом уходе сотрудника или смене подрядчика занимает час, а не день.
Если доступ к контуру есть у подрядчика, этот реестр и регулярная сверка как раз то, что методика ФСТЭК об уровне зрелости позволяет записать в договор.
Чего не делать
- Не менять пароль сервисной учётки, не зная всех мест, где он записан. Половина сервисов потеряет подключение.
- Не удалять ключи и учётки массово в первый же час. Сначала таблица и владельцы, потом решения. Неопознанная учётка может оказаться резервным копированием.
- Не считать удаление пароля из репозитория достаточной мерой. Его нужно сменить.
- Не забывать группу
docker, когда перечисляете администраторов. - Не хранить итоговую таблицу в открытой папке. Она сама по себе карта того, куда идти злоумышленнику.
Похожая картина у вас?
Разберём ваш контур за 30 минут бесплатного созвона: версия RX, состав сервисов, что болит сильнее всего.
Написать