Pull to refresh

суБД — Безопасность Данных

Reading time 4 min
Views 14K
В ходе реализации нового проекта заказчик часто задаёт вопрос о том, каким образом защищена внедряемая СУБД. Один из вероятных ответов (неправильный на мой взгляд): «БД находится во внутреннем периметре вычислительной сети и недоступна для злоумышленника». По статистике инсайдеры более опасны, так как у них есть возможность легитимно исследовать уязвимости в предоставленных сервисах.

Предлагаю попробовать самостоятельно настроить уже имеющийся функционал, позволяющий повысить уровень защищённости вашей системы.

Предисловие: мне поручили задачу по написанию утилитки, которая должна проверять настройки PostgreSQL. В этой статье я хочу поделиться аналитикой возможностей данной СУБД, используемых для предотвращения несанкционированного доступа.

1. Обновление программного обеспечения.


Однозначно нужно стараться ставить последнюю версию софта или специальных патчей для закрытия обнаруженных интернет-сообществом уязвимостей. На момент написания стати это — 9.5.4. Далее мы будем изменять параметры в файле postgresql.conf из каталога PGDATA, так как все из них требуют перезапуска службы СУБД.

2. Установка нестандартных настроек


Изменим порт подключения:

port = '5333'

Конечно nmap обнаружит сервис postgres, однако детектировать активное сканирование в сети легче, чем точечное обращение к целевому хосту. При желании можно задействовать port knocking.

3. Ограничение числа возможных подключений


Явно указываем ip-пользователей. Пользователям не часто выдают доступ к написанию SQL-запросов, поэтому ограничиваем количество продуктивных серверов:

listen_addresses = 'ip_1, ip_2, ip_3'

Изменяем максимальное количество одновременных подключений (+1 для суперюзера или репликации). По умолчанию стоит значение 100 (видимо исходя из работы с web-сервером), но если у вас стандартная связка с пулом 1С, то устанавливаем:

max_connections = '4'

В файле pg_hba.conf убираем записи host, hostnossl и local (последний — если не используются доменные сокеты Unix). Оставляем\устанавливаем только hostssl.

Убираем стандартную учётную запись postgres и параметры all: для DATABASE указываем конкретное имя БД, а для USER — имя пользователя, которому разрешено подключение.

В поле METHOD записываем тип аутентификации пользователя + дополнительные опции. В моём примере проверяем валидность пользователей по сертификатам SSL, то есть добавляем параметр cert. У нас получаются строчки вида:

hostssl    test_database             test_user             192.168.23.2/24           cert 

Вообще здесь много свободы для фантазии, так как в postgres реализовали совместимость с GSS, SSPI, IDENT, LDAP, RADIUS и PAM.

4. Усложнение подбора пароля.


Ограниченим время для аутентификации на СУБД:

authentication_timeout = '1s'

Если не используется прямой доступ человеков, то я бы поставил значение «1s» — достаточно для ввода корректной парольной информации роботом, но недостаточно для полноценного брутфорса. Скрываем при помощи MD5 пароли пользователей PostgreSQL:

password_encryption = 'on'

Требуем, чтобы в случае успешного подключения СУБД проводила проверку доступа пользователя к БД. В случае активации этой настройки пользователей придётся создавать в формате <имя_пользователя>@<имя_рабочей_БД>.

db_user_namespace = 'on'

Если хотим использовать аутентификацию GSSAPI — устанавливаем:

krb_server_keyfile = 'файл_гсcапи'
krb_caseins_users = 'on' 

Примечание: Имена становятся регистрозависимыми. При использовании этой настройки пользователям нужно создавать имена в формате <имя_пользователя>@<имя_домена>. Соответственно db_user_namespace нужно переключить в режим off.

5. Использование архитектурных особенностей


Если у вас используется репликация, то можно ограничить количество репликантов при помощи параметров max_wal_senders = 2 и max_replication_slots = 2. Потенциальный злоумышленник даже если и получит доступ к БД, то не сможет сразу скачать все данные бэкапом при условии, что ваши реплики находятся в рабочем состоянии.

Хотя дефолтный уровень изоляции REPEATABLE READ в Postgres более строгий, чем того требует ISO/IEC 9075, тот же стандарт SQL рекомендует использовать:

default_transaction_isolation = 'serializable'

Можно задать default_transaction_read_only = on, а затем создать триггер, который будет срабатывать на изменение уровня транзакций в сессии. Таким образом можно вести журнал вносимых изменений в СУБД.

6. Шифрование канала передачи данных


Включаем ssl — защищаем КПД между PostgreSQL и клиентом:

ssl = 'on'
ssl_ciphers = 'HIGH:+3DES:!aNULL'

Параметр !aNULL запрещает вход анонимных юзеров. На всякий случай явно указываем, что наш сервер будет диктовать свои правила при установлении защищённого соединения (по дефолту так и работает):

ssl_prefer_server_ciphers = 'on'

Генерим сертификаты для SSL — можно по этой инструкции. Учитываем что Postgres требует идентичности имени выданного сертификата и имени пользователя, который производит подключение. Если используем винду, то на неё можно поставить OpenSSL и выполнять те же команды. Сертификаты по умолчанию должны находиться в PGDATA:

  • сертификат нашей СУБД (без ключа):

    ssl_cert_file = 'серт.crt'	
    

  • ключ для СУБД:

    ssl_key_file = 'ключ.key'
    

  • если хотим отслеживать цепочки сертификатов, то добавляем сертификат удостоверяющего центра (УЦ):

    ssl_ca_file = 'ваш_са.crt'	
    

  • при активации предыдущего пункта можно отслеживать список отозванных сертификатов (СОС):

    ssl_crl_file = 'ваш_сос.crl'
    

Перезапускаем службу postgresql, проверяем отсутствие ошибок. На стороне пользователя устанавливаем цепочку сертификатов. Проверить корректность подключения можно при помощи утилиты psql с параметрами:

psql -U test_user sslcert=test_user.crt

Вывод в случае успешного подключения:

SSL-соединение (протокол: TLSv1.2, шифр: ECDHE-RSA-AES256-GCM-SHA384, бит: 256)

Послесловие: Начиная с версии 9.5 была добавлена политика безопасности строк. Про неё и использование нативного шифрования данных в БД надеюсь у меня получится написать отдельный текст.
Tags:
Hubs:
+10
Comments 3
Comments Comments 3

Articles