Database Vault,简称DBV,2005年发布。
Oracle数据库中的SYS用户相当于Linux中的root用户。另一个有DBA权限的用户是SYSTEM。
Separation of duty (SoD),拥有所有权限会导致做坏事,甚至可以删除审计记录。后者可使用外部审计。也就是说,虽不能防止其行为,但可记录其痕迹。
尽管我们可以使用SYS登录,但SYS实际是schema, 拥有很多对象。
多因子认证只用多余1中方式认证用户。
Context-based security - 根据上下文确定是否赋权
Adaptive security - 即时调整和改变
Separation of Duty (SoD) - 禁止让一个人执行所有操作
Conditional auditing - 细粒度的审计
DBV嵌入到数据库软件的核心,是声明式的。
DVSYS拥有的一组表。DBMS_MACADM或OEMCC配置。
HAP = High Assurance Principle
HAP for database security = 1 DB mechanism + 1 DBV mechanism
DB mechanism指传统的账户,权限,角色等;DBV mechanism指factor,rule,realm和command rule。
factor是用PL/SQL来解析的。
factor的组合(与,或)就是rule。
rule set是rule的库,便于维护和重用。
Realm是为需要保护的对象建立的域,系统权限无法访问。可认为是安全沙箱。
12c后的relam称为mandatory realm,即使是对象的属主和具有对象直接访问权限也受realm的保护。
realm可关联用户和角色,用户可以是管理者或参与者。
基于上下文和rule的安全检查。
和SAR(Secure Application Role)激活角色不同,用户必须具有访问对象的权限,Command Rule是额外的保护。
Access = Privilege + DBV rule.
DBV依赖OLS,因此启用DBV会自动启用OLS,但无需OLS许可,除非单独使用OLS。
12c中,DBV和OLS一样默认已安装。
SQL> select parameter, value from v$option where parameter like '%Vault%';
PARAMETER VALUE
------------------------------ ----------
Oracle Database Vault FALSE
启用DBV需要先在CDB中操作:
GRANT CREATE SESSION, SET CONTAINER TO c##sec_admin_owen
IDENTIFIED BY password CONTAINER = ALL;
GRANT CREATE SESSION, SET CONTAINER TO c##dbv_owner_root_backup
IDENTIFIED BY password CONTAINER = ALL;
GRANT CREATE SESSION, SET CONTAINER TO c##accts_admin_ace
IDENTIFIED BY password CONTAINER = ALL;
GRANT CREATE SESSION, SET CONTAINER TO c##dbv_acctmgr_root_backup
IDENTIFIED BY password CONTAINER = ALL;
connect sys as sysdba
BEGIN
CONFIGURE_DV (
dvowner_uname => 'c##dbv_owner_root_backup',
dvacctmgr_uname => 'c##dbv_acctmgr_root_backup',
force_local_dvowner => FALSE);
END;
/
@?/rdbms/admin/utlrp.sql
CONNECT c##dbv_owner_root_backup
EXEC DBMS_MACADM.ENABLE_DV;
CONNECT / AS SYSDBA
SHUTDOWN IMMEDIATE
STARTUP
至此,启用完毕。以上两个backup结尾的用户平时不用,是用来给实际的DV Owner和Account Manager赋权的:
CONNECT c##dbv_owner_root_backup
GRANT DV_OWNER TO c##sec_admin_owen WITH ADMIN OPTION;
CONNECT c##dbv_acctmgr_root_backup
GRANT DV_ACCTMGR TO c##accts_admin_ace WITH ADMIN OPTION;
确认DBV已启用:
SELECT * FROM SYS.DBA_DV_STATUS;
NAME STATUS
------------------- --------------------
DV_APP_PROTECTION NOT CONFIGURED
DV_CONFIGURE_STATUS TRUE
DV_ENABLE_STATUS TRUE
此时,PDB中的DBV尚未启用。
connect sys@sales
BEGIN
CONFIGURE_DV (
dvowner_uname => 'c##dbv_owner_root_backup',
dvacctmgr_uname => 'c##dbv_acctmgr_root_backup');
END;
/
@?/rdbms/admin/utlrp.sql
CONNECT c##dbv_owner_root_backup@sales
EXEC DBMS_MACADM.ENABLE_DV;
connect / as sysdba
ALTER PLUGGABLE DATABASE sales CLOSE IMMEDIATE;
ALTER PLUGGABLE DATABASE sales OPEN;
SELECT * FROM DBA_DV_STATUS;
NAME STATUS
------------------- --------------------
DV_APP_PROTECTION NOT CONFIGURED
DV_CONFIGURE_STATUS TRUE
DV_ENABLE_STATUS TRUE
CONNECT c##dbv_owner_root_backup@sales
GRANT DV_OWNER TO c##sec_admin_owen WITH ADMIN OPTION;
CONNECT c##dbv_acctmgr_root_backup@sales
GRANT DV_ACCTMGR TO c##accts_admin_ace WITH ADMIN OPTION;
至此,我们配置了common user来管理DBV,当然也可以用local user, 此略。
指的就是使用local user来管理。Oracle Docs中介绍很详细,此略,就是将DV_OWNER和DV_ACCTMGR赋予local user。
前面演示过了。
可用OEMCC或DVSYS.DBMS_MACADM Package。
connect c##sec_admin_owen/password@sales
desc DBMS_MACADM
ward off - 避开
一些Oracle Apps, 都有配置好了的安全策略,参见Master Note for Oracle Database Vault security policies with Siebel, PeopleSoft, JD Edwards EnterpriseOne and WebCenter Content (Doc ID 1623425.1)。
包括DV_SECANALYST,DV_ADMIN,DV_OWNER,DV_AUDIT_CLEANUP,DV_MONITOR,DV_ACCTMGR等。
其中最重要的:
根据SoD原则,数据库相关操作分为以下三类:
DAA对应的是DV_ACCTMGR和CONNECT角色,对应用户c##accts_admin_ace。
可以看到,sys用户已经没有新建用户的权利:
SQL> alter session set container=sales;
Session altered.
SQL> grant create session to lisa identified by welcome1;
grant create session to lisa identified by welcome1
*
ERROR at line 1:
ORA-01031: insufficient privileges
关闭audit也是无权限的:
SQL> ALTER system SET audit_sys_operations=false scope=spfile;
ALTER system SET audit_sys_operations=false scope=spfile
*
ERROR at line 1:
ORA-01031: insufficient privileges
ODBA对应的用户默认是SYS,可用于赋权,管理PDB,备份等。
DBV将Package,数据,配置存于账户DVSYS。DVSYS.DBMS_MACADM是管理DBV的唯一手段。SA对应的即DV_OWNER 角色。
sys用户并不能给自己赋dv_owner权限:
SQL> show user
USER is "SYS"
SQL> grant dv_owner to sys;
grant dv_owner to sys
*
ERROR at line 1:
ORA-47410: Realm violation for GRANT on DV_OWNER
由默认的审计策略,记录登录、赋权、账户操作等。
需使用DBMS_MACADM package AUTHORIZE% API。
本例由HR和SH两个schema,使用的是Sample Schema。
创建两个realm,并将HR, SH中的对象添加到相应的realm。
connect c##sec_admin_owen/password@sales
BEGIN
dbms_macadm.create_realm(
realm_name => 'Sales History'
, description => 'Realm for protection of SH objects and roles'
, enabled => dbms_macutl.g_yes
, audit_options => dbms_macutl.g_realm_audit_fail
, realm_type => 0 );
END;
/
BEGIN
dbms_macadm.create_realm(
realm_name => 'Human Resources'
, description => 'Realm for protection of HR objects and roles'
, enabled => dbms_macutl.g_yes
, audit_options => dbms_macutl.g_realm_audit_fail
, realm_type => 1 );
END;
/
BEGIN
dbms_macadm.add_object_to_realm (
realm_name => 'Sales History'
, object_owner => 'SH'
, object_type => '%'
, object_name => '%');
END;
/
BEGIN
dbms_macadm.add_object_to_realm (
realm_name => 'Human Resources'
, object_owner => 'HR'
, object_type => 'TABLE'
, object_name => '%');
END;
/
注意,这两个realm的类型,一个是普通的(0),一个是强制的(1)。
column name format a60
SELECT name, realm_type
FROM dvsys.dba_dv_realm
ORDER BY name;
NAME REALM_TYP
------------------------------------------------------------ ---------
Database Vault Account Management REGULAR
Human Resources MANDATORY
Oracle Database Vault REGULAR
Oracle Default Component Protection Realm REGULAR
Oracle Default Schema Protection Realm REGULAR
Oracle Enterprise Manager REGULAR
Oracle System Privilege and Role Management Realm REGULAR
Sales History REGULAR
8 rows selected.
简单来说,强制realm剥夺了SYS用户甚至是对象属主的权限,除非进行Realm authorization,参见这里:
SQL> connect hr/oracle@sales
Connected.
SQL> select count(*) from employees;
select count(*) from employees
*
ERROR at line 1:
ORA-01031: insufficient privileges
SQL> connect sys@sales as sysdba
Enter password:
Connected.
SQL> select count(*) from hr.employees;
select count(*) from hr.employees
*
ERROR at line 1:
ORA-01031: insufficient privileges
而对于不同realm:
SQL> connect sh/oracle@sales
Connected.
SQL> select count(*) from sh.sales;
COUNT(*)
----------
918843
SQL> connect system/Welcome1@sales
Connected.
SQL> select count(*) from sh.sales;
select count(*) from sh.sales
*
ERROR at line 1:
ORA-01031: insufficient privileges
接下来做Realm authorization, 将object owner指定为realm owner:
connect c##sec_admin_owen/password@sales
BEGIN
dbms_macadm.add_auth_to_realm (
realm_name =>'Human Resources'
, grantee => 'HR'
, rule_set_name => NULL
, auth_options => dbms_macutl.g_realm_auth_owner );
END;
/
BEGIN
dbms_macadm.add_auth_to_realm (
realm_name =>'Sales History'
, grantee => 'SH'
, rule_set_name => NULL
, auth_options => dbms_macutl.g_realm_auth_owner );
END;
/
在以上语句中,grantee可以是用户或角色,建议角色。另rule_set_name为空,但也可配置以指定何时和如何进行Realm authorization。
现在hr可以访问自己的表了:
SQL> connect hr/oracle@sales
Connected.
SQL> select count(*) from hr.employees;
COUNT(*)
----------
107
接下来创建factor:
connect c##sec_admin_owen/password@sales
-- Create a factor for the day of the week
BEGIN
dbms_macadm.create_factor(
factor_name => 'CURRENT_DAY',
factor_type_name => 'Time',
description => 'The current day of the week',
rule_set_name => NULL ,
get_expr => 'TO_CHAR(SYSDATE,''DY'')',
validate_expr => NULL,
identify_by => dbms_macutl.g_identify_by_method,
labeled_by => dbms_macutl.g_labeled_by_self,
eval_options => dbms_macutl.g_eval_on_access,
audit_options => dbms_macutl.g_audit_on_get_error,
fail_options => dbms_macutl.g_fail_with_message);
END;
/
-- Create a factor for the hour of the day
BEGIN
dbms_macadm.create_factor(
factor_name => 'CURRENT_HOUR',
factor_type_name => 'Time',
description => 'The current hour of the day',
rule_set_name => NULL ,
get_expr => 'TO_CHAR(SYSDATE,''HH24'')',
validate_expr => NULL,
identify_by => dbms_macutl.g_identify_by_method,
labeled_by => dbms_macutl.g_labeled_by_self,
eval_options => dbms_macutl.g_eval_on_access,
audit_options => dbms_macutl.g_audit_on_get_error,
fail_options => dbms_macutl.g_fail_with_message);
END;
/
COMMIT;
在以上语句中,get_exp使用了SQL语句,也可以是PL/SQL函数,但返回必须是VARCHAR2类型。
例如:
SQL> connect sys/Welcome1@sales as sysdba
Connected.
CREATE OR REPLACE FUNCTION inside_maint_window RETURN VARCHAR2 IS
l_now DATE := SYSDATE;
l_hour NUMBER := TO_CHAR(SYSDATE,'HH24');
BEGIN
IF TO_CHAR(l_now,'DY') = 'FRI'
AND l_hour BETWEEN 19 AND 23 THEN
RETURN 'Y';
ELSE
RETURN 'N';
END IF;
END;
12 /
Function created.
SQL> GRANT EXECUTE ON inside_maint_window TO dvsys;
Grant succeeded.
SQL> connect c##sec_admin_owen/password@sales
Connected.
BEGIN
dbms_macadm.create_factor(
factor_name => 'In_Maintenance_Window',
factor_type_name => 'Time',
description =>
'The current system time is within the weekly maintenance window.',
rule_set_name => NULL ,
get_expr => 'sec_pol.inside_maint_window',
validate_expr => NULL,
identify_by => dbms_macutl.g_identify_by_method,
labeled_by => dbms_macutl.g_labeled_by_self,
eval_options => dbms_macutl.g_eval_on_access,
audit_options => dbms_macutl.g_audit_on_get_error,
fail_options => dbms_macutl.g_fail_with_message);
END;
16 /
PL/SQL procedure successfully completed.
查询factor:
CONNECT sh@sales
column DAY_OF_WEEK format a20
column HOUR_OF_DAY format a20
SELECT get_factor('CURRENT_DAY') DAY_OF_WEEK
, DVF.F$CURRENT_HOUR HOUR_OF_DAY
FROM dual;
DAY_OF_WEEK HOUR_OF_DAY
-------------------- --------------------
WED 16
rule返回bool值。rule应尽量重用。
DBV rule可关联多个rule set。rule set是rule的集合,其中所有的rule必须返回true。
先创建两个rule:
connect c##sec_admin_owen/password@sales
BEGIN
dbms_macadm.create_rule(
rule_name => 'Is Maintenance Day of Week'
, rule_expr => 'GET_FACTOR(''Current_Day'') = ''FRI'''
);
END;
/
BEGIN
dbms_macadm.create_rule(
rule_name => 'Within Maintenance Hours'
, rule_expr => 'TO_NUMBER(GET_FACTOR(''Current_HOUR'')) BETWEEN 19 AND 23'
);
END;
/
然后创建rule set,管理的rule必须全部返回true:
-- Create the Maintenance Window DBV Rule Set
-- requiring all rules to be true
BEGIN
dbms_macadm.create_rule_set(
rule_set_name =>'Inside Maintenance Window',
description =>'Checks to see if maintenance and patch activity can be executed.',
enabled =>dbms_macutl.g_yes,
eval_options =>dbms_macutl.g_ruleset_eval_all,
audit_options =>dbms_macutl.g_ruleset_audit_fail,
fail_options =>dbms_macutl.g_ruleset_fail_show,
fail_message =>NULL,
fail_code =>NULL,
handler_options =>dbms_macutl.g_ruleset_handler_off,
handler =>NULL);
END;
/
-- Associate the DBV Rules to the DBV Rule Set
BEGIN
dbms_macadm.add_rule_to_rule_set (
rule_set_name => 'Inside Maintenance Window'
, rule_name => 'Is Maintenance Day of Week'
);
END;
/
BEGIN
dbms_macadm.add_rule_to_rule_set (
rule_set_name => 'Inside Maintenance Window'
, rule_name => 'Within Maintenance Hours'
);
END;
/
以上语句,DBMS_MACUTL.G_RULESET_AUDIT_FAIL表示只有在评估失败时审计。
利用之前创建的rule set来实现SAR(激活角色)。
connect c##sec_admin_owen/password@sales
BEGIN
dbms_macadm.create_role(
role_name => 'SH_DELETE_ROLE'
, enabled => 'Y'
, rule_set_name => 'Inside Maintenance Window'
);
END;
/
查看:
CONNECT sys@sales AS SYSDBA
column role format a15
column schema format a15
column package format a20
-- we can see that a role database object has been created
SELECT *
FROM dba_application_roles
WHERE role = 'SH_DELETE_ROLE';
ROLE SCHEMA PACKAGE
--------------- --------------- --------------------
SH_DELETE_ROLE DVSYS DBMS_MACSEC_ROLES
赋予此role删除和读取某表权限:
CONNECT sh@sales
GRANT SELECT ON sh.sales TO sh_delete_role;
将此role加入到realm:
connect c##sec_admin_owen/password@sales
BEGIN
dbms_macadm.add_object_to_realm (
realm_name => 'Sales History'
,object_owner => 'SH'
,object_name => 'SH_DELETE_ROLE'
,object_type => 'ROLE'
);
END;
/
创建测试用户lisa,也可直接用hr用户:
SQL> connect c##accts_admin_ace/password@sales
Connected.
SQL> grant create session to lisa identified by welcome1;
Grant succeeded.
这里无需将SH_DELETE_ROLE赋予用户lisa,也就是说,书中的以下语句是多余的,而且执行也不会成功
SQL> GRANT sh_delete_role TO lisa;
GRANT sh_delete_role TO lisa
*
ERROR at line 1:
ORA-01924: role 'SH_DELETE_ROLE' not granted or does not exist
此时,由于不在维护期,因此也无法启用角色:
SQL> connect hr/oracle@sales
Connected.
SQL> SELECT * FROM session_roles;
ROLE
----------------------------------------
RESOURCE
SODA_APP
SQL> select * from sh.sales;
select * from sh.sales
*
ERROR at line 1:
ORA-00942: table or view does not exist
SELECT get_factor('CURRENT_DAY') DAY_OF_WEEK
, DVF.F$CURRENT_HOUR HOUR_OF_DAY
3 FROM dual;
DAY_OF_WEEK HOUR_OF_DAY
-------------------- --------------------
WED 18
SQL> EXEC dvsys.dbms_macsec_roles.set_role('SH_DELETE_ROLE');
BEGIN dvsys.dbms_macsec_roles.set_role('SH_DELETE_ROLE'); END;
*
ERROR at line 1:
ORA-47305: Rule Set violation on SET ROLE (SH_DELETE_ROLE)
ORA-06512: at "DVSYS.DBMS_MACUTL", line 49
ORA-06512: at "DVSYS.DBMS_MACUTL", line 398
ORA-06512: at "DVSYS.DBMS_MACSEC", line 286
ORA-06512: at "DVSYS.ROLE_IS_ENABLED", line 4
ORA-06512: at "DVSYS.DBMS_MACSEC_ROLES", line 53
ORA-06512: at line 1
为了得到一个成功的例子,我们修改rule:
BEGIN
DBMS_MACADM.UPDATE_RULE(
rule_name => 'Is Maintenance Day of Week'
, rule_expr => 'GET_FACTOR(''Current_Day'') = ''WED'''
);
END;
/
BEGIN
DBMS_MACADM.UPDATE_RULE(
rule_name => 'Within Maintenance Hours'
, rule_expr => 'TO_NUMBER(GET_FACTOR(''Current_HOUR'')) BETWEEN 1 AND 23'
);
END;
/
然后用lisa登录测试:
SQL> connect hr/oracle@sales;
Connected.
SQL> SELECT get_factor('CURRENT_DAY') from dual;
GET_FACTOR('CURRENT_DAY')
--------------------------------------------------------------------------------
WED
SELECT get_factor('CURRENT_DAY') DAY_OF_WEEK
2 , DVF.F$CURRENT_HOUR HOUR_OF_DAY from dual;
DAY_OF_WEEK HOUR_OF_DAY
-------------------- --------------------
WED 18
SQL> SELECT * FROM session_roles;
ROLE
----------------------------------------
RESOURCE
SODA_APP
SQL> EXEC dvsys.dbms_macsec_roles.set_role('SH_DELETE_ROLE');
PL/SQL procedure successfully completed.
SQL> SELECT * FROM session_roles;
ROLE
----------------------------------------
SH_DELETE_ROLE
SQL> select count(*) from sh.sales;
COUNT(*)
----------
918843
command rule类似于trigger, 可应用于SQL语句和PL/SQL。
connect c##sec_admin_owen/password@sales
BEGIN
dbms_macadm.create_command_rule (
command => 'DROP TABLE'
, rule_set_name => 'Inside Maintenance Window'
, object_owner => 'SH'
, object_name => '%'
, enabled => 'Y'
);
END;
/
然后以对象属主登录:
SQL> connect sh@sales
Enter password:
Connected.
column DAY_OF_WEEK format a20
column HOUR_OF_DAY format a20
SQL>
SELECT get_factor('CURRENT_DAY') DAY_OF_WEEK
, DVF.F$CURRENT_HOUR HOUR_OF_DAY
3 FROM dual;
DAY_OF_WEEK HOUR_OF_DAY
-------------------- --------------------
WED 18
SQL> DROP TABLE sh.sales_history;
DROP TABLE sh.sales_history
*
ERROR at line 1:
ORA-47400: Command Rule violation for DROP TABLE on SH.SALES_HISTORY
如果rule set评估为true,则可以删除成功:
SQL> DROP TABLE sh.sales;
Table dropped.
SQL> SHOW RECYCLEBIN;
ORIGINAL NAME RECYCLEBIN NAME OBJECT TYPE DROP TIME
---------------- ------------------------------ ------------ -------------------
SALES BIN$rcZhiHsZYTbgUwEAAH/Alg==$0 TABLE 2020-08-26:18:35:40
SQL> FLASHBACK TABLE SH.SALES TO BEFORE DROP;
Flashback complete.
SQL> select count(*) from sh.sales;
COUNT(*)
----------
918843
做某些配置时需要禁用DBV。此处参考https://docs.oracle.com/en/database/oracle/oracle-database/19/dvadm/disabling-and-enabling-oracle-database-vault.html
先禁止PDB的, 以DV_OWNER用户登录:
CONNECT c##dbv_owner_root_backup@sales
EXEC DBMS_MACADM.DISABLE_DV;
然后重启PDB即可。
CDB如下操作:
CONNECT c##dbv_owner_root_backup@sales
EXEC DBMS_MACADM.DISABLE_DV;
然后重启数据库即可。
SQL> SELECT * FROM V$OPTION WHERE PARAMETER = 'Oracle Database Vault';
PARAMETER
----------------------------------------------------------------
VALUE CON_ID
---------------------------------------------------------------- ----------
Oracle Database Vault
FALSE 0
SQL> drop user c##sec_admin_owen;
User dropped.
SQL> drop user c##accts_admin_ace;
User dropped.
SQL> drop user c##dbv_owner_root_backup;
User dropped.
SQL> drop user c##dbv_acctmgr_root_backup;
User dropped.