安全性和DBMS:选择保护工具时需要记住的内容


我叫Denis Rozhkov,我是Jatoba产品团队的 Gazinformservice的软件开发主管立法和公司法规对数据存储的安全性提出了某些要求。没有人希望第三方获得机密信息的访问权,因此以下问题对于任何项目都很重要:标识和身份验证,数据访问管理,确保系统中信息的完整性,记录安全事件。因此,我想谈谈有关DBMS安全性的一些有趣的观点。

本文Mail.ru Cloud Solutions托管的@Databases Meetup撰写如果您不想阅读,可以看到:


本文将分为三个部分:

  • 如何保护连接。
  • 什么是对操作的审核以及如何记录数据库部分发生的情况并连接到数据库。
  • 如何保护数据库本身中的数据以及用于此目的的技术是什么。


DBMS安全性的三个组成部分:连接保护,活动审核和数据保护

连接保护


您可以直接或通过Web应用程序间接连接到数据库。通常,业务方面的用户(即与DBMS合作的人)不会直接与之交互。

在谈论保护连接之前,您需要回答一些重要问题,这些问题取决于将如何构建安全措施:

  • 一个业务用户是否等效于一个DBMS用户;
  • 是仅通过您控制的API访问DBMS数据,还是直接访问表?
  • 是否将DBMS分配在单独的受保护网段中,是否与之交互以及如何进行;
  • 是否使用池/代理和中间件,它们可以更改有关如何建立连接以及谁使用数据库的信息。

现在,让我们看看可以使用哪些工具来保护连接:

  1. 使用数据库防火墙类解决方案。至少,额外的保护层将最大程度地提高DBMS中发生的事件的透明度-您可以提供额外的数据保护。
  2. . , . — -, , . , , .

    , MS SQL Vulnerability Assessmen
  3. . , , , , , . .
  4. 配置SSL,如果DBMS与最终用户之间没有网络隔离,则它不在单独的VLAN中。在这种情况下,必须保护使用者与DBMS本身之间的通道。保护工具属于开源软件。

这将如何影响DBMS性能?


让我们看一个PostgreSQL示例,如果启用了太多资源,SSL将如何影响CPU负载,增加计时并降低TPS。

我们使用pgbench加载PostgreSQL-这是一个用于运行性能测试的简单程序。它可能在并行数据库会话中重复执行一个命令序列,然后计算平均事务处理速度。

不使用SSL且使用SSL的测试1-与每个事务建立连接:

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"

不使用SSL且使用SSL的测试2-所有事务均在一个连接中执行:

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

测试结果
 没有SSLSSL协议
在每个交易中建立连接
平均延迟171.915毫秒187.695毫秒
tps包括建立连接58.16811253.278062
tps,不包括建立的连接64.08454658.725846
中央处理器24%28%
所有事务都在一个连接中执行。
平均延迟6.722毫秒6.342毫秒
tps包括建立连接1587.6572781576.792883
tps,不包括建立的连接1588.3805741577.694766
中央处理器17%21%

在轻负载下,SSL的影响可与测量误差相比。如果传输的数据量很大,情况可能会有所不同。如果我们为每个事务建立一个连接(这种情况很少见,通常该连接在用户之间共享),那么您将有大量的连接/断开连接,其效果可能会更大一些。即,可能存在性能下降的风险,但是,差异不大到不使用保护的程度。

请注意,比较操作模式有很大的不同:在同一会话中,您的工作不同。这是可以理解的:资源花费在创建每个连接上。

我们有一种情况,当我们以信任模式连接Zabbix时,也就是说,我们没有检查md5,因此不需要身份验证。然后客户要求启用md5身份验证模式。这给CPU带来了很大的负担,性能下降了。他们开始寻找优化的方法。解决此问题的可能方法之一是实施网络限制,为DBMS创建单独的VLAN,添加设置以使清楚从何处进行连接并删除身份验证,还可以优化身份验证设置以降低启用身份验证的成本,但是通常使用各种方法身份验证会影响性能,并且在为DBMS设计服务器(硬件)的计算能力时需要考虑这些因素。

