随着时代的发展,审计已经被越来越多的人关注,且一些重要单位已经明文要求数据库中的重要数据,必须开启审计,例如员工的工资。假如某些重要数据被非法或者恶意篡改,那审计的追溯功能就能派上用场。但是要注意一点,审计功能会消耗数据库服务器性能,需根据现场实际情况,制定合理的审计规则。
环境:虚拟机VMware 麒麟V3.3
数据库版本:DM8安全版
程序安装路径:/home/dmdba/dm/dmdbms
数据初始化路径:/home/dmdba/dm/dbdata/dmdata
可执行此命令打开普通审计功能(用SYSAUDITOR用户操作):
SP_SET_PARA_VALUE(1,'ENABLE_AUDIT',1); --DM7
SP_SET_ENABLE_AUDIT(1); --DM8
过程执行完成后,立即生效,审计有三种取值
0 :关闭审计
1:打开普通审计
2:打开普通审计和实时审计
默认值为0
数据库审计员可通过查询 V$DM_INI 动态视图查询 ENABLE_AUDIT 的当前值。
SELECT * FROM V$DM_INI WHERE PARA_NAME='ENABLE_AUDIT';
达梦有三种级别的审计:
1.系统级
系统的启动、关闭、部分系统事件以及一些系统过程和函数的调用,此级别的审计无法也无需由用户进行设置,只要审计开关打开就会自动生成对应审计记录。
比如数据库的启动和停止:
2.语句级
导致影响特定类型数据库对象的特殊 SQL 或语句组的审计。如AUDIT TABLE将审计CREATE TABLE、ALTER TABLE 和 DROP TABLE 等语句
3.对象级
审计作用在特殊对象上的语句。如工资表上的UPDATE语句。
审计配置的规则,会存在表SYSAUDITOR.SYSAUDIT中,新增一条审计规则,就在 SYSAUDIT 中增加一条对应的记录,取消审计则删除 SYSAUDIT 中相应的记录。
增加语句级审计规则,命令格式如下:SP_AUDIT_STMT(TYPE,USERNAME,WHENEVER)
TYPE:审计对象(表,视图,存储过程)
USERNAME:用户,NULL 表示不限制
WHENEVER:审计时机
ALL: 不管成功或是失败都审计
SUCCESSFUL:操作成功的时候审计
FAIL:操作失败的时候审计
取消语句级审计规则,命令格式如下:
函数名称不同,参数意义和增加审计一致
SP_NOAUDIT_STMT(TYPE,USERNAME,WHENEVER)
语句级审计规则,往下细分为:DDL类(表、视图等),DML类(增删改查等),MAC类(策略标记等),其他类(导入导出等),常用的主要是前两种DDL和DML。
示例1:审计DDL类语句
比如审计所有用户登录信息,无论登录成功或失败
SP_AUDIT_STMT('CONNECT', 'NULL', 'ALL'); --审计所有用户登录信息,无论登录成功或失败
示例2:审计DDL类语句
比如TEST用户创建角色、用户、模式、表、视图、索引等成功/失败/无论成功或失败
用SYSAUDITOR(默认密码SYSAUDITOR)用户登录达梦客户端,右键用户,设置审计。
对应的DDL如下:
SP_AUDIT_STMT('TABLESPACE', 'TEST', 'SUCCESSFUL'); --TEST用户创建表空间成功
SP_AUDIT_STMT('USER', 'TEST', 'SUCCESSFUL'); --TEST用户创建用户成功
SP_AUDIT_STMT('ROLE', 'TEST', 'SUCCESSFUL'); --TEST用户创建角色成功
SP_AUDIT_STMT('SCHEMA', 'TEST', 'SUCCESSFUL'); --TEST用户创建模式成功
SP_AUDIT_STMT('TABLE', 'TEST', 'ALL'); --TEST用户创建表无论成功或失败
SP_AUDIT_STMT('VIEW', 'TEST', 'SUCCESSFUL');--TEST用户创建视图成功
SP_AUDIT_STMT('INDEX', 'TEST', 'SUCCESSFUL');--TEST用户创建索引成功
SP_AUDIT_STMT('SEQUENCE', 'TEST', 'SUCCESSFUL');--TEST用户创建序列成功
SP_AUDIT_STMT('SYNONYM', 'TEST', 'SUCCESSFUL');--TEST用户创建同义词成功
SP_AUDIT_STMT('TABLE', 'NULL', 'ALL');--所有用户创建表成功或失败
示例3:审计DML类语句
比如增删改表数据成功,查询表数据失败。执行存储过程,无论成功或失败。
SP_AUDIT_STMT('DELETE TABLE', 'TEST', 'SUCCESSFUL');--TEST用户删除表数据成功
SP_AUDIT_STMT('UPDATE TABLE', 'TEST', 'SUCCESSFUL');--TEST用户更新表数据成功
SP_AUDIT_STMT('INSERT TABLE', 'TEST', 'SUCCESSFUL');--TEST用户插入表数据成功
SP_AUDIT_STMT('SELECT TABLE', 'TEST', 'FAIL');--TEST用户查询表数据失败
SP_AUDIT_STMT('EXECUTE PROCEDURE', 'TEST', 'ALL');--TEST用户执行存储过程,无论成功或失败
SP_AUDIT_STMT('DELETE TABLE', 'NULL', 'SUCCESSFUL');--所有用户删除表数据成功
根据上面配置的规则,模拟一些场景,验证审计效果
审计结果表:
SELECT * FROM v$AUDITRECORDS;
SELECT USERNAME,IP,SCHNAME,OPERATION,SUCC_FLAG,SQL_TEXT,OPTIME FROM V$AUDITRECORDS ORDER BY OPTIME DESC;
示例1:TEST用户连接数据库,成功或失败,会审计
TEST用户连接成功,被记录,符合预期。
连接失败(故意输错密码),被记录,符合预期。
示例2:SYSDBA用户创建用户TEST2,成功或失败,不会被审计
因为规则只限定了TEST用户,所以SYSDBA用户创建用户不会被审计。
SYSDBA用户操作:
审计规则表没有SYSDBA用户的记录,符合预期。
示例3:TEST用户创建表成功或失败,会审计
TEST用户操作:
创建表成功和失败,都被记录,符合预期。
示例4:TEST用户写入、更新、删除数据,成功,会审计;
TEST用户查询数据,失败,会审计;成功,不会审计;
TEST用户操作:
insert into test.t1 values (1,'1');
insert into test.t1 values (2,'2');
insert into test.t1 values (3,'3');
commit;
update test.t1 set name='22' where id='2';
commit;
delete from test.t1 where id='3';
commit;
select * from test.t1;
select * from v$AUDITRECORDS;
增删改被记录,查询成功不被记录,查询失败被记录,符合预期。
**综上所述,所有验证的结果均符合预期,和配置的规则一致。**注意,如果用户执行的一条语句与设置的若干审计项都匹配,只会在审计文件中生成一条审计记录。
增加对象级审计规则,命令格式如下:
SP_AUDIT_OBJECT(TYPE,USERNAME,SCHEMA_NAME,OBJECT_NAME,COLUMN_NAME,WHENEVER)
TYPE:INSERT,DELETE,UPDATE,ALL等
USERNAME :用户名
SCHNAME:模式名,为空时置null
TVNAME:表、视图、存储过程名不能为空
COLNAME:列名
WHENEVER:审计时机
ALL: 不管成功或是失败都审计
SUCCESSFUL:操作成功的时候审计
FAIL:操作失败的时候审计
取消语句级审计规则,命令格式如下:
函数名称不同,参数意义和增加审计一致
SP_NOAUDIT_OBJECT(TYPE,USERNAME,SCHEMA_NAME,OBJECT_NAME,COLUMN_NAME,WHENEVER)
对象级审计规则,往下细分为:表级(指定用户、不指定用户),字段级(指定用户、不指定用户)。
示例1:审计表级语句-指定用户
比如TEST用户对TEST.T1表写入数据,无论成功或失败;查询失败,删除、更新、批量写入数据成功,进行审计。
表名上面右键,设置审计。
--对象级,表级审计规则
SP_AUDIT_OBJECT('INSERT', 'TEST', 'TEST', 'T1', 'ALL'); --TEST用户对TEST.T1表写入数据,无论成功或失败
SP_AUDIT_OBJECT('SELECT', 'TEST', 'TEST', 'T1', 'FAIL'); --TEST用户对TEST.T1表查询失败
SP_AUDIT_OBJECT('DELETE', 'TEST', 'TEST', 'T1', 'SUCCESSFUL'); --TEST用户对TEST.T1表删除数据成功
SP_AUDIT_OBJECT('UPDATE', 'TEST', 'TEST', 'T1', 'SUCCESSFUL'); --TEST用户对TEST.T1表更新数据成功
SP_AUDIT_OBJECT('MERGE INTO', 'TEST', 'TEST', 'T1', 'SUCCESSFUL');--TEST用户对TEST.T1表批量写入数据成功
示例2:审计表级语句-不指定用户(即所有用户)
SP_AUDIT_OBJECT('DELETE', 'NULL', 'TEST', 'T1', 'SUCCESSFUL'); --所有用户对TEST.T1表删除数据成功
SP_AUDIT_OBJECT('UPDATE', 'NULL', 'TEST', 'T1', 'SUCCESSFUL'); --所有用户对TEST.T1表更新数据成功
示例3:审计字段级语句-指定用户
比如TEST用户对表TEST.T1的DT字段的更新成功进行审计。
SP_AUDIT_OBJECT('ALL', 'TEST', 'TEST', 'T1', 'NAME', 'SUCCESSFUL'); --TEST用户对表TEST.T1的NAME字段的所有操作成功(默认)
默认生成的DDL为ALL(即包含了DELETE、UPDATE等等),如果需要手动调整,如下:
SP_AUDIT_OBJECT('UPDATE', 'TEST', 'TEST', 'T1', 'DT', 'SUCCESSFUL'); --TEST用户对表TEST.T1的DT字段的更新成功
其实,相对于字段级来说,ALL和UPDATE效果是一样的,因为咱们平时对表的字段,也不能进行DELETE、INSERT,只能更新。但是考虑到审计规则语法的参数,此处还是单独对此做了一些说明。
根据上面配置的规则,模拟一些场景,验证审计效果
审计结果表:
SELECT * FROM v$AUDITRECORDS;
SELECT USERNAME,IP,SCHNAME,OPERATION,SUCC_FLAG,SQL_TEXT,OPTIME FROM V$AUDITRECORDS ORDER BY OPTIME DESC;
示例1:TEST用户对TEST.T1表写入数据,成功或失败,会审计。SYSDBA用户写入成功或失败,不会被审计。
TEST用户操作:
SYSDBA用户操作:
审计表里,只记录TEST用户写入的操作,符合预期。
示例2:TEST和SYSDBA用户对TEST.T1表更新数据,成功,会审计
SP_AUDIT_OBJECT('UPDATE', 'TEST', 'TEST', 'T1', 'SUCCESSFUL'); --TEST用户对TEST.T1表更新数据成功
SP_AUDIT_OBJECT('UPDATE', 'NULL', 'TEST', 'T1', 'SUCCESSFUL'); --所有用户对TEST.T1表更新数据成功
SYSDBA不满足第一条规则,但是满足第二条规则。TEST用户两条规则都满足,但是只记录一次。
TEST用户操作:
SYSDBA用户操作:
更新数据成功,都被记录,符合预期。
**综上所述,所有验证的结果均符合预期,和配置的规则一致。**注意,如果用户执行的一条语句与设置的若干审计项都匹配,只会在审计文件中生成一条审计记录。
正式环境配置了很多审计规则之后,所有的规则都会记录在审计规则表
select * from SYSAUDITOR.SYSAUDIT
表结构如下:
序号 列 数据类型 说明
1 LEVEL SMALLINT 审计级别
2 UID INTEGER 用户ID
3 TVPID INTEGER 表、视图等ID
4 COLID SMALLINT 列ID
5 TYPE SMALLINT 审计类型
6 WHENEVER SMALLINT 审计情况
LEVEL:1=语句级,2=对象级
WHENVER:1=SUCCESSFUL,2=FAIL,3=ALL
此表不能delete删除,也不能truncate清空,只能通过加入审计规则和移除审计规则增删数据;
且此表的可读性很差,假如想看到底配了些什么规则(尤其是想取消某个规则),目前没有发现好的手段,只能去客户端一个个点,很不现实。因此,本篇文章写了一个查询SQL,可以将一些常用规则,生成一种可读性好的结果集,例如某个环境有以下规则:
规则表数据截图:
可以通下面SQL语句,一键生成配置规则DDL(此SQL只是将一些常用规则做了转义,提供一种解决思路,可自行调整SQL语法,仅供参考);
尤其是前辈交接的数据库,而没有交接当时配置审计的DDL语句,安防组要来检查数据库配置了哪些审计规则,此时,这个SQL就能派上大用场,整体思路和实际可执行SQL如下:
--审计规则表SELECT * FROM SYSAUDITOR.SYSAUDIT;
--根据大量的实际规则数据,找规律,分析对应的值代表的意思,做成转义sql;
--语句级6个字段,其中UID,TVPID,COLID字段值为'-1';
--对象级6个字段,表级审计,COLID字段值为'-1';
--对象级,字段级审计,默认TVPID为'0',对应ALL;
--对象级,字段级审计,参数数量多一个,单独拼sql,注意表ID和字段ID都相等才行;
--SYSOBJECTS对象系统表,通过关联sql,获取模式名和表名;
--SYSCOLUMNS字段系统表,通过关联sql,获取字段名;
SELECT CASE
WHEN LEVEL='1' AND COLID='-1' THEN 'SP_AUDIT_STMT'||'('''||NTYPE||''','''||NUID||''','''||NWHENEVER||''');' --语句级
WHEN LEVEL='2' AND COLID='-1' THEN 'SP_AUDIT_OBJECT'||'('''||NTYPE||''','''||NUID||''','''||SCH||''','''||TAB||''','''||NWHENEVER||''');' --对象级-表
WHEN LEVEL='2' AND COLID!='-1' THEN 'SP_AUDIT_OBJECT'||'('''||NTYPE||''','''||NUID||''','''||SCH||''','''||TAB||''','''||COL_NAME||''','''||NWHENEVER||''');' --对象级-字段
ELSE 'ERROR' END AS DDLS
FROM ( SELECT A.LEVEL ,A.COLID,ZZ.COL_NAME,
CASE WHEN UID='-1' THEN 'NULL' WHEN UID!='-1' THEN (SELECT B.USERNAME FROM ALL_USERS B WHERE B.USER_ID=A.UID) ELSE UID END AS NUID ,
DECODE(A."TYPE",
--语句级DDL
'74','CONNECT', --登录
'9','TABLESPACE',--表空间
'12','USER', --用户
'13','ROLE', --角色
'14','SCHEMA', --模式
'15','TABLE', --表
'16','VIEW', --视图
'20','SEQUENCE', --序列
'17','INDEX', --索引
'26','SYNONYM', --同义词
--语句级 DML
'32','DELETE TABLE', --删除表数据
'33','UPDATE TABLE', --更新表数据
'30','INSERT TABLE', --插入表数据
'31','SELECT TABLE', --查询表数据
'27','EXECUTE PROCEDURE', --存储过程
--对象级-表
'50','INSERT',
'51','SELECT',
'52','DELETE',
'53','UPDATE',
'56','MERGE INTO',
--对象级-字段
'0','ALL',
A."TYPE") AS NTYPE
,(SELECT Y.NAME FROM SYSOBJECTS Y WHERE ID= (SELECT X.SCHID FROM SYSOBJECTS X WHERE X.ID=A.TVPID) AND SUBTYPE$ IS NULL) AS SCH --从系统表获取模式名
,(SELECT Z.NAME FROM SYSOBJECTS Z WHERE Z.ID=A.TVPID) AS TAB --从系统表获取表名
, DECODE(A."WHENEVER",
'1','SUCCESSFUL',
'2','FAIL',
'3','ALL',
A."WHENEVER") AS NWHENEVER --SUCCESSFUL=1,FAIL=2,ALL=3
FROM SYSAUDITOR.SYSAUDIT A LEFT JOIN (SELECT YY.ID AS TABID,
XX.NAME AS COL_NAME,
XX.COLID
FROM SYSCOLUMNS XX
JOIN SYSOBJECTS YY
ON XX.ID=YY.ID
WHERE YY.SUBTYPE$='UTAB' ) ZZ
ON ZZ.TABID=A.TVPID AND ZZ.COLID=A.COLID --表ID相等且字段ID相等,获取字段名称
);
SQL转义结果集如下:
假如想取消某些规则,就可以将结果集粘贴出来,将‘AUDIT’替换成‘NOAUDIT’,执行,即可将对应的审计规则取消。就不用去达梦客户端里面一个个点。
cd /home/dmdba/dm/dmdbms/tool/
./analyzer
或者使用DM审计客户端
登录SYSAUDITOR审计账号,默认密码SYSAUDITOR
右键“审计规则”》“新建审计规则分析”
比如针对所有用户的创建表、用户、删除、更新等操作进行审计。
右键刚创建的审计规则名称,点击“审计规则分析”
弹出的界面,要选择审计日志文件,添加目录或文件
审计日志一般在数据文件同级目录/dbdata/dmdata/DAMENG
可以提前将审计日志文件拿出来一份到WINDOWS的桌面,选好文件之后,点击确定。
等待一分钟,生成的结果如下:(和查询V$AUDITRECORDS效果一样)
注意,执行了INSERT、UPDATE等DML语句,SQL执行成功时,审计日志表就已经记录此操作,后续无论提交还是回滚,都不会再变了。
通过测试TEST.T1表写入数据时,有审计和无审计数据库的性能
SP_AUDIT_OBJECT('INSERT', 'NULL', 'TEST', 'T1', 'ALL');
begin
for i in 1..100000 loop
insert into test.t1 values (i,i||'ABC',sysdate,'noautid');
commit;
end loop;
end;
10万条数据写入耗时21秒
truncate table test.t1;
begin
for i in 1..1000000 loop
insert into test.t1 values (i,i||'ABC',sysdate,'noautid');
commit;
end loop;
end;
100万条数据写入耗时3分53秒
TOP稳定在85%左右,没有超过95%:
iostat稳定在35%左右,没有超过40%
truncate table test.t1;
begin
for i in 1..100000 loop
insert into test.t1 values (i,i||'ABC',sysdate,'sjz2');
commit;
end loop;
end;
10万条数据写入耗时28秒
truncate table test.t1;
begin
for i in 1..1000000 loop
insert into test.t1 values (i,i||'ABC',sysdate,'sjz');
commit;
end loop;
end;
100万条数据写入耗时约5分46秒
TOP稳定在115%左右,没有超过125%
iostat稳定在55%左右,没有超过65%
用同样的方法,将单条数据多次提交,改成批量数据一次性提交。这里就不放太多截图了,有些冗余,挑几个重要的,详情看下个章节的表格即可。SQL如下:
truncate table test.t1;
begin
for i in 1..1000000 loop
insert into test.t1 values (i,i||'ABC',sysdate,'ABC');
end loop;
commit;
end;
无审计100W入库耗时11秒366毫秒
无审计1000W入库耗时1分56秒488毫秒
开审计100W入库耗时15秒415毫秒
开审计1000W入库耗时3分15秒499毫秒
(1)单条多次提交
是否开启审计 10万入库耗时 100万入库耗时 100万的TOP 100万的IO
否 21秒 3分53秒 85% 35%
是 28秒 5分46秒 115% 55%
差值 7秒 113秒 30% 20%
性能损耗 33% 48% 37.5% 57.1%
(2)批量一次性提交
是否开启审计 100万入库耗时 1000万入库耗时 1000万的TOP 1000万的IO
否 11秒238毫秒 1分56秒488毫秒 105% 35%
是 11秒415毫秒 3分15秒499毫秒 170% 65%
差值 177毫米 79秒 65% 30%
性能损耗 1.6% 68% 61% 85%
由此可见,开启审计确实对数据库性能是有影响的,本次简单测试结论性能降低平均约30~50%。具体影响程度,与开启的审计项数量相关,以现场实际情况为准。
(1)只要审计功能被启用,系统级的审计记录就会产生。
(2)在进行数据库审计的时候,审计员之间没有区别,可以审计所有数据库对象,也可以取消其他审计员的审计设置。
(3)语句级审计不针对特定的对象,只针对用户和对象类型。
(4)对象级审计针对指定的用户与指定的对象进行审计。
(5)在设置审计时,审计选项不区分包含关系;审计时机不区分包含关系,都可以设置。
(6)如果用户执行的一条语句与设置的若干审计项都匹配,只会在审计文件中生成一条审计记录。
数据库审计,是数据库运维安全的一种手段,自古以来安全和性能就是你增我减、你强我弱的一种情况,因此需要根据不同的需求、不同的环境,制定合适的审计规则,达到一种相对的平衡,既能满足日常审计,又不会对数据库性能造成太大的影响。个人建议,开启审计之后,语句级的只需开启DDL相关的即可,比如新建表、新建视图等操作量少的;对象级的话,只针对重要表的重要字段开启审计即可,比如工资表的工资列。
仅供参考,如有不足,欢迎斧正。
关于更多达梦数据库审计介绍,参考《DM8安全管理》手册第五章节。
更多资讯请上达梦技术社区了解: https://eco.dameng.com/
文章
阅读量
获赞