开发者学堂课程【PostgreSQL 快速入门:26PostgreSQL 对象安全控制】学习笔记,与课程紧密连接,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/16/detail/85
26PostgreSQL 对象安全控制
内容介绍:
一、数据传输加密
二、数据传输加密
三、审计日志-SQL
四、审计日志-基于对象的审计
五、对象安全控制-约束,视图,物化视图
一、数据传输加密
149作为主节点,97作为客户端。
两边的SSL的openssl包已装好。在Postgre DQLhostssl中生成key文件。
在主机上,服务端先生成key文件(检验文件)openssl req -new -text -out server.req -req -sub.j ‘/C-CN/ST-Zhe.jiang/I,-Hangzhou/0-seynabi/CN-‘,可随便赋予first-name,赋予输出名字server-req,可输入任意数据,假设123,123必须记住。显示必须四位以上,再假设12345,就会生成私钥文件和请求的server-req文件,之后可将其配置到数据库中,数据库中有两项配置,最主要的两项,一是key既私钥文件,另一项是IQ文件,先将两项文件配置好。
首先将两项文件复制过来,复制到阿里云 115.28.168.97(1),既数据库的hed,数据库的权限需要修改,修改成600,修改完后将配置文件也进行修改,配置文件的SSL文件将要打开,修改成on,支持的算法也将其打开,两个文件也打开,一是crt文件,crt文件是秘钥的,privkey-pen是key文件,修改完后,将IQ文件生成CRT,提示输入密码,生成PostgrezQAY131220100421360a55Z->文件,PostgrezQAY131220100421360a55Z->文件也要修改为600权限,结算后重启数据库,注意要添加-w,就会提示生成秘钥的数据PEM pass phrase,这样才能重启。
如果将秘钥pass phrase去掉,在生成第四步CRT文件时,可使用密码spenssl req -x500 -in server.req -text -key server.key -out server.crt,因为更安全的做法是将秘钥保留,去掉也可以。这时去连接数据库,从客户端psql -h 115.28.55.149连接,连接后就会显示当前连接是SSL连接,加密算法是DHE-RSA-AES256-SHA,加密位数是256位。
现在客户端和服务端所有的数据传输都是经过SSL加密的,假设有跨公网应用,跨公网连接数据库,或者是两个数据库间传输,复制或者是longdis复制,假设在公网上传输的数据是经过加密,如果没有加密,在公网传输的数据有可能会被截获,进而获取传输的数据。总结:以上的ssl配置是比较简单。
如果要修改SSL加密的算法DHE-RSA-AES256-SHA,可在配置文件中进行修改。假设查看支持那些算法。可在阿里云115.28.55.149中创建extension,去查找连接是否是使用SSL加密,显示为trust,表示当前连接使用SSL加密算法,SHA表示当前的加密算法,前面连接上后也会提示,显示当前SSL连接是哪种版本。
支持命令:
public 1 ssl_cipher 1 text 1 1 nornal
public 1 ssl_client_cert_present 1 boolean 1 1 nornal
public 1 ssl_ client_dn 1 text 1 1 nornal
public 1 ssl_ client_dn_field 1 text 1 1 nornal
public 1 ssl_ client_serial 1 nuneric 1 1 nornal
public 1 ssl_ is_used 1 boolean 1 1 nornal
public 1 ssl_ issuer_dn 1 text 1 1 nornal
public 1 ssl_ issuer_field1 text 1 1 nornal
public 1 ssl_version 1 text 1 1 nornal
ssl 演示结束。
二、数据传输加密
- 如果客户端没办法支持SSL的openssl包,可使用端口加密
http://blog.163.com/digoa@126/blog/static/163877040201342383123592/。
端口加密例子:
Lardis下通过ssh去创建ssh隧道,相当于通过ssh去进行ssh端口的数据转发。
隧道的两边,发送过来的传输,在隧道中是加密的。假设有A服务器在IDCA,B服务器在IDCB,IDCA和IDCB之间不能使用SSL认证方法,可在节点间去假设隧道,在隧道上传输的数据都是加密的,但是会带来性能的下降,比直接使用SSL性能下降得更厉害。观察这两个对比,这两个使用方法简单,在做all_rock会使用,从而生成一个key。相当于不用输入密码就直接建立隧道。
可不建立,只是为了进入隧道后不用输入密码。在33服务器上,在33和39都创建key文件,创建好后,将id_rsa.pub拷贝到ssh/authorired keys文件中,相当于3和9连接可以不使用密码。在39中输入密码后,33颗不用密码。
使用 SSH 命令创建隧道,隧道指定数据传输进行压缩,压缩级别是9。本地监听17100端口,往17100发送数据相当于发送到172.16.3.33上的1999端口,相当于建立连接,相当于连接本地的1999这时连接17100端口,这时连接17100端口,查看隧道是否正常,连接后颗不用查看SSLconnection (eipher: RC4-SMA, bits:120),相当于两层 SSL,将SSLconnection (eipher: RC4-SMA, bits:120)去掉后进行连接,数据也是加密的,通过17100连接相当于通过SSH做成的端口带领进入。
- 测试性能
使用16连接,4个现成,测出是一万六的TPS,使用17100端口,关闭隧道,进行测试。
测试结果的TPS是72410,在压缩的情况下传输是16804TPS,如果不使用压缩,TPS 为七千多,使用压缩效率较高。网络传输时有压缩,就是SSH协议里做的。压缩打开 TPS 是一万七,相差较多性能。
blowfish指的是SSL的加密算法,因blowfish支持SSL加密算法较多,可使用des,bloufish加密算法,各个加密算法之间的效率是有差别的,假设使用bloufish,测出结果是合并,比直接使用SSL加密要低,但是比单个端口带领效率高。因为创建好隧道相当于所有连接都走一个端口,SSH命令只会使用到一个CDU,最终瓶颈变成端口代理服务器,使用加密会消耗CPU的资源,最终是CPU的瓶颈,是端口代理CPU的瓶颈。
如果做多个端口可以将多端口和进行利用,进而去减少瓶颈的可能。但也是不方便的,相当于程序连接数据库使用到不同的端口,较麻烦。测试结果,如果将压缩关闭,使用多个端口代理,就发现比单个端口要高,比直接使用ss加密带来的加密方法要低。
这时CPU相当于四千左右,乘以八连接,三万左右。
- ssl cipher效率对比
前面的测试是SSH,openssh支持的加密算法,这是列出openssh的加密算法。
使用opentrl sped命令测试哪种加密算法效率最高。Sign表示时间,从数据看出,aes128效率是最高。观察100000中的测试,表示是nossl测试,tps为六万三,使用RC4-SHA加密算法测试,得出结果为五万五,具有一定的性能下降。,在数据加密时会损耗一部分性能。使用aes-128,tps为四万七,损耗较严重。最优效率的是RC4-SHA,因测试出的结果数据较高,说明效率高,效率高被破解的简易程度比加密算法破解更容易。
观察最终的权衡。从结果来看,比使用ssh效率要高,因为最快是三万多。
在几种算法中,都能够达到四万以上甚至五万多的cps效率,采用Tener技术是在不得已的情况下,在客户端不能调用SSL数据库的情况下使用。
三、审计日志-SQL
Postgreaql,包括其他数据库可能会记 DBA,或者公司比较关心的事务,比较敏感的数据变更做 chance。
Postgreaql参数文件中支持 mod,mod 表示表级别数据的更改命令可将其记录下来。 INSERT UPDATE,DELETE语句,TRUNCATE语句,是作为mod范畴中的,如果是DDL,有CREATE, ALTER,DROP对表的操作,就会被记录下。
Log_statement=‘ddl’配置的参数对应log_lock_waits-on参数,log_lock_waits-on位于What to Log章节中,记录东西。一般来说,在生长环境中,直接配置ddl,因为ddl记录,对ddl的操作都会记录下来。但是对于普通的INSERT UPDATE,就不会记录。
如果记录UPDATE,DELETE语句,TRUNCATE,量非常大,因为操作多。如果记录某一些用户,假设对业务用户可能不关心INSERT UPDATE, 认为是正常的,业务里发出的seckout语句,对于普通的dba用户,或者coper文件员创建的账号,去做审计,可以单独给用户alter加上相应的权限(APP相当于一个用户)。
赋予digoal是dba用户,加上审计所有的社会语句,将审计的社会语句记录下来。通过用户所有的连接,查找某一事物,其社会语句也会记录下来。查看对应的日志。审计已记录,已记录日志文件中。INSERT UPDATE,DELETE语句,TRUNCATE语句表示一种配置,另一种是对于某一些数据库是非常重要的,所有事物都要记录。
配置ALTER ROLE IN DATABA DATABASE_name,指定数据库名,SET configuration,所有用户连接到该数据库,所有的社会语句就会记录下来,可以配置库级别,或者是角色级别,或者是角色加数据库级别。
四、审计日志-基于对象的审计
对象触发器,当自认为表很重要时,所有的变更都记录。用户的账户信息,假设更改信息,应用程序可能会将更改做流水记录,记录于记录日表里。对于用户账户表的更新,没有审计,直接更新。
另一流水表,假设要记录账户表的每一笔更新,可以触发器加hstore数据类型,因为hstore数据类型比较方便跟踪所有的变更,属于弹性的,类似于 结算的类型,纯属是key-vary的值。
假设创建一个测试表,测试表很重要,是用户的账户信息,将测试表建好,接着创建CREATE EITENSTON hstere,所有的审计记录存在于CREATE EITENSTON hstere数据类型中,使用超级用户去创建EITENSTON,接着再创建记录表,包括所有的表,因演示只使用一个表,所有的表变更全部记录在table_chage_rec表里,table_chage_rec表中记录有ID,id seria18 primary key表示表的PK,relid oid表示表的oid,记录的是 test,审计 test 表,test字段存储17008,对应的是test表,在讲解系统表时有提到。
第三字段table_schema指的是test表对应于哪个表下,table_name表示表名,when_tg表示什么时候触发,在什么情况下触发。
level表示级别,语句级还是statement级。op表示什么操作,in-set,up-date,delete操作。old_rec表示删除操作,删除记录放入old_rec中,new_rec就不含有数据,假设是up-date,old_rec记录更新前这条记录的情况,和更新后的情况。
假设执行inseter,order中就不会存在,只存在于new_rec,crt_time tinesting vithout tine zone DEFAULT nou<>.表示触发器的时间点,后面表示哪个数据库连接的,客户端的地址和客户端的IP是什么,从而能审计出是哪里进行的操作,是否是真正的业务代码还是被攻击的,或者是DBA上修改别人的账号的作用。
dnl_trace触发器
new-rec和old_rec存储的类型都是hstore,表示一条存储着key-vary的记录,old也表示一条存储着key-vary的记录。
用户名标记为session_user,session_user表示会话是哪个用户连接的,inet_client_addr表示当前会话的客户端,假设连接会话,select session_user表示自身连接,切换另一用户连接,就会显示postgres。客户端IP既地址为selsct inet_client_addr<>,因使用unise sockeys连接,所以显示为空地址,端口可以显示。假设连接127.0.0.1,可以显示端口,因为是TSEIP传输。
执行 session_user 代码:
p
oetgres=>select inet_clinet_port<>
i
net_client_port
3
8390
<
1 row>
p
oetgres=>select inet_clinet_addr<>
i
net_client_addr
1
27.0.0.1
<
1 row>
假设是通过阿里云115.28.168.97连接,显示115.28.168.97主机的IP,查看115.28.168.97主机的postgres,显示115.28.55.149的postgres。
就可以在触发器中了解是通过哪个地址连接从而执行的。TG_OP表示 tg执行什么操作,执行delete操作时,将OLD*这行,通过hatore函数合并成hatore的数据类型。
hstore函数类型
该函数传输record,返回hstore类型。将table_chame_rec插入记录表中,table_chame_rec里的relid表示对应表的ID,也是tg_relid,都是表示来自于触发器的变量,假设使用PRPG SECORD,hstore函数的触发器可以支持变量有TG_RELID、TG_RELID表示触发事件的表的RELID是什么,既上面要储存的。
第二字段的schma名字是来自于PRPG SECORD里的TG_TABLE_SCHMA和TG_TABLE_NAUE,都是来自于schma变量,tg_when表示什么时候触发,表示before触发器或者表示after触发器。TG_LEVEL表示是行级别或者是语句级别。
TG_OP表示DELETE,假设是delete,TR_OP等于DELETE。V_old_rec和v_user来自于前面函数定义的变量。如果显示INSET,将NEW转换为hstore,假设显示UPDATE,OLD和NEW都会拥有。将其放入创建的TPL table_chare_rec表中,接着创建触发器,创建后,在CREATE TRTGGER is AFTER DELETE or INSET or UPDATE ON test FOR EACH ROW EKECUTE PROCEDURE dnl_trace()表中再创建触发器,取名为TG,使得在test上操作都会记录在table_change_rec表中。
假设往其中插入一条记录,查询记录,记录已插入,插入test表,在table_change_rec表中也可以查询记录。这个类型属于key-vary类型 ,id表示列名,1表示字段值,info表示列名,digoal表示字段值,crt_tine表示列名,2013-12-22 13:05:28表示字段值。
如果将2013-12-22 13:05:28记录求解,可以使用hstore提供的命令,进行几次dnl,创建一个UPDATE,创建一个DELETE。这时已经记录三笔记录。第一次INSSET,第二次UPDATE,第三次DELETE。执行UPDATE会拥有变更前的数据和变更后的数据,是通过哪个端口进行连接后的变更,都会被记录。如果是按照字段去将KPL读出,可以使用each<old_rec.*>方法读出。
读出在id等于2中,包含3条记录,解出id为1,info为digoal,crt_time时间为2013-12-22 13:05:28。
因触发器函数只写一个,可在想要变更的表上创建触发器。rec表中记录所有变更的表名,操作是INSET ,UPDATE, DELETE,连接的用户。
可以做到精细的控制。如果不想对整个表数据执行chance,可以在创建函数中写入条件,假设只针对于VIP账户,假设表中一段含有VIP,只跟踪VIP账户的变更,可以在触发器函数里进行判断。
假设DELETE时,OLD.*VIP字段值是否为TRUST,如果是就创建,不是就不跟踪这条记录。都可以在函数中做到比较精细的控制。
五、对象安全控制-约束,视图,物化视图
1、约束
账户不能小于0 balance>=0,直接使用check。
2、视图和物化视图
一般被用于控制列或者值的被查询安全。假设表中,对于A用户只开放某一些范围以内的数据,可以建立视图,可不将表的权限直接给予。
查询列
条件筛选行
加密列:假设某一数据加密前不可查看,加密后可查看。只能通过视图来控制加密的条件用法。
3、防范视图攻击
视图也可能被攻击。在讲解espenliand既成本中提到。假设在PostgreSQL中,执行secoke语句,well条件里有两个条件,优先执行成本低的条件。
假设well-A and B,判断两个条件,A消耗成本100,B消耗成本是1,先执行B,得到fruth,A条件不用判断。从而做到运行上的优化。进而就会成为视图被攻击的路口,因为在创建视图时,视图就是well条件,基本上都是well条件。
假设要限制1某些条件,后面肯定有well。假设userinfelid表,里面存有四条记录,在测试表中创建,往里面插入四条记录,视图进入后再创建视图,视图限制条件是groupid等于2,查找视图时只能查找到一条记录,目的是不让查看其他记录。
如何攻击,如何获得情报。创建一个函数,先执行,再去判断userinfelid条件,因为expl视图时,有记录filter:<groupid=2>,记住filter。假设创建攻击函数,指定很低的成本,几乎没有成本。指定成本raise notice,notice中有些值是来源于上方的表,在其中创建userinfelid函数,创建完后,查询select * from v_uterinfe whereattack(idgroupid. usernase.age.addr.eeasil.phane) ,
加入well条件,esckrank查看,含有两个过滤条件,在查询时,有groupid. usernase.age.addr.eeasil.phane 和and过滤条件,先执行成本低的条件,会将所有的结果给出,结果中不显示,可以在函数中res既给出查询到的数据。
所以对于视图的攻击时是简单的,含有创建函数的权限,视图对于用户来首相当于没有创建,还可取到其他别的数据。相当于攻击esperlianed漏洞,既优化器的执行。
因secoke语句含有两个判断条件,前面提到的and。赋予函数的成本为低成本,每一条记录都会先
attack(id.groupid. usernase.age.addr.eeasil.phane判断,再去判断groupid-2。
在判断 attack(id.groupid. usernase.age.addr.eeasil.phane 函数,直接将值抛出,所以可以直接查看这些值。每一条记录是全能扫描,会扫描所有记录,四行记录都会被扫描。扫描每一条时,判断条件,假设是,就会被返回。
当满足两个条件才会fruth。判断时会触发attack(id.groupid. usernase.age.addr.eeasil.phane成本低的,后面groupid-2也会判断,只是当后面判断为trust时,才会判断。
如果是fruth,后面是不进行判断。上面是函数,跟函数里触发的东西没有关系,只是跟成本有关。假设将成本改大,原本默认是1,现改成2。将cost改为2,再执行secoke语句,就不存在,就不便利,成本变高。groupid-2是有成本的,在数据库中,groupid=2对应的函数,都会去执行groupid函数。假设等号对应的groupid里面是int4 eqsel的函数,function是有成本的。
在执行一条secoke语句,假设语句里有well条件,well条件有两个条件,A条件和B条件,A条件要消耗一些资源,进行判断都会消耗资源。
先执行成本低的,先执行
attack <int.int.text.int.text.text.text>cost 2函数,原本已传入几个值给attack <int.int.text.int.text.text.text>cost 2函数,这几个值是表里的字段名。执行id.groupid. usernase.age.addr.eeasil.phane函数时直接将其抛出,返回truth。
进行攻击先抛出notice,将视图隐藏的数据找出。rights将值抛出,本来不会出现。创建视图时可加入security barrier,加入后条件相当于加一层外层,这层外层一直要处于外部,视图就安全。
如何规避该问题。创建视图时加入 security barrier,新建 VUCE 视图。