Сигурност и СУБД: какво трябва да помните при избора на средства за защита

Сигурност и СУБД: какво трябва да помните при избора на средства за защита

Казвам се Денис Рожков, ръководител съм на разработката на софтуер в компанията «Газинформсервис», в екипа на продукта. Jatoba. Законодателството и корпоративните норми поставят определени изисквания за сигурността на съхранението на данни. Никой не иска трети лица да имат достъп до конфиденциална информация, затова за всеки проект са важни следните въпроси: идентификация и аутентификация, управление на достъпа до данни, осигуряване на целостта на информацията в системата, регистриране на събитията за сигурност. Затова искам да разкажа за някои интересни моменти, свързани с безопасността на СУБД.

Статията е подготвена по повод изказването на @Databases Meetup, организирано от Mail.ru Cloud Solutions. Ако не искате да четете, можете да гледате:

Пуснете видеото

Статията ще се състои от три части:
  • Как да защитим връзките.
  • Какво е одит на действията и как да регистрираме какво става от страна на базата данни и връзката с нея.
  • Как да защитим данните в самата база данни и какви технологии съществуват за това.

Сигурност и СУБД: какво трябва да помните при избора на средства за защита
Трите съставки на безопасността на СУБД: защита на връзките, одит на действията и защита на данните.

Защита на връзките

Към базата данни може да се свързва както директно, така и посредствено през уеб приложения. Обикновено потребителят от страна на бизнеса, т.е. човекът, който работи с СУБД, не взаимодейства с нея директно.

Преди да говорим за защита на връзките, трябва да отговорим на важни въпроси, от които зависи как ще се изградят мерките за сигурност:

  • еквивалентен ли е един бизнес потребител на един потребител на СУБД;
  • осигурява ли се достъп до данните на СУБД само чрез API, който контролираш, или има директен достъп до таблиците;
  • изолиран ли е СУБД в отделен защитен сегмент, кой и как взаимодействат с него;
  • използват ли се pooling/proxy и междинни слоеве, които могат да променят информацията за това как е изградена връзката и кой използва базата данни.

Сега нека погледнем какви инструменти могат да се използват за защита на връзките:

  1. Използвайте решения от клас database firewall. Допълнителният слой на защита поне ще повиши прозрачността на това, което се случва в СУБД, а максимум — ще можете да осигурите допълнителна защита на данните.
  2. Използвайте политики за пароли. Приложението им зависи от това как е структурирана вашата архитектура. Във всички случаи — една парола в конфигурационния файл на уеб приложението, което се свързва с СУБД, не е достатъчна за защита. Има редица инструменти за СУБД, които позволяват контрол върху това как потребителят и паролата изискват актуализация.

    Можете да прочетете повече за функциите за оценка на потребителите тук, също така може да знаете за MS SQL Vulnerability Assessment тук

  3. Обогатете контекста на сесията с необходимата информация. Ако сесията е непрозрачна, не разбирате кой работи в нея в СУБД, можете в рамките на изпълняваната операция да добавите информация за това кой, какво и защо го прави. Тази информация може да се види в одита.
  4. Настройте SSL, ако нямате мрежово разделение на СУБД от крайни потребители, а тя не е в отделен VLAN. В такива случаи е задължително да защитите канала между потребителя и самата СУБД. Има инструменти за защита, включително и сред open source.

Как това ще повлияе на производителността на СУБД?

Нека да видим на примера на PostgreSQL как SSL влияе на натоварването на CPU, увеличаването на тайминга и намаляването на TPS, дали няма да отнеме твърде много ресурси, ако е включен.

Натоварваме PostgreSQL, използвайки pgbench — това е проста програма за стартиране на тестове за производителност. Тя многократно изпълнява една последователност от команди, възможно в паралелни сесии на базата данни, а след това изчислява средната скорост на транзакциите.

Тест 1 без SSL и с използване на SSL — връзката се установява при всяка транзакция:

pgbench.exe --connect -c 10 -t 5000 "host=192.168.220.129 dbname=taskdb user=postgres sslmode=require
sslrootcert=rootCA.crt sslcert=client.crt sslkey=client.key"

срещу

pgbench.exe --connect -c 10 -t 5000 "host=192.168.220.129 dbname=taskdb user=postgres"

