Коротко. Утро на серверах: учётки, ключи 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

Закрытые ключи с правами на чтение для всех и копии ключей в домашних каталогах заносятся в таблицу. Заодно выписываются сроки действия сертификатов: это пригодится для мониторинга.

Что сделать с найденным

  1. Закрыть доступы людей, которые ушли. Ключи SSH, учётки ОС, роли в базе, администраторы RX и Keycloak. Это делается в тот же день.
  2. Сменить скомпрометированные пароли. Найденные в истории команд, в репозиториях, в файлах с открытым чтением. Порядок смены для сервисных учёток RX: сначала новый пароль в настройках всех клиентов, потом в самой системе, иначе сервисы потеряют подключение. Удобнее, когда система позволяет на время держать два пароля или две учётки.
  3. Разделить общие учётки на личные. Общая учётка admin означает, что в журнале не видно, кто что делал.
  4. Сузить права. Суперпользователь базы только у администраторов СУБД, группа docker только у тех, кому нужен root, роли брокера по виртуальным хостам.
  5. Перенести секреты в хранилище. Зашифрованные файлы в репозитории или внешнее хранилище секретов, права 0600 на файлы конфигурации. Как это устроить вместе с изменениями через репозиторий, рассказано в статье про GitOps.
  6. Повторять. Таблица из инвентаризации становится реестром доступов. Сверка раз в квартал и при каждом уходе сотрудника или смене подрядчика занимает час, а не день.

Если доступ к контуру есть у подрядчика, этот реестр и регулярная сверка как раз то, что методика ФСТЭК об уровне зрелости позволяет записать в договор.

Чего не делать

  • Не менять пароль сервисной учётки, не зная всех мест, где он записан. Половина сервисов потеряет подключение.
  • Не удалять ключи и учётки массово в первый же час. Сначала таблица и владельцы, потом решения. Неопознанная учётка может оказаться резервным копированием.
  • Не считать удаление пароля из репозитория достаточной мерой. Его нужно сменить.
  • Не забывать группу docker, когда перечисляете администраторов.
  • Не хранить итоговую таблицу в открытой папке. Она сама по себе карта того, куда идти злоумышленнику.