结论:在许多解决方案中,即使很小的身份验证也会对项目产生很大的影响,并且只有在产品中实现时,这种情况才变得很糟糕。

行动审核


审核不仅可以是DBMS。审计是接收有关不同部门发生的情况的信息。它既可以是数据库防火墙,也可以是构建DBMS的操作系统。

在具有审计功能的商业企业级DBMS中,一切都很好,在开源中-并非总是如此。这是PostgreSQL的功能:

  • 默认日志-内置日志;
  • 扩展名:pgaudit-如果您没有足够的默认日志记录,则可以使用单独的设置来解决一些问题。

视频中的报告之外:

“可以使用log_statement = all的标准日志记录功能为操作员提供基本注册。

这对于监视和其他用途是可以接受的,但不能提供审核通常所需的详细程度。

仅列出数据库执行的所有操作是不够的。

还应该可以找到审计员感兴趣的特定报表。

标准的日志记录工具显示用户请求的内容,而pgAudit则着重于数据库发出请求时所发生事件的详细信息。

例如,审核员可能想要确保已在记录的维护窗口中创建了特定表。

对于基本的审计和grep来说,这似乎是一个简单的任务,但是如果您遇到类似以下(故意混淆)的示例,该怎么办:

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

标准日志记录将为您提供:

LOG:语句:DO $$
BEGIN
EXECUTE'CREATE TABLE import'|| 'ant_table(id INT)';
END $$;

在动态创建表的情况下,似乎似乎需要搜索感兴趣的表。

这不是理想的,因为仅按表名进行搜索会更可取。

这是pgAudit有用的地方。

对于相同的输入,它将在日志中输出以下输出:

审计:SESSION,33.1,功能,请,,,“DO $$
BEGIN
执行'CREATE TABLE进口' || 'ant_table(id INT)';
END $$;“
审计:SESSION,33,2,DDL,CREATE TABLE,TABLE,public.important_table,CREATE TABLE重要表(id INT)

不仅注册DO块,而且还注册了全文CREATE TABLE及其操作符类型,对象类型和全名,使搜索更容易。

在操作员杂志SELECT和DML中,可以将pgAudit配置为为语句中引用的每个关系记录一个单独的条目。