Тест 2 без SSL и с използване на SSL — всички транзакции се изпълняват в една връзка:

pgbench.exe -c 10 -t 5000 "host=192.168.220.129 dbname=taskdb user=postgres sslmode=require
sslrootcert=rootCA.crt sslcert=client.crt sslkey=client.key"

срещу

pgbench.exe -c 10 -t 5000 "host=192.168.220.129 dbname=taskdb user=postgres"

Останалите настройки:

scaling factor: 1
query mode: simple
number of clients: 10
number of threads: 1
number of transactions per client: 5000
number of transactions actually processed: 50000/50000

Резултати от теста:

 
NO SSL
SSL

Връзката се установява при всяка транзакция

средно закъснение
171.915 ms
187.695 ms

tps включително установяване на връзки
58.168112
53.278062

tps без установяване на връзки
64.084546
58.725846

CPU
24%
28%

Всички транзакции се изпълняват в една връзка

средно закъснение
6.722 ms
6.342 ms

tps включително установяване на връзки
1587.657278
1576.792883

tps без установяване на връзки
1588.380574
1577.694766

CPU
17%
21%

При малки натоварвания влиянието на SSL е сравнимо с грешката при измерване. Ако обемът на предаваните данни е много голям, ситуацията може да бъде различна. Ако установяваме по едно свързване за всяка транзакция (което е рядко, обикновено свързванията се споделят между потребителите), имате голямо количество свързвания/дисконекции; влиянието може да бъде малко по-голямо. Тоест, рисковете от намалена производителност могат да съществуват, но разликата не е толкова значима, че да не се използва защита.

Обърнете внимание — силна разлика има, ако сравнявате режимите на работа: в рамките на една сесия работите или в различни. Това е разбираемо: за създаването на всяко свързване се изразходват ресурси.

Имаше случай, когато свързвахме Zabbix в режим trust, тоест не проверявахме md5, а аутентикацията не беше необходима. После клиентът поиска да включим режима md5-аутентикация. Това доведе до голямо натоварване на CPU, производителността падна. Започнахме да търсим начини за оптимизация. Едно от възможните решения на проблема е да се реализира мрежово ограничение, да се направят отделни VLAN за СУБД, да се добавят настройки, за да бъде ясно кой и откъде се свързва и да се премахне аутентификацията. Също така, може да се оптимизират настройките на аутентификацията, за да се намалят разходите при включването на аутентификацията, но като цяло, приложението на различни методи за аутентификация влияе на производителността и изисква да се вземат предвид тези фактори при проектирането на изчислителните ресурси на сървърите (железа) за СУБД.

Извод: в редица решения дори малки нюанси при аутентификацията могат да окажат значително влияние върху проекта и е лошо, когато това става ясно едва при внедряването в продуктивна среда.

Аудит на действията

Аудитът не може да бъде само на СУБД. Аудитът е получаване на информация за това, какво се случва на различни сегменти. Това може да бъде както database firewall, така и операционната система, на която е изградена СУБД.

При комерциалните СУБД от ниво Enterprise аудитът е в добро състояние, при open source — не винаги. Ето какво има в PostgreSQL:

  • default log — вградено логване;
  • extensions: pgaudit — ако стандартното логване не е достатъчно, можете да се възползвате от отделни настройки, които решават част от задачите.

Допълнение към доклада във видеото:

Основната регистрация на операторите може да бъде осигурена чрез стандартно средство за водене на дневник с log_statement = all.

Това е приемливо за мониторинг и други видове употреба, но не предоставя ниво на детайлност, обикновено необходимо за одит.

Недостатъчно е просто да имате списък с всички операции, извършвани с базата данни.

Трябва също да има възможност да се намерят конкретни изрази, които представляват интерес за одитора.

Стандартното средство за водене на дневник показва това, което е поискал потребителят, докато pgAudit се фокусира върху детайлите на това, което се е случило, когато базата данни е изпълнявала запитването.

Например, одиторът може да иска да се увери, че конкретна таблица е създадена в документирания прозорец за поддръжка.

Това може да изглежда като проста задача за основен одит и grep, но какво, ако получите нещо подобно (умишлено объркано) пример:

DO $$
BEGIN
EXECUTE ‘CREATE TABLE import’ || ‘ant_table (id INT)’;
END $$;

