一 数据库版本
SYS@LEO1>select * from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
CORE 11.2.0.1.0 Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 – Production
操作系统信息
[oracle@leonarding1 admin]$ uname -a
Linux leonarding1.oracle.com 2.6.32-200.13.1.el5uek #1 SMP Wed Jul 27 21:02:33 EDT 2011 x86_64 x86_64 x86_64 GNU/Linux
二 再谈Oracle安全管理
1.上一篇我们聊到《洪兴社的Oracle情节之安全管理篇(一)》 http://space.itpub.net/26686207/viewspace-763470
主要介绍了“安全认证” “TDE透明数据加密” “细粒度权限控制”这三个方面的Oracle安全技术。从原理到实践我们由浅入深分析了技术细节和应用场景,使大家从整体上了解Oracle技术的发展状态,下面展示一下Oracle安全产品的发展路线
下面是Oracle常见安全解决方案
本文重点讲述内容列表
1.VPN 虚拟私有数据库访问控制
2.OLS 标签安全访问控制
3.Database vault 数据库保险箱
4.FGA细粒度审计
5.SYS管理员级审计
什么是重点:Oracle产品的原理并不复杂,关键是知道在什么场合下适用什么样的产品,产品特性,带来的效果。
三 演示一个VPD进行数据访问控制的示例
1.什么是VPD:Virtual Private Database 虚拟私有数据库,听起来像是一个独立自主的数据库,其实在逻辑上是独立的,物理上就是一个数据库。原理就是通过指定过滤策略,对用户的SQL添加谓词条件,来达到过滤数据的目的。
2.VPD优点:
精细化访问
对业务透明,不同的客户发出相同SQL语句,查询到的结果集不一样,可以让不同客户只看其相关的数据
对用户透明,用户感知不到
不对数据本身做任何操作,只在SQL层面进行过滤处理
VPD是数据库默认自带的,无需独立安装
3.实验
我们建一张业务表car,有汽车名,汽车数量,汽车价格三个字段,插入9条记录,分成高中低三个档次
LEO1@LEO1>create table car (name varchar2(20),num number,cost number);
Table created.
LEO1@LEO1>insert into car values('toyota',10,30); 高级车
1 row created.
LEO1@LEO1>insert into car values('volvo',50,30);
1 row created.
LEO1@LEO1>insert into car values('honda',60,30);
1 row created.
LEO1@LEO1>insert into car values('biaozhi',70,20); 中级车
1 row created.
LEO1@LEO1>insert into car values('xuetielong',80,20);
1 row created.
LEO1@LEO1>insert into car values('polo',90,20);
1 row created.
LEO1@LEO1>insert into car values('xiali',20,10); 低级车
1 row created.
LEO1@LEO1>insert into car values('jili',30,10);
1 row created.
LEO1@LEO1>insert into car values('byd',40,10);
1 row created.
LEO1@LEO1>commit;
Commit complete.
LEO1@LEO1>select * from car;
NAME NUM COST
-------------------- ---------- -------------------- -------------------- ----------
toyota 10 30
volvo 50 30
honda 60 30
biaozhi 70 20
xuetielong 80 20
polo 90 20
xiali 20 10
jili 30 10
byd 40 10
9 rows selected.
我们的思路:car表上添加过滤策略“filter_name”和“filter_num”,当select语句中有name字段时触发“filter_name”策略,当select语句中有num字段时触发“filter_num”策略,过滤策略由函数“fun_name”和“fun_num”实现。
创建函数“fun_name”
LEO1@LEO1>create or replace function fun_name (fun_scheme varchar2,fun_object varchar2)
return varchar2 as fun_cost varchar2(20);
begin
fun_cost:='cost=30';
return(fun_cost);
end fun_name;
/
2 3 4 5 6 7
Function created.
创建函数“fun_num”
LEO1@LEO1>create or replace function fun_num (fun_scheme varchar2,fun_object varchar2)
return varchar2 as fun_cost varchar2(20);
begin
fun_cost:='cost=10';
return(fun_cost);
end fun_num;
/
2 3 4 5 6 7
Function created.
添加过滤策略“filter_name”
LEO1@LEO1>begin
dbms_rls.add_policy(
object_schema => 'leo1',
object_name => 'car',
policy_name => 'filter_name',
policy_function => 'fun_name',
sec_relevant_cols => 'name');
end;
/
2 3 4 5 6 7 8 9
PL/SQL procedure successfully completed.
添加过滤策略“filter_num”
LEO1@LEO1>begin
dbms_rls.add_policy(
object_schema => 'leo1',
object_name => 'car',
policy_name => 'filter_num',
policy_function => 'fun_num',
sec_relevant_cols => 'num');
end;
/
2 3 4 5 6 7 8 9
PL/SQL procedure successfully completed.
当我们要查询汽车名的时候,会触发filter_name过滤策略,从而调用fun_name函数限制where cost=30的记录显示
LEO1@LEO1>select name,cost from car;
NAME COST
-------------------- ----------
toyota 30
volvo 30
honda 30
当我们要查询汽车数量的时候,会触发filter_num过滤策略,从而调用fun_num函数限制where cost=10的记录显示
LEO1@LEO1>select num,cost from car;
NUM COST
---------- ----------
20 10
30 10
40 10
当我们不想使用过滤策略的时候,如何删除?
使用drop_policy存储过程来删除,filter_name和filter_num过滤策略
LEO1@LEO1>execute dbms_rls.drop_policy('leo1','car','filter_name');
PL/SQL procedure successfully completed.
LEO1@LEO1>execute dbms_rls.drop_policy('leo1','car','filter_num');
PL/SQL procedure successfully completed.
LEO1@LEO1>select * from car;
NAME NUM COST
-------------------- ---------- ----------
toyota 10 30
volvo 50 30
honda 60 30
biaozhi 70 20
xuetielong 80 20
polo 90 20
xiali 20 10
jili 30 10
byd 40 10
9 rows selected.
利用VPD隐藏敏感列信息
我们设计一个新的“filter_num”策略,只显示cost=10的记录,隐藏num列的汽车数量
LEO1@LEO1>begin
dbms_rls.add_policy(
object_schema => 'leo1',
object_name => 'car',
policy_name => 'filter_num',
policy_function => 'fun_num',
sec_relevant_cols => 'num',
sec_relevant_cols_opt => dbms_rls.all_rows); 只显示相关的行信息
end;
/
2 3 4 5 6 7 8 9 10
PL/SQL procedure successfully completed.
LEO1@LEO1>select * from car;
NAME NUM COST
-------------------- ---------- ----------
toyota 30
volvo 30
honda 30
biaozhi 20
xuetielong 20
polo 20
xiali 20 10
jili 30 10
byd 40 10
9 rows selected.
小结:VPD是一种行级安全控制,操作简单无需添加任何组件即可实施。
四 演示一个OLS进行数据访问控制的示例
1.什么是OLS:Oracle Label Security 甲骨文标签安全访问控制,通过创建标签来过滤结果集,这种方式会修改表结构,会增加一列叫“标签列”又叫“伪列”,通过给不同的记录指定不同的标签,从而达到显示不同的结果集。OLS比VPD功能更强大一些,并且不是数据库默认自带的,需要独立安装。
2.Oracle Label Security的安装
Oracle 10g 安装OLS
运行Oracle程序安装文件
./runInstaller 安装组件->选择“Oracle Label Security 10.2.0.1.0”
Oracle 11g 安装OLS
11g不需安装OLS组件,已经安装好了,只需要启动就好。
Red Hat Linux
(1)[oracle@leonarding1 oracle]$ chopt enable lbac 启动OLS,写入OLS日志
Writing to /u02/app/oracle/product/11.2.0/db_1/install/enable_lbac.log...
%s_unixOSDMakePath% -f /u02/app/oracle/product/11.2.0/db_1/rdbms/lib/ins_rdbms.mk lbac_on
%s_unixOSDMakePath% -f /u02/app/oracle/product/11.2.0/db_1/rdbms/lib/ins_rdbms.mk ioracle
(2)启动dbca安装Oracle Label Security数据库对象和专属用户
[oracle@leonarding1 oracle]$ dbca
配置数据库选项,点击“下一步”
选择哪个数据库->“LEO1” 点击“下一步”
Oracle Label Security 组件上挑勾,点击“下一步”
这里就出现了不可思议的场景,Oracle Label Security是灰框框,不可打勾,如果这里是白框框那么恭喜你可以成功继续下一步了。当然没有安装上的筒子们也不要气馁,条条大路通罗马,请看下面的脚本方法。
Oracle Label Security 组件的脚本安装法
(1)我们使用Oracle自带的OLS安装脚本来部署OLS组件$ORACLE_HOME/rdbms/admin/catols.sql
[oracle@leonarding1 ~]$ sqlplus / as sysdba
SQL*Plus: Release 11.2.0.1.0 Production on Fri Jun 14 18:57:08 2013
Copyright (c) 1982, 2009, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
SYS@LEO1>@?/rdbms/admin/catols.sql
<<<<<<<<<<<<<<省略脚本执行信息>>>>>>>>>>>>>>>
请注意在创建完数据库对象后会自动关闭数据库,你需要重新启动
Database closed.
Database dismounted.
ORACLE instance shut down.
(2)检查OLS专属用户LBACSYS的状态,正常安装脚本后为OPEN,如果是LOCKED,请执行下面解锁步骤
SYS@LEO1>select username,account_status from dba_users;
。。。。。。省略无用内容。。。。。。
USERNAME ACCOUNT_STATUS
------------------------------ --------------------------------
LBACSYS OPEN
SYS OPEN
SYSTEM OPEN
OUTLN EXPIRED & LOCKED
MGMT_VIEW EXPIRED & LOCKED
33 rows selected.
解锁并设置密码,如果要是OPEN状态,可跳过这一步
alter user lbacsys account unlock;
alter user lbacsys identified by lbacsys;
小结:LBACSYS是OLS管理员用户,安装OLS之后就会自动创建,如果有锁请解锁即可使用。
(3)检查LBACSYS用户中涉及到的数据库对象信息
LBACSYS用户中不存在无效的数据库对象。
SYS@LEO1>select object_type,object_name from dba_objects where owner='LBACSYS' and status='INVALID';
no rows selected
SYS@LEO1>set pagesize 999 设置999行才有一个分界符
SYS@LEO1>select object_type,count(*) from dba_objects where owner='LBACSYS' group by object_type;
OBJECT_TYPE COUNT(*)
--------------------------------------------------
SEQUENCE 2
PROCEDURE 5
LIBRARY 10
PACKAGE 24
LOB 1
PACKAGE BODY 23
TYPE BODY 5
TRIGGER 3
FUNCTION 35
TABLE 21
INDEX 28
VIEW 57
TYPE 10
13 rows selected.
这就是Oracle Label Security所使用的数据库对象,以上我们完成了Oracle Label Security组件的安装。
(4)如何卸载Oracle Label Security组件
有安装脚本自然就会有卸载脚本,执行catnools.sql脚本就可自动卸载OLS
SYS@LEO1>@?/rdbms/admin/catnools.sql
PL/SQL procedure successfully completed. 删除存储过程
PL/SQL procedure successfully completed.
Trigger dropped. 删除触发器
Trigger dropped.
Trigger dropped.
PL/SQL procedure successfully completed.
PL/SQL procedure successfully completed.
User dropped. 最后删除用户
2 rows deleted.
Commit complete.
先删除Oracle Label Security对应的数据库对象再删除LBACSYS用户。
(5)如何使用好Oracle Label Security
创建标签策略
SYS@LEO1>alter user lbacsys identified by lbacsys; 设置密码
User altered.
SYS@LEO1>conn lbacsys/lbacsys 切换lbacsys用户
Connected.
LBACSYS@LEO1>execute sa_sysdba.create_policy(policy_name => 'ACCESS_LEO1',column_name => 'OLS_COLUMN');
BEGIN sa_sysdba.create_policy(policy_name => 'ACCESS_LEO1',column_name => 'OLS_COLUMN'); END;
*
ERROR at line 1:
ORA-00439: feature not enabled: Oracle Label Security
ORA-06512: at "LBACSYS.LBAC_SYSDBA", line 113
ORA-06512: at "LBACSYS.SA_SYSDBA", line 44
ORA-06512: at line 1
####################################################################################################
安装database vault
(1)启动chopt enable dv 服务
(2)依赖Oracle Label Security
(3)重启数据库startup force
(4)dbca创建数据库对象
启动chopt enable dv 服务
[oracle@leonarding1 ~]$ chopt enable dv
Writing to /u02/app/oracle/product/11.2.0/db_1/install/enable_dv.log...
%s_unixOSDMakePath% -f /u02/app/oracle/product/11.2.0/db_1/rdbms/lib/ins_rdbms.mk dv_on
%s_unixOSDMakePath% -f /u02/app/oracle/product/11.2.0/db_1/rdbms/lib/ins_rdbms.mk ioracle
五 演示一个通过触发器进行审计的示例。
Car表是一个非常重要的表,记录了4S店汽车的销量情况,我们要对操作这个表动作进行审计
LEO1@LEO1>select * from car;
NAME NUM COST
-------------------- ---------- ----------
toyota 10 30
volvo 50 30
honda 60 30
biaozhi 70 20
xuetielong 80 20
polo 90 20
xiali 20 10
jili 30 10
byd 40 10
9 rows selected.
创建审计表car_audit
LEO1@LEO1>create table car_audit (
name varchar2(20),
num number,
cost number,
uuser varchar2(20),
ddate date); 2 3 4 5 6
Table created.
创建审计触发器
LEO1@LEO1>create trigger trg_car_audit
after insert or delete or update on car
for each row
declare
a_name varchar2(20);
a_num number;
a_cost number;
begin
a_name :=:old.name;
a_num :=:old.num;
a_cost :=:old.cost;
insert into car_audit values(a_name,a_num,a_cost,user,sysdate);
end;
/
2 3 4 5 6 7 8 9 10 11 12 13 14
Trigger created.
删除记录
LEO1@LEO1>delete from car where num=100;
1 row deleted.
LEO1@LEO1>commit;
Commit complete.
插入记录
LEO1@LEO1>insert into car values('kia',100,50);
1 row created.
LEO1@LEO1>commit;
Commit complete.
更新记录
LEO1@LEO1>update car set num=200 where num=100;
1 row updated.
LEO1@LEO1>commit;
Commit complete.
凡是对car表进行DML操作都会触发审计触发器,并在car_audit表中留下审计记录
LEO1@LEO1>select * from car_audit;
NAME NUM COST UUSER DDATE
-------------------- ---------- ---------- -------------------- ---------
kia 100 50 LEO1 15-JUN-13
LEO1 15-JUN-13
kia 100 50 LEO1 15-JUN-13
六 分别演示对sys用户和普通用户进行审计的示例。
我们在操作数据库的时候,知道SYS用户的权限是最大的干什么事很方便,同时带来的问题就是非常危险,没有人可以束缚住。因此我们有时需要对SYS用户进行审计
SYS@LEO1>show parameter audit
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
audit_file_dest string /u02/app/oracle/admin/LEO1/adump
audit_sys_operations boolean FALSE 默认SYS用户审计是关闭的,这个参数是开启审计SYS用户所有SQL语句
audit_syslog_level string 默认是关闭的,这个参数指出SYS用户审计日志的存放位置
audit_trail string DB
SYS@LEO1>alter system set audit_sys_operations=true scope=spfile; 打开SYS用户审计
System altered.
SYS@LEO1>alter system set audit_syslog_level='user.notice' scope=spfile; 用户日志
System altered.
SYS@LEO1>startup force 重启数据库使静态参数生效
ORACLE instance started.
Total System Global Area 471830528 bytes
Fixed Size 2214456 bytes
Variable Size 285214152 bytes
Database Buffers 176160768 bytes
Redo Buffers 8241152 bytes
Database mounted.
Database opened.
SYS@LEO1>show parameter audit
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
audit_file_dest string /u02/app/oracle/admin/LEO1/adump
audit_sys_operations boolean TRUE 审计启动
audit_syslog_level string USER.NOTICE
audit_trail string DB
设置sys用户审计日志输出位置,Linux 中syslog.conf文件配置了各种类型日志的输出位置和消息源
我们只需要将Oracle日志输出配置信息添加到该文件中就可以了
[root@leonarding1 log]# vi /etc/syslog.conf
添加如下信息
# About Oracle SysLog
user.notice /var/log/oracle_dbms
添加完之后,我们还要重新加载一下配置信息,syslog.conf文件生效
[root@leonarding1 log]# ps -ef | grep syslogd
root 2385 1 0 Jun14 ? 00:00:01 syslogd -m 0
root 29740 29502 0 17:25 pts/1 00:00:00 grep syslogd
[root@leonarding1 log]# kill -HUP 2385 重新加载
Ok,操作系统的配置内容完成了。
下面我们来演示一下SYS用户的审计
SYS@LEO1>create table test as select * from dba_objects; 我们创建一个表
Table created.
SYS@LEO1>drop table test purge; 再删除一个表
Table dropped.
好了,SYS用户操作做完了,我们来看看oracle_dbms审计日志中有没有抓取到SQL语句
[root@leonarding1 log]# cat oracle_dbms
Jun 15 18:08:40 leonarding1 Oracle Audit[29903]: LENGTH : '199' ACTION :[46] 'create table test as select * from dba_objects' DATABASE USER:[1] '/' PRIVILEGE :[6] 'SYSDBA' CLIENT USER:[6] 'oracle' CLIENT TERMINAL:[5] 'pts/3' STATUS:[1] '0' DBID:[10] '1692458681'
Jun 15 18:08:49 leonarding1 Oracle Audit[29903]: LENGTH : '174' ACTION :[21] 'drop table test purge' DATABASE USER:[1] '/' PRIVILEGE :[6] 'SYSDBA' CLIENT USER:[6] 'oracle' CLIENT TERMINAL:[5] 'pts/3' STATUS:[1] '0' DBID:[10] '1692458681'
Good 创建表test和删除表test的命令都抓取到了,例如 startup shutdown connect等操作都是可以抓取到的。
小结:通过上面的测试实例,我们了解到了对数据库管理员的审计也逐渐成为信息安全中的重要一项,这样可以对管理员人员进行监督,权限限制,提高数据库安全级别,完善安全管理制度。这里提及一个问题,为什么SYS用户的操作记录需要记录在操作系统文件中呢,这里就有一个渊源了,由于SYS用户本身权力就大,大到可以把自己的操作记录都可以删除,因此为了节制SYS用户,就把记录操作的日志放在了操作系统下面,还不是普通用户可以访问的,必须是操作系统管理员才能查看,这下同学们应该知道原委了吧。
普通用户审计的示例
我们既可以对SYS用户进行审计,那么在平时的时候更多的是对普通用户的审计,对普通用户的审计就没有这么严格了,它的审计记录是可以放在数据库基表sys.aud$中的,我们可以在数据库层面上进行查看。
标准审计内容
(1)审计会话
(2)审计对象
(3)审计操作
(4)审计授权
实验
SYS@LEO1>show user
USER is "SYS"
SYS@LEO1>alter system set audit_trail=db,extended scope=spfile; 启动审计追逐数据库功能
System altered.
SYS@LEO1>startup force; 重启数据库使静态参数生效
ORACLE instance started.
Total System Global Area 471830528 bytes
Fixed Size 2214456 bytes
Variable Size 285214152 bytes
Database Buffers 176160768 bytes
Redo Buffers 8241152 bytes
Database mounted.
Database opened.
我们计划对leo1用户的car表进行审计
SYS@LEO1>audit select,insert,update,delete on leo1.car;
Audit succeeded.
指定审计对象和审计动作,对select,insert,update,delete这四个操作Oracle都会进行审计。
插入记录
LEO1@LEO1> insert into leo1.car values('mini',150,150);
1 row created.
LEO1@LEO1>commit;
Commit complete.
LEO1@LEO1> select * from car;
。。。。。。省略。。。。。。
LEO1@LEO1>select userid,obj$name,sqltext from sys.aud$;
USERID OBJ$NAME SQLTEXT
--------------------------------------------------------------------------------------------------------------------------------
LEO1 CAR select * from car
LEO1 CAR insert into leo1.car values('mini',150,150)
VPD OLS db vault audit sys用户
刘盛Leonarding
2013.6.16
北京&summer
分享技术~成就梦想
Blog:www.leonarding.com
##########################################################################################
如果喜欢我的文章就请扫下面二维码吧!关注微信号:leonarding_public
在这里你能得到技术、实事、热点消息等新兴事物的思考和观点,别的地方可能没有的东西。我将为大家提供最新技术与资讯动态,传递正能量。