不需要解析以查找与特定表(*相关的所有语句。

这将如何影响DBMS性能?


让我们在启用全面审核的情况下运行测试,看看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 =
debug_print_rewrite = on
debug_print_plan = on
debug_pretty_print = on
log_checkpoints = on
log_connections = on
log_disconnections = on
log_duration = on
log_hostname = on
log_lock_waits = on
log_replication_commands = on
log_temp_files = 0
log_timezone =

在参数为1 CPU,2.8 GHz,2 GB RAM,40 GB HDD的PostgreSQL DBMS上,我们使用以下命令执行三个负载测试:

$ 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%
中央处理器72%91%
测试1(50个连接)
10分钟内的交易数7416932445
事务/秒12354
平均延迟405毫秒925毫秒
测试2(150个连接,可连接100个)
10分钟内的交易数8172731429
事务/秒13652
平均延迟550毫秒1432毫秒
关于尺寸
数据库大小2251兆字节2262兆字节
数据库日志大小0兆4587 Mb

底线:全面审核不是很好。审计产生的数据量会很大,就像数据库本身中的数据一样,甚至更多。使用DBMS时生成的日志量是产品上的常见问题。

我们看一下其他参数:

  • 速度变化不大:没有记录-43.74秒,有记录-53.23秒。
  • RAM和CPU的性能将下降,因为您需要使用审核创建文件。在生产上也很明显。

当然,随着连接数量的增加,性能会略有下降。

在拥有审计的公司中,这甚至更加困难:

  • 有很多数据;
  • 不仅需要通过SIEM中的syslog进行审计,而且还需要对文件进行审计:syslog突然发生了一些事情,保存数据的文件应该靠近数据库;
  • 审计需要一个单独的架子,以免沉没在I / O磁盘上,因为它占用了大量空间;
  • 碰巧IS员工到处都需要GOST,他们需要客人身份证明。

数据访问限制


让我们看一下用于保护数据并在商业DBMS和开放源代码中访问数据的技术。

可以整体使用:

  1. 过程和功能的加密和模糊处理(包装)-即使代码与可读代码不可读的单独工具和实用程序。是的,那么它既不能更改也不能重构。有时至少在DBMS方面需要这种方法-许可限制的逻辑或授权逻辑在过程和功能级别精确加密。
  2. (RLS) — , , - - .
  3. (Masking) — , , - . , .
  4. Security DBA/Application DBA/DBA — , , , database- application-. open source , . , .
  5. . , , .
  6. — .
  7. End-to-end encryption — client-side .
  8. . , — , .

?


让我们看一个PostgreSQL中列加密的例子。有一个pgcrypto模块,它允许您以加密形式存储所选字段。当只有一些数据有价值时,这很有用。为了读取加密的字段,客户端传递解密密钥,服务器对数据解密并将其发布给客户端。没有数据的密钥,任何人都无能为力。

让我们用pgcrypto进行测试创建一个包含加密数据和常规数据的表。以下是用于创建表的命令,在第一行中,一条有用的命令是在注册DBMS的同时创建扩展本身:

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毫秒

从具有加密功能的表中采样:

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 | 解密| 解密
----- + -------------- + ------------
1 | \ x31 | \ x31
2 | \ x32 | \ x32
3 | \ x33 | \ x33
...
999 | \ x393939 | \ x393939
1000 | \ x31303030 | \ x31303030
(1000行)

时间:50.203毫秒

测试结果
 没有加密pgcrypto(解密)
1000行读取1,386毫秒50,203毫秒
中央处理器十五%35%
内存 + 5%

加密对性能有很大影响。可以看出,时间增加了,因为解密加密数据的操作(并且解密通常仍包裹在逻辑中)需要大量资源。也就是说,加密包含某种数据的所有列的想法充满了降低的性能。

但是,加密并不是解决所有问题的灵丹妙药。解密和数据传输过程中的解密数据和解密密钥位于服务器上。因此,可以由对数据库服务器具有完全访问权限的人员(例如系统管理员)拦截密钥。

当所有用户的整个列都有一个键(即使不是全部,但对于一组有限的客户)时,这并不总是正确和正确的。这就是为什么他们开始进行端到端加密的原因,在DBMS中,他们开始考虑用于加密来自客户端和服务器的数据的选项,出现了相同的密钥库存储库-在DBMS端提供密钥管理的单独产品。


MongoDB中这种加密的示例

商业和开源DBMS中的安全功能


功能一种密码政策审计保护过程和功能的源代码RLS加密
甲骨文商业的+++++
Msql的商业的+++++
贾托巴商业的++++扩展名
PostgreSQL的自由扩展名扩展名--+扩展名
Mongodb自由--+----仅在MongoDB Enterprise中可用

该表远未完成,但情况是这样的:在商业产品中,安全性问题已经解决了很长时间,在开源中,通常,一些附件用于安全性,许多功能还不够,有时您必须添加一些内容。例如,密码策略-在PostgreSQL中有很多不同的扩展名(12345)实现密码策略,但在我看来,没有国内企业段的需求都包括在内。

如果什么地方都不需要,该怎么办?例如,我要使用特定的DBMS,其中没有客户需要的功能。

然后,您可以使用适用于不同DBMS的第三方解决方案,例如“ Crypto DB”或“ Garda DB”。如果我们谈论的是来自国内市场的解决方案,那么他们比开源软件更了解GOST。

第二种选择是编写自己所需的内容,在过程级别在应用程序中实现数据访问和加密。没错,有了GOST将会更加困难。但总的来说-您可以根据需要隐藏数据,将其放入DBMS中,然后在应用程序级别将其获取并解密。同时,立即考虑如何在应用程序中保护这些算法。我们认为,这应该在DBMS级别完成,因为它将更快地工作。

最初由Mail.ru Cloud Solutions @Databases Meetup上进行此演讲。观看视频其他出席并在Mail.ru集团的Kubernetes周围报名电报活动公告

还有什么要阅读的主题

  1. 不仅仅是Ceph:MCS块云存储
  2. 如何为项目选择数据库,以免再次选择

All Articles