Стандартното водене на дневник ще ви даде това:

LOG: statement: DO $$
BEGIN
EXECUTE ‘CREATE TABLE import’ || ‘ant_table (id INT)’;
END $$;

Изглежда, че за намиране на интересната таблица може да се наложи известно познаване на кода в случаите, когато таблиците се създават динамично.

Това не е идеално, тъй като би било за предпочитане просто да се търси по име на таблицата.

Тук ще бъде полезен pgAudit.

За същия вход той ще генерира следния изход в дневника:

AUDIT: SESSION,33,1,FUNCTION,DO,,,"DO $$
BEGIN
EXECUTE ‘CREATE TABLE import’ || ‘ant_table (id INT)’;
END $$;
AUDIT: SESSION,33,2,DDL,CREATE TABLE,TABLE,public.important_table,CREATE TABLE important_table (id INT)

Регистрира се не само блокът DO, но и целият текст CREATE TABLE с тип на оператора, тип на обекта и пълното име, което улеснява търсенето.

При воденето на дневници на оператори SELECT и DML pgAudit може да бъде конфигуриран да регистрира отделен запис за всяко отношение, на което има референция в оператора.

Не е необходимо синтактично анализиране, за да се намерят всички оператори, свързани с конкретна таблица (*)».

Как това ще повлияе на производителността на СУБД?

Нека направим тестове с включен пълен одит и да видим какво ще бъде въздействието върху производителността на PostgreSQL. Ще включим максимално дневник на БД по всички параметри.

В конфигурационния файл почти нищо не променяме, от важното — включваме режим debug5, за да получим максимално информация.

postgresql.conf

log_destination = ‘stderr’
logging_collector = on
log_truncate_on_rotation = on
log_rotation_age = 1d
log_rotation_size = 10MB
log_min_messages = debug5
log_min_error_statement = debug5
log_min_duration_statement = 0
debug_print_parse = on
debug_print_rewritten = on
debug_print_plan = включен
debug_pretty_print = включен
log_checkpoints = включен
log_connections = включен
log_disconnections = включен
log_duration = включен
log_hostname = включен
log_lock_waits = включен
log_replication_commands = включен
log_temp_files = 0
log_timezone = ‘Europe/Moscow’

На СУБД PostgreSQL с параметри 1 CPU, 2,8 ГГц, 2 Гб RAM, 40 Гб HDD извършваме три натоварващи теста, използвайки командите:

$ pgbench -p 3389 -U postgres -i -s 150 benchmark
$ pgbench -p 3389 -U postgres -c 50 -j 2 -P 60 -T 600 benchmark
$ pgbench -p 3389 -U postgres -c 150 -j 2 -P 60 -T 600 benchmark

Резултати от тестването:

Без логиране
С логиране

Крайно време за напълване на БД
43,74 сек
53,23 сек

ОЗУ
24%
40%

CPU
72%
91%

Тест 1 (50 свързвания)

Брой транзакции за 10 минути
74169
32445

Транзакции/сек
123
54

Средна закъснение
405 мс
925 мс

Тест 2 (150 свързвания при 100 възможни)

Брой транзакции за 10 минути
81727
31429

Транзакции/сек
136
52

Средна закъснение
550 мс
1432 мс

За размерите

Размер на БД
2251 МБ
2262 МБ

Размер на логовете на БД
0 Мб
4587 Мб

В крайна сметка: пълният одит не е много добро решение. Обемът на данните от одита ще бъде колкото данните в самата база данни, ако не и повече. Такъв обем на логовете, който се генерира при работа с СУБД, е обичайна проблема на продукция.

Гледаме и други параметри:

  • Скоростта не се променя много: без логиране — 43,74 сек, с логиране — 53,23 сек.
  • Производителността по RAM и CPU ще намалее, тъй като трябва да се състави файл с одита. Това също е забележимо на продукция.

При увеличаване на броя на свързванията, естествено, показателите ще се влошават малко.

В корпорациите с одит е още по-сложно:

  • данните са много;
  • одитът е необходим не само чрез syslog в SIEM, но и в файлове: ако с syslog нещо се случи, файлът, в който ще се съхраняват данните, трябва да бъде близо до базата;
  • за одит е необходима отделна платформа, за да не се претоварват дисковете по I/O, тъй като заема много място;
  • често служителите по ИТ сигурност искат навсякъде ГОСТ, изискват удостоверяване по ГОСТ.

