суБД — Безпека Даних

В ході реалізації нового проекту замовник часто задає питання про те, яким чином захищена впроваджувана СУБД. Один із ймовірних відповідей (неправильний на мій погляд): «БД знаходиться у внутрішньому периметрі обчислювальної мережі недоступна для зловмисника». За статистикою інсайдери більш небезпечні, так як у них є можливість легітимно дослідити уразливості в наданих послугах.
Пропоную спробувати самостійно налаштувати вже наявний функціонал, що дозволяє підвищити рівень захищеності вашої системи.

Передмова: мені доручили завдання з написання утилітки, яка повинна перевіряти налаштування 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 = 'файл_гссапи'
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 була додана політика безпеки рядків. Про неї і використання нативного шифрування даних в БД сподіваюся, у мене вийде написати окремий текст.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.