Ограничение на достъпа до данните

Нека да разгледаме технологиите, които се използват за защита на данните и достъпа до тях в комерсиални СУБД и open source.

Какво може да се използва по принцип:

  1. Шифроване и обфускация на процедури и функции (Wrapping) — тоест отделни инструменти и утилити, които правят четимия код нечетим. Всъщност, след това не може да се промени или рефакторират обратно. Такъв подход понякога е необходим поне на страната на СУБД — логиката на лицензионните ограничения или логиката на авторизация се шифрова точно на ниво процедури и функции.
  2. Ограничение на видимостта на данните по редове (RLS) е ситуация, при която различни потребители виждат една таблица, но с различен набор редове, тоест на някои потребители не може да им се показва нещо на ниво редове.
  3. Редактиране на показваните данни (Masking) е, когато потребителите в една колона на таблицата виждат или данни, или само звездици, т.е. за определени потребители информацията ще бъде скрита. Технологията определя на кой потребител какво да се показва, в зависимост от нивото на достъп.
  4. Разграничаването на достъпа Security DBA/Application DBA/DBA е по-скоро свързано с ограничаването на достъпа до самата СУБД, което означава, че служителите по информационна безопасност могат да бъдат отделени от базовите администратори и администраторите на приложения. При open source технологии има малко, докато в комерсиалните СУБД те са много. Те са необходими, когато много потребители имат достъп до самите сървъри.
  5. Ограничаване на достъпа до файлове на ниво файлова система. Можете да предоставяте права и привилегии за достъп до директории, така че всеки администратор да има достъп само до необходимите данни.
  6. Мандатният достъп и почистването на паметта — тези технологии се използват рядко.
  7. End-to-end encryption в самата СУБД — това е криптиране от страна на клиента с управление на ключовете на сървъра.
  8. Криптиране на данни. Например, колоночно криптиране — когато използвате механизъм, който криптира отделна колона на базата.

Как това влияе на производителността на СУБД?

Нека разгледаме примера с колонното криптиране в PostgreSQL. Има модул pgcrypto, който позволява да се съхраняват избрани полета в криптиран вид. Това е полезно, когато само някои данни имат стойност. За да се прочетат криптираните полета, клиентът предава ключ за дешифриране, сървърът декриптира данните и ги подава на клиента. Без ключа никой не може да направи нищо с вашите данни.

Нека проведем тест с pgcrypto.. Създаваме таблица с криптирани данни и с обикновени данни. По-долу са командите за създаване на таблиците, а в самия първи ред полезната команда — създаването на самото разширение с регистрация на СУБД:

CREATE EXTENSION pgcrypto;
CREATE TABLE t1 (id integer, text1 text, text2 text);
CREATE TABLE t2 (id integer, text1 bytea, text2 bytea);
INSERT INTO t1 (id, text1, text2)
VALUES (generate_series(1,10000000), generate_series(1,10000000)::text, generate_series(1,10000000)::text);
INSERT INTO t2 (id, text1, text2) VALUES (
generate_series(1,10000000),
encrypt(cast(generate_series(1,10000000) AS text)::bytea, 'key'::bytea, 'bf'),
encrypt(cast(generate_series(1,10000000) AS text)::bytea, 'key'::bytea, 'bf'));

След това ще се опитаме да направим извлечение на данни от всяка таблица и ще видим времевите показания на изпълнението.

Извлечение от таблица без функция за криптиране:

psql -c "timing" -c "select * from t1 limit 1000;" "host=192.168.220.129 dbname=taskdb
user=postgres sslmode=disable" > 1.txt

Хронометърът е стартиран.

  id | text1 | text2
——+——-+——-
1 | 1     | 1
2 | 2     | 2
3 | 3     | 3

997 | 997   | 997
998 | 998   | 998
999 | 999   | 999
1000 | 1000  | 1000
(1000 реда)

Време: 1,386 ms

Извлечение от таблица с функция за криптиране:

psql -c "timing" -c "select id, decrypt(text1, 'key'::bytea, 'bf'),
decrypt(text2, 'key'::bytea, 'bf') from t2 limit 1000;"
"host=192.168.220.129 dbname=taskdb user=postgres sslmode=disable" > 2.txt

Хронометърът е стартиран.

  id | decrypt | decrypt
——+—————+————
1 | x31 | x31
2 | x32 | x32
3 | x33 | x33

999 | x393939 | x393939
1000 | x31303030 | x31303030
(1000 реда)

Време: 50,203 ms

Резултати от теста:

 
Без криптиране
Pgcrypto (decrypt)

Извлечение на 1000 реда
1,386 ms
50,203 ms

CPU
15%
35%

ОЗУ
 
+5%

Криптирането оказва значително влияние върху производителността. Чувствително се увеличава времето, тъй като операциите по декриптиране на криптираните данни (които обикновено са обвити във вашата логика) изискват значителни ресурси. Тоест, идеята да се криптират всички колони, съдържащи някакви данни, може да доведе до понижаване на производителността.

В същото време, криптирането не е сребърна куршум, който решава всички проблеми. Декриптираните данни и ключът за декриптиране по време на декриптиране и предаване на данни са на сървъра. Следователно, ключовете могат да бъдат прихванати от тези, които имат пълен достъп до сървъра на базата данни, например системния администратор.

Когато за цялата колона за всички потребители има само един ключ (дори и да не е за всички, а за ограничен набор от клиенти) — това не винаги е добре и правилно. Затова започнаха да се правят end-to-end криптиране, в СУБД се разглеждат варианти за криптиране на данни отстрана на клиента и сървъра, появиха се така наречените хранилища за управление на ключове — отделни продукти, които осигуряват управление на ключовете отстрана на СУБД.

Сигурност и СУБД: какво трябва да помните при избора на средства за защита
Пример за такова криптиране в MongoDB

Инструменти за сигурност в търговски и open source СУБД

Функции
Тип
Политика за пароли
Аудит
Защита на изходния код на процедури и функции
RLS
Криптиране

Oracle
Комерсиално
+
+
+
+
+

MsSql
Комерсиално
+
+
+
+
+

Jatoba
Комерсиално
+
+
+
+
разширения

PostgreSQL
Безплатно
разширения
разширения

+
разширения

MongoDb
Безплатно

+


Достъпен само в MongoDB Enterprise

Таблицата не е напълно завършена, но ситуацията е следната: в търговските продукти проблемите със сигурността се решават отдавна, в open source обикновено за сигурност се използват някакви надстройки, много функции липсват, понякога се налага да се добавя нещо. Например, политиките за пароли — в PostgreSQL има много различни разширения.1, 2, 3, 4, 5), които реализират паролни политики, но всички изисквания на вътрешния корпоративен сектор, според мен, не покриват нито едно от тях.

Какво да направите, ако никъде не намерите нужното? Например, хочется использовать определенную СУБД, в которой нет функций, которые требует заказчик.

Тогава можете да използвате външни решения, които работят с различни СУБД, например „Крипто БД“ или „Гарда БД“. Ако става дума за решения от вътрешния сектор, те разбират ГОСТ по-добре, отколкото в open source.

Вторият вариант е сами да напишете нужния код, да реализирате достъп до данните и шифроване на приложението на ниво процедури. Разбира се, с ГОСТа ще бъде по-трудно. Но във всеки случай — можете да скриете данните, както трябва, да ги запазите в СУБД, а после да ги извлечете и дешифровате правилно на ниво приложение. Важно е да мислите и как ще защитите тези алгоритми на приложението. Според нас, това трябва да се прави на ниво СУБД, защото така ще работи по-бързо.

Тази презентация бе представена за първи път на @Databases Meetup от Mail.ru Cloud Solutions. Вижте видео други изказвания и се абонирайте за анонсите на събития в Telegram Около Kubernetes в Mail.ru Group.

Какво още да прочетете по темата:

  1. Повече от Ceph: блоково хранилище на облака MCS.
  2. Как да изберем база данни за проекта, за да не се налага да избираме отново.

Източник: habr.com

Купете надежден хостинг за сайтове с защита от DDoS, VPS VDS сървъри 🔥 Купете надежден хостинг за сайтове с защита от DDoS, VPS VDS сървъри | ProHoster