Listener Password in Oracle 10g

在Google上搜索“监听 安全 oracle”,一堆《实例讲解Oracle监听口令及监听器安全》的文章,都是copy+paste自eygle的这篇《Oracle的监听口令及监听器安全》,eygle的测试环境是本地的10.2.0.3客户端加远程9.2.0.4数据库。

如果服务器端数据库版本在Oracle9i以后,设置监听密码的情况则有一些变化。

Metalink Note 260986.1中,可以看到:

In Oracle 10, the TNSListener is secure out of the box and there should not be a need to set a listener password as in older versions of the Oracle listener.

Oracle10g以后,设置Listener密码已经不是安全检查的必要条件了,因为默认在10g里面除了启动监听的用户之外,其它用户都无法停止Listener(还有另外一些lsnrctl的命令也同样被禁止了,比如trace, reload等),即使Listener没有设置密码。

在默认情况下,启动Listener或者使用lsnrctl status命令查看监听状态,可以看到:

Security                  ON: Password or Local OS Authentication

这表明Listener的安全机制使用了Password方式或者Local OS Authentication方式,在这种状态下,即使是设置了监听密码,对于启动监听的user来说,也仍然是不需要任何密码就可以停止监听的。

如果我们想去除自Oracle10g之后的这种新安全机制,那么需要在listener.ora文件中添加:

LOCAL_OS_AUTHENTICATION_[listener name] = OFF

重新启动Listener之后,将会只看到:

Security                  ON: Password

这就又回复到了Oracle9i时的状态,只要有密码存在,无论是谁尝试停止监听都会被要求set password。

D:\Temp>lsnrctl

LSNRCTL for 32-bit Windows: Version 11.1.0.7.0 - Production on 20-MAY-2009 11:15:41

Copyright (c) 1991, 2008, Oracle.  All rights reserved.

Welcome to LSNRCTL, type "help" for information.

LSNRCTL> status
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=kamus-laptop)(PORT=1521)))
TNS-01169: The listener has not recognized the password
LSNRCTL> stop
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=kamus-laptop)(PORT=1521)))
TNS-01169: The listener has not recognized the password
LSNRCTL> set password
Password:
The command completed successfully
LSNRCTL> status
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=kamus-laptop)(PORT=1521)))
STATUS of the LISTENER
------------------------
Alias                     LISTENER
Version                   TNSLSNR for 32-bit Windows: Version 11.1.0.7.0 - Production
Start Date                20-MAY-2009 11:14:22
Uptime                    0 days 0 hr. 1 min. 34 sec
Trace Level               off
Security                  ON: Password
SNMP                      OFF
Listener Parameter File   D:\oracle\product\11.1.0\db_1\network\admin\listener.ora
Listener Log File         d:\oracle\diag\tnslsnr\kamus-laptop\listener\alert\log.xml
Listening Endpoints Summary...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=kamus-laptop)(PORT=1521)))
Services Summary...
Service "orcl11g" has 1 instance(s).
  Instance "orcl11g", status READY, has 1 handler(s) for this service...
Service "orcl11g_XPT" has 1 instance(s).
  Instance "orcl11g", status READY, has 1 handler(s) for this service...
The command completed successfully
LSNRCTL> stop
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=kamus-laptop)(PORT=1521)))
The command completed successfully
LSNRCTL>

How to Prevent DBA User From Logining Database Without Password

我们知道如果某个操作系统用户属于dba组,那么登录了这个用户之后,不再需要任何密码就能以SYS用户登录到数据库中,在产品环境中,这无疑是一个严重的安全漏洞。

kamus@desktop:~$ whoami
kamus
kamus@desktop:~$ sqlplus / as sysdba

SQL*Plus: Release 11.1.0.6.0 - Production on Sun Apr 5 17:56:58 2009

Copyright (c) 1982, 2007, Oracle.  All rights reserved.

Connected to an idle instance.

SQL> show user
USER is "SYS"
SQL> exit
Disconnected
kamus@desktop:~$ sqlplus nouser/nopassword as sysdba

SQL*Plus: Release 11.1.0.6.0 - Production on Sun Apr 5 17:37:42 2009

Copyright (c) 1982, 2007, Oracle.  All rights reserved.

Connected to an idle instance.

SQL> show user
USER is "SYS"
SQL>  

正如上面的演示,我们轻松以SYS身份登录进了数据库,无须给任何用户名密码,甚至是随便给一个毫不存在的用户和密码也可以。

如何防止这样的问题?

首先,我们可以利用oracle自身提供的sqlnet.ora文件中的参数sqlnet.authentication_services。在$ORACLE_HOME/network/admin/sqlnet.ora文件中添加如下行:
sqlnet.authentication_services=(NONE)

再次尝试不提供用户密码登录sqlplus,将遇到ORA-01031错误。

kamus@desktop:~$ sqlplus / as sysdba

SQL*Plus: Release 11.1.0.6.0 - Production on Sun Apr 5 18:05:07 2009

Copyright (c) 1982, 2007, Oracle.  All rights reserved.

ERROR:
ORA-01031: insufficient privileges


Enter user-name: ^C
kamus@desktop:~$ sqlplus sys/oracle as sysdba

SQL*Plus: Release 11.1.0.6.0 - Production on Sun Apr 5 18:06:31 2009

Copyright (c) 1982, 2007, Oracle.  All rights reserved.

Connected to an idle instance.

SQL> 

更进一步,我们还可以让dba组的其他用户必须通过监听程序来连接数据库,这样内置于监听中的审计和跟踪功能就能得到更好的使用。

先来看一下如果不通过监听连接数据库的情况。继续上面的例子,在我们通过用户名密码成功登录数据库实例以后,查看一下操作系统级别的进程。

kamus@desktop:~$ ps -ef|grep sqlplus
kamus     6556  5409  0 18:06 pts/0    00:00:00 sqlplus            as sysdba
kamus     6561  5601  0 18:11 pts/2    00:00:00 grep sqlplus
kamus@desktop:~$ ps -ef|grep 6556 | grep -v grep
kamus     6556  5409  0 18:06 pts/0    00:00:00 sqlplus            as sysdba
oracle    6557  6556  0 18:06 ?        00:00:00 oracleorcl11g (DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq)))

pid为6556的进程是user process,对应其的server process的pid是6557,这就是oracle使用的双层架构(Two-Task Architecture),任何用户进程(user process)不会跟数据库内存或者数据文件直接交互,而是通过一个对应的服务端进程(server process)来完成工作的。

我们可以注意到,6556进程的属主是kamus,因为是这个用户执行的sqlplus命令,但是6557进程的属主却是oracle,这是为什么呢?这归功于setuid。查看一下oracle可执行文件的权限。

kamus@desktop:~$ cd $ORACLE_HOME/bin
kamus@desktop:/u01/app/oracle/product/11.1.0/bin$ ls -l oracle
-rwsr-s--x 1 oracle oinstall 144792107 2009-01-05 14:01 oracle

owner的权限是rws,最后的s位表明在该执行文件上启用了setuid,具体含义就是不管是那个用户执行了该文件,该文件总是以属主的身份运行。那么如果我们取消掉s位,会出现什么情况呢?

kamus@desktop:/u01/app/oracle/product/11.1.0/network/admin$ cd
kamus@desktop:~$ su - oracle
Password: 
[orcl11g]@desktop[/home/oracle]$cd $ORACLE_HOME/bin
[orcl11g]@desktop[/u01/app/oracle/product/11.1.0/bin]$chmod u-s oracle
[orcl11g]@desktop[/u01/app/oracle/product/11.1.0/bin]$ls -l oracle
-rwxr-s--x 1 oracle oinstall 144792107 2009-01-05 14:01 oracle

再次尝试在kamus用户下登录sqlplus。碰到了ORA-09925错误。

kamus@desktop:~$ sqlplus sys/oracle as sysdba

SQL*Plus: Release 11.1.0.6.0 - Production on Sun Apr 5 18:26:16 2009

Copyright (c) 1982, 2007, Oracle.  All rights reserved.

ERROR:
ORA-09925: Unable to create audit trail file


Enter user-name: 

再检查一下后台进程。

kamus@desktop:~$ ps -ef|grep sqlplus|grep -v grep
kamus     6699  5601  0 18:26 pts/2    00:00:00 sqlplus            as sysdba
kamus@desktop:~$ ps -ef|grep 6699|grep -v grep
kamus     6699  5601  0 18:26 pts/2    00:00:00 sqlplus            as sysdba
kamus     6700  6699  0 18:26 ?        00:00:00 oracleorcl11g (DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq)))

原因很清楚,当我们去掉了oracle可执行文件的s位以后,server process的属主成为了kamus,而不是之前的oracle。登录sqlplus需要记录一定的audit信息,这是由server process来完成的,但是因为现在属主是kamus,并没有权限在oracle软件的安装目录中写入任何信息,因此报ORA-09925错误。

更彻底一些,我们连server process都不允许在本地启动,去掉oracle可执行文件的其他用户执行权限,只保留属主的读写执行权限。

[orcl11g]@desktop[/u01/app/oracle/product/11.1.0/bin]$chmod 0700 oracle
[orcl11g]@desktop[/u01/app/oracle/product/11.1.0/bin]$ls -l oracle
-rwx------ 1 oracle oinstall 144792107 2009-01-05 14:01 oracle

再次尝试登录sqlplus,这次碰到了ORA-12546错误。

kamus@desktop:~$ sqlplus sys/oracle as sysdba

SQL*Plus: Release 11.1.0.6.0 - Production on Sun Apr 5 18:44:14 2009

Copyright (c) 1982, 2007, Oracle.  All rights reserved.

ERROR:
ORA-12546: TNS:permission denied


Enter user-name: 

检查后台进程,可以看到根本就没有启动成功的server process。

kamus@desktop:~$ ps -ef|grep sqlplus|grep -v grep
kamus     6916  5601  0 18:44 pts/2    00:00:00 sqlplus            as sysdba
kamus     6917  6916  0 18:44 ?        00:00:00 [sqlplus] 

在这种设置下,必须要通过监听才可以登录数据库。

首先,使用oracle用户登陆,启动数据库。取消掉oracle可执行文件的s位后,必须要登陆到该文件的属主用户下,才可以启动数据库。

[orcl11g]@desktop[/home/oracle]$sqlplus sys/oracle as sysdba

SQL*Plus: Release 11.1.0.6.0 - Production on Sun Apr 5 18:56:23 2009

Copyright (c) 1982, 2007, Oracle.  All rights reserved.

Connected to an idle instance.

SQL> startup
ORACLE instance started.

Total System Global Area  238530560 bytes
Fixed Size                  1299116 bytes
Variable Size             100666708 bytes
Database Buffers          134217728 bytes
Redo Buffers                2347008 bytes
Database mounted.
Database opened.
SQL> 

然后再登陆kamus用户,尝试登陆sqlplus。orcl11g是在tnsnames.ora文件中已经设置过的连接字串。

[orcl11g]@desktop[/home/kamus]$sqlplus sys/oracle@orcl11g as sysdba

SQL*Plus: Release 11.1.0.6.0 - Production on Sun Apr 5 18:57:16 2009

Copyright (c) 1982, 2007, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 - Production
With the Partitioning and Real Application Testing options

SQL> 

通过监听,可以正常连接数据库了。再检查一下后台进程的情况。

[orcl11g]@desktop[/home/kamus]$ps -ef|grep sqlplus|grep -v grep
oracle    7077  6966  0 18:56 pts/3    00:00:00 sqlplus            as sysdba
kamus     7156  7008  0 18:57 pts/5    00:00:00 sqlplus                    as sysdba
[orcl11g]@desktop[/home/kamus]$ps -ef|grep LOCAL|grep -v grep
oracle    7118  7077  1 18:56 ?        00:00:02 oracleorcl11g (DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq)))
oracle    7172     1  0 18:57 ?        00:00:00 oracleorcl11g (LOCAL=NO) 

7077进程是我们使用oracle用户打开的sqlplus连接,对应的server process是7118,7156进程则是使用kamus用户打开的sqlplus连接,可以看到并没有父进程是7156的server process,只有一个7172的进程,它的父进程号是1。

[orcl11g]@desktop[/home/kamus]$ps -fp 1
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 17:10 ?        00:00:01 /sbin/init 

1是初始化进程,父进程为1代表这个进程是被fork出来的,这就是通过监听连接数据库的机制,user process联系监听,监听再fork一个server process用以应对客户端的请求。

至此,我们已经完成了对于数据库连接的基本安全性设置。

结论:通过下面的两种方法来完成数据库连接的安全保障。
1. 在sqlnet.ora文件中添加sqlnet.authentication_services=(NONE),用以保证必须要给出SYS用户密码才能登陆。
2. 设置oracle可执行文件的运行权限为0700,用以保证非oracle软件的属主必须要通过监听才可以连接数据库。

安全,并不仅仅是局限于数据库本身的,在本文的安全性设置中,它牵涉到数据库运行的机制以及操作系统的部分知识,当你的知识越全面,你就能想到越多的方法来完善整个系统的安全。当然,安全性的建设也远远不局限于技术层面,规章制度、人员素质、完善的审计流程都具有决定性的影响。

User Default Password Check in Oracle 11g

在数据库安全性检查中有一项首先要完成的工作,就是检查数据库中的用户密码是否还仍然保留着默认值,比如sys的密码是否还是change_on_install,system的密码是否还是manager,scott的密码是否还是tiger。

在Oracle 11g之前,我们需要手工来完成这样的工作,大概步骤是:
1. 创建一张自定义的表,保存下常用的系统用户以及默认密码的HASH值。
2. 将系统中的用户密码HASH值与该表中的HASH值比较,如果相同,则表明还在使用默认值。

注意:在数据字典中存储的密码是被HASH算法加密过的,加密后的值不但跟密码本身有关还跟用户名有关,也就是,如果是不相同的用户名那么即使是完全相同的密码,加密后的HASH值也是不一样的。这样保证了每一个用户的每一个密码都有自己独一无二的HASH值。

在Oracle 11g之前,加密后的密码可以从DBA_USERS数据字典的PASSWORD字段中获得,因此可以通过这个字段中存储的值来做是否是默认值的检查。但是在11g中,PASSWORD字段却不再显示密码的内容了。

先看一下文档中对这个字段的描述:

Indicates whether the user is authenticated by OID (GLOBAL) or externally authenticated (EXTERNAL); NULL otherwise

SQL> select username,decode(password,null,'NULL',password) password from dba_users;
 
USERNAME                       PASSWORD
------------------------------ ------------------------------
MGMT_VIEW                      NULL
SYS                            NULL
SYSTEM                         NULL
DBSNMP                         NULL
SNPM                           NULL
SYSMAN                         NULL
SNPW                           NULL
SCOTT                          NULL
KAMUS                          NULL
OUTLN                          NULL
WMSYS                          NULL
DIP                            NULL
ORACLE_OCM                     NULL
TSMSYS                         NULL
 
14 rows selected

可以看到PASSWORD字段已经不再显示密码内容,全部都为空。

那么,如果再去检查这些用户是否还在使用默认的密码呢?

方法一:从SYS.USER$基表中检查,在基表的password字段中仍然可以查到HASH后的值。

SQL>  select name,password from user$ where name='SCOTT';

NAME                           PASSWORD
------------------------------ ------------------------------
SCOTT                          F894844C34402B67

方法二:这是推荐的方法,最简单的方法,11g中可以使用的方法,11g提供了新的DBA_USERS_WITH_DEFPWD视图,该视图中包含了所有还在使用默认密码的用户名。

SQL> alter user scott identified by tiger;

User altered.

SQL> select * from DBA_USERS_WITH_DEFPWD where username='SCOTT';

USERNAME
------------------------------
SCOTT

SQL> alter user scott identified by tiger1;

User altered.

SQL> select * from DBA_USERS_WITH_DEFPWD where username='SCOTT';

no rows selected

Oracle对于安全性的支持力求做到业界领先,Oracle始终在每个细节上进步着。

Oracle Maximum Security Architecture

Oracle 最大安全性架构

很多人应该知道在基于Oracle数据库的系统实施过程中,有一种高可用性的解决方案,称为MAA(Maximum Availability Architecture),通过RAC和Dataguard等一系列技术和选件搭建一个可以获得最大高可用性的IT环境。

MAA保证了IT系统能够被持续使用,而与此同时,另外一个需求就诞生了,系统不但需要能够持续使用,而且还需要能够安全使用。安全,同样也是IT系统能够符合行业标准的前提条件。面对安全需求,Oracle提出了MSA架构,也就是Maximum Security Architecture,最大安全性架构。

IT系统在哪些方面具有安全性需求呢?
1. 用户管理
应用系统需要有正常的用户登陆以及用户验证,具有权限的用户在自身管理方面是需要注意安全的,以防止被其它人员非法获取登陆或者查看数据的权限。

2. 存取控制
在应用系统中不同的用户应该具有不同的权限,不同权限的用户可以登陆的范围或者查看数据的多少也是不同的。这是上面一步的延展,不同的用户通过安全的机制登陆进系统了,同样需要有另外一种安全机制来控制不同的用户存取不同的数据。

3. 数据加密以及数据遮盖
进一步延展,不同的用户安全登陆系统,并且已经各自安全的查看自己的数据了,那么数据本身是否安全呢?这就需要数据加密或者数据遮盖技术来完成。

4. 监控
这个体系并不仅仅是监控报表,因为那只是事后的工作,也许一个违规的操作出现几天以后,安全报表中才出现记录,哪怕仅仅是几个小时,实际上违规的操作已然发生,产生的危害也许已经是无法挽回的了。因此对于整个应用系统的安全流程,必须要有一个完善的监控体系来实时地给予监控,在违规操作发生的当时就立即予以报警。

那么Oracle提出的MSA架构是如何在各个方面提供相应的技术以及产品呢?同样以上述的四个方面分别阐述。

1. 用户控制
1.1 单一登录
管理多个账户以完成相关的工作任务将导致安全性的薄弱环节和高额的所有权成本。一般地,为完成每天的日常工作,一个员工要管理十四个密码或账户。为了应付“密码过多”的问题,员工可能会把密码抄写下来,或选择一个容易猜中的密码。人们经常忘记密码,并频繁地向帮助部门查询。系统管理员甚至面临者一个更大的问题。系统管理员需要花费大量的时间去管理分布于各种数据库,web服务器和网络上的这些账户。如果一个雇员离开了公司,而系统管理员没有注意删除所有的账户,一些老的账号可能就仍然处于激活状态,这无疑埋下了很大的安全隐患。


单一登录原理图

这个问题的解决方案就是单一登录。单一登录可以使用户通过一个单一的登录过程就能访问所用被授权的应用。如果只管理一个密码或证明书,用户一般就不会把它记录下来,或选择一个不容易被猜中的密码。每个企业都应该有使雇员强制性选择安全密码的安全性策略。认证证书可以集中存储于一个LDAP目录,因此系统管理员可以在一个单独的地方管理这些账户。账户的集中化可以使系统管理员能更迅速地完成追加,删除和修正账户的工作。Oracle通过单点登陆服务套件(Enterprise Single Sign-On suite)集成Oracle互联网目录LDAP提供了单一认证。Oracle也可以与其他第三方单一登录服务器的集成,如Kerberos 和 Netegrity。

1.2 超强认证
通过互联网你可能看不到正在与谁做生意,所以在数字世界中存在着一种可以让系统识别身份的机制。用户名和密码的组合是一个系统认证和识别用户的最普遍或最基本的方式。一些企业认为,这种基础的,单向的认证方式并不十分安全,特别是当用户需要管理几个密码时更是如此。另一种方式,或者是认证的更安全的方式是所谓的超强认证。我们可以给出几个超强认证的例子,如X.509数字证书,证明卡和生物认证设备。Oracle 通过身份管理(COREid)结合第三方全面支持基本认证和多种超强认证。比如支持以下具有工业标准的高级认证方式:
Kerberos
RADIUS (Remote Authentication Dial-In User Service)
Secure Sockets Layer
PKI

2. 存取控制
2.1 精细的访问控制
互联网和在线服务目前已要求服务器能够实现精细的访问控制。如果您考虑数据库服务器将管理互联网上多团体用户的数据,数据库必须保证用户只能访问与它相关的数据,而不涉及其他的数据。例如,在线银行业务服务需要保证客户所访问的账户信息只能是他们自己的,而不能看到其他客户的信息。
能够控制对敏感信息的访问对需要满足隐私性需求的应用也由帮助。例如,医疗应用软件必须保证医生只能看到他们自己病人的记录。
因为数据库在传统上是在表的级别上分配权限,而不会控制在单独的记录或更低的级别,附加的应用代码可能被要求取得更精细的访问控制。传统方法的问题是如果用户利用应用之外的方式,如特别的查询工具等访问数据库,就可以绕过安全性设置。而且,维护复杂的访问控制代码会导致高额的开发和管理成本。


Oracle10g数据库的标签安全保护最敏感数据

Oracle10g数据库的标签安全性组件(Label Security)是一个精细访问控制或行级别安全性的无限的解决方案。建立在Oracle虚拟个人数据库的工具包基础上的Oracle标签安全性向数据行中追加了一个特别的标记(标签),可以达到行级别的安全性。例如,在线服务可以使用一个订阅标签,它可以将存储于相同数据库服务器中的各企业的数据更安全有效的分离开。
简单的Label Security设置方法参看我的这篇文章 – 利用OLS实现行级安全性 Step By Step

2.2内部控制
企业IT系统的内部安全管理的需求来源于传统的管理用户的模糊定义,尤其是某些特权用户的定义(比如DBA等),原先只是希望他们管理数据库表结构或本部门的数据,但由于其传统的定义使这类用户可以访问所有的应用数据,甚至敏感数据(如企业HR部门的员工工资和个人信息,Finance部门的重要业务数据等);同时,随着企业系统的发展,信息整合带来不可避免的数据库合并,大量的子系统的特权用户的访问权限被简单地扩展到了所有系统。

Oracle Database Vault正是为解决上面这些敏感的安全问题而诞生的, Oracle Databse 10g R2 企业版的新增安全选件,Database Vault安全选件可以控制什么人,在什么时间,在什么地点或是什么样的应用程序来访问,保护我们的业务避免来自于内部的用户恶意的攻击。对职责进行严格分离,甚至在我们的系统管理员中,Oracle Database Vault选件额外增加强大的可预见性的控制功能帮助企业或公司满足今天严格法规和敏感的需求。Vault是目前业内最早的相关安全的产品,引入了几个新的强大的安全特性(Realms领域、Factor代理、Rule规则等)来限制对数据库的访问,即便是一些超级用户或特权也是如此。这些特点可应用于一个灵活的,易于定制的样式去增强我们的授权需要,而不需对客户已存在的应用做任何修改。

3. 数据加密以及数据遮盖
3.1 加密系统
通过互联网从事商务活动需要通过网络传输信息。任何人,不论是黑客,解密高手还是不诚实的雇员,都可以下载一个信息包的嗅探器,当信用卡等这类敏感信息在网络中传输时,利用嗅探器可以捕获它们。不怀好意的用户也可以利用一些途径获得对存储于服务器中的数据的非法访问。为了防止对数据的非法访问,可以采用加密系统,利用信息的不规则性保护数据。它涉及数学的计算方法和密钥。公共密钥的基础结构是最普遍采用的方法。它为加密,数据整合,数字认证和数字签名提供了技术。


Oracle10g数据库的高级安全性组件保证网络传输数据安全

当数据在网络中的所有层,包括用户层,中间层和数据库层传输时,Oracle提供了网络中端到端的加密。Oracle应用服务器提供了网络中用户层和中间层的加密。Oracle数据库的高级安全性组件(Advanced Security)提供了网络中中间层和数据库层的加密。为了强化性能,Oracle通过Oracle与RSA的BSAFE库的集成,支持BHAPI的接口。Oracle也对存储于数据库内部的数据提供加密。对于非常敏感信息如信用卡号的加密,如果有对数据非法访问的企图或摆脱数据库控制的企图,如通过操作系统,可在数据库中追加一个额外的保护层。

3.2 备份安全
为了信息的延续性,信息保存的时间要求越来越长,因此备份数据的安全也受到了很大的挑战,一方面,企业使用大量的备份介质来备份数据;一方面,企业不断地从备份数据中恢复以便使用;同时,企业会对大量的备份筛选,淘汰过时的备份,这些复杂的数据备份管理过程中,信息的安全问题也日益突出。

如果企业选择将备份数据保存在磁盘中,那么TDE(Transparent Data Encryption)是应该首选考虑的,TDE可以在包含敏感数据的列,表,表空间上进行加密,加密之后的数据备份到磁盘上,备份文件中的信息也同样是加密的,这样即使备份文件意外丢失,也几乎没有可能通过恢复或者直接扫描裸文件的方法从备份文件中获得敏感数据。

在云计算十分受到追捧的今天,将自己的备份数据存储在第三方提供的云计算存储(比如Amazon S3)中,如何才能放心,如何才能保证其中的敏感数据不被剽窃,TDE无疑是理想的选择。

如果企业选择直接将数据备份到磁带中,那么Oracle Secure Backup提供方便、安全可靠的磁带备份解决方案。

为了更好地管理备份数据的安全,Oracle通过10g 之后版本中诞生的最新选件Secure Backup来很好地管理与控制备份介质尤其是磁带备份的安全问题。Secure Backup为数据库备份提供了中央磁带备份管理平台,简化了Oracle数据库与文件系统的备份管理。数据就是企业的生命力,必须被妥善保管并保护,保持在服务器激活的状态过程中不被恶意访问。数据中心的安全策略是保护物理接入服务器、数据、公司网络的关键。当数据保存至磁带,Oracle Secure Backup 将与安全策略平行工作,它提供了安全的Inter-Domain数据交换与控制消息机制,限制授权用户对备份数据的管理并通过RMAN将数据加密写入至备份磁带。

借助于成熟的Secure Socket Layer (SSL) 技术,集成Oracle Advanced Security 选件,Oracle Secure Backup可以实现双向服务器授权、加密备份恢复控制消息、网络传输过程数据加密,从而保证数据备份传输过程中的安全。

数据库备份可以通过RMAN进行加密,然后由Oracle Secure Backup完成对磁带的加密格式写入。这种集成式的加密方案保证了数据在离开数据库之后的安全。RMAN加密备份的解密是在恢复操作或重载时自动完成的,任何需要的时候密钥都是可用的,用户可以任意选用密码或Oracle Encryption Wallet。

Oracle Secure Backup提供了基于密码和关联用户权限的用户层访问控制以避免备份数据被未授权用户所访问。每个配置用户必须被注册拥有指定的系列权限,可以在域内设置执行任何数据保护操作。通过组合内部预置的18种特殊的备份及恢复权力,备份者可以高度精确的控制用户对域内的访问行为。通过选择预定义的5类对用户接入域时对各角度“读”或“写”的安全控制类,同时用户也可以定义自己的安全控制类来满足用户环境内的安全需求。一个客户只能被赋予一种安全类但是一个安全类可以拥有多个用户。

4. 监控
4.1 精细审核
审核是普遍使用的最有效的安全性机制,它可以保证系统的合法用户能完成他们应该从事的工作,同时又可以限制他们对权限的滥用。通过审核,企业可以跟踪用户的活动,从而发现安全性的漏洞。而且,用户如果知道他们正受到跟踪,他们也不愿意滥用他们的权限。因为传统的审核将产生极大量的数据,因此也很难发现有用的信息,Oracle10g强化了精细审核(FGA)。利用精细的扩展审核,安全性漏洞将会非常容易被发现。例如,如果建立了一个审核策略用于重复性筛选信用卡号,就会自动生成一个警告,警告系统管理员可能的入侵。系统管理员可根据这些警告做出响应,如终止非法数据库的对话。

4.2 Audit Vault
如果说Oracle Database Vault是完善了对于数据库SYSDBA的权限控制,那么Oracle Audit Vault则是对于企业内部违规者的进一步预防和监控。

目前最新版本的OAV 10.2.3.1不但支持Oracle的数据库产品(Oracle Database 9i到10gR2的所有数据库版本),同时也提供了对于Microsoft SQL Server 2000/2005. IBM DB2 UDB 8.2/9.5, 以及 Sybase ASE 12.5/15.0等主流关系型数据库的支持,自动获捕获,存储,分析审计数据,用户已经能够通过单一的审计解决方案来完成对企业内各种数据库活动的审计工作。

对于Oracle数据库而言,OAV的元数据可以是数据库redo日志,数据库Audit日志以及操作系统Audit日志(其它类型的数据库会有所不同),这些元数据被Audit Agent通过预先制定的捕获规则抓取到Audit Server中,而Audit Server端则提供了多样的报表查询,并且根据预先定义的企业策略提供违规操作告警功能。

Oracle Audit Vault帮助机构实施“信任但是验证”原则。Oracle Audit Vault帮助企业简化合规报告,及早检测到威胁,同时以透明的方式收集并将审计数据整合到企业级的审计整合管理解决方案中;整合并保护从Oracle数据库采集的审计数据;通过简化IT安全官员和内部审计员的工作,大幅度降低企业合规性的成本;使用户拥有最大灵活性的同时,有效监控他们的活动以确保这些行为符合企业的制度。

结论
MSA架构体现了Oracle的深度防御理念(Defense-in-Depth),在网络层,存储层,人员层都提供了完善的防护,同时在监控方面又体现了Proactive的2.0理念,实时并且全方位的给予安全监控。

世上没有安全性的魔术子弹,但Oracle始终站在产品安全性以及客户的系统安全性背后。

Oracle提出:

因为我们自己的企业也是运行在Oracle之上,我们也是提供坚不可摧软件的既得利益者。坚不可摧建立在我们具有20年为世界上最具安全性意识的客户建立系统的实力和经验的基础上,这些客户中包括情报部门和国防部,也建立在由十九个独立的安全性评估所提供的保障基础上。(我们最强劲的竞争对手只分别具有零个或一个评估。他们为什么不在安全产品的生命周期和可证明的安全软件上进行投资呢?)

坚不可摧的软件是一个长期的承诺,它已经在实施过程中,它将被扩展到对每个Oracle产品的相同的开发方法和保障评定中。今天,所有强烈关注安全性的客户都会考虑把他们的数据库运行在Oracle上。

获取更多MSA架构信息,请参看官方网站

让我们的数据更安全

很早之前,在做税务行业数据库架构整体方案的时候,曾经建议过将多个数据库实例整合到一个RAC数据库中时,客户提出过一个疑问,数据都放在一个数据库里面,安全性怎么保证?物理隔离才安全。

那时候,我的回答是,物理隔离就安全了?数据库的安全绝对不仅仅是是否能够从这台机器登陆到数据库服务器上,那只是一个前端的考虑点而已,在数据传输的每个阶段,都需要考虑安全性,都需要制定跟企业特点相符合的安全策略,而Oracle数据库在即使是非物理隔离的多个数据库实例上,也同样具备多种安全保护措施。

这里,并不过多地探讨到底Oracle数据库提供了多少Security的解决方案,只是想说,现在的企业在考虑安全性上,更多地是在想如何从外部防范入侵,大多数都忽略了内部的问题,中国有句古话 – 千里之堤毁于蚁穴,其实,内部的毁坏可能才是最致命的。

曾经被朋友请去给某个公安机关的数据库做恢复工作,数据的备份是每天的export文件,且不说这样的备份是否合理,单单就安全性考虑,至少在我帮助恢复和最后检查数据完整性的时候,我可以看到居民们的姓名、身份证号码,甚至,如果当时我愿意copy一份dmp文件拿走的话,也恐怕没有人知道。

再看看我曾经服务过的单位,都或多或少存在这样的安全隐患。

仍然回到我比较熟悉的税务行业,诚然,税务行业的数据保密级别跟银行相比,要低不少,但是以其中的“防伪税控”系统为例,其中存放着企业增值税的信息,并且系统的复杂程度跟税务行业的其它应用相比要简单不少,表的数量不过百张,表结构也相对简单,直接通过查看表中的数据基本上可以获得需要的信息。而“稽核协查”系统的数据又基本上全部由“防伪税控”系统中复制而来,这其中包含着可能会存在的企业违规操作信息。

国税有着企业的纳税情况;地税有着个人的纳税额;银行有着个人的贷款情况、信用卡消费情况;移动,网通,医院,网监,只要有数据库的地方,就有着安全的需求,以上任何一个企事业单位,如果数据泄漏了,恐怕都是一件天大的事情。

数据库的安全建设,现在在国内还仅仅处于一个起步的阶段,在我见过的大多数数据库中,都或多或少存在着安全问题,无论是安装了多少防火墙,无论是安装了多厚的铁门,铁门前面站了多少警卫,进门之前需要签多少字,中控室里安装了多少摄像头,只要有合适的理由登陆进数据库中,一切防范措施似乎都形同虚设了。让跟业务无关的技术人员能够直接面对最终的数据,仅仅这一点就足够让人后脊梁冒冷汗的。

实际上,对于企业数据安全性的要求,现在已经不仅仅是企业内部的需求了,随着美国萨班斯法案(Sarbanes-Oxley)、美国HIPAA法案(Health Insurance Portability and Accountability Act)、日本个人信息保护法案、欧盟隐私和电子通信指令等法规和隐私保护指令的不断出台,中国也开始制定了《企业内部控制基本规范》,该法规被称为中国版的萨班斯法案,在2008年6月28日发布,在规范内最后一条明确指出“本规范自2009年7月1日起实施”,实施范围限定为上市公司,同时也鼓励在非上市的其它大中型企业内实行。

看一下上面提到的几个问题,再看一下Oracle数据库中是否有相应的解决方法。

1. 如何让数据库管理员看不到业务数据?

Oracle Database Vault,Oracle数据库企业版的一个增值选件。它主要是用于管理单个数据库的安全性方面的,当然它也适用于Oracle的RAC环境。在Oracle Database Vault 引入了两个新概念,第一就是领域的概念,也就是说我们可以把数据库的对象组成一个领域,例如说多个表,整个应用或者多个应用,而Database Vault 管理员可以把要进行安全保护的数据库对象放到领域中。第二个概念是规则集合的概念,Database Vault 管理员可以创建一个包含几乎所有DDL和DML操作的语句的集合,然后加上相应的规则,比如说时间,IP地址之类,就能够限制用户对于特定数据的访问权限,而这个是可以应用到所有的用户上的,包括Oracle数据库里面的超级用户sys和system。
有了Oracle Database Vault ,我们需要培养的是一个负责制定公司安全策略的并且会点击鼠标的家伙,通过OEM中的图形化界面,制定不同的数据库领域,要知道监控一个人要比监控一堆DBA简单的多。

From Drop Box

2. 如何让数据库系统的审计符合法律规定?

Oracle Audit Valut,一种新的安全产品,它使审计收集和分析流程自动化,将审计数据变为关键的安全资源,从而帮助应对如今围绕合规性和内部威胁方面的重要业务挑战。Oracle Audit Vault帮助机构实施“信任但是验证”原则。Oracle Audit Vault帮助企业简化合规报告,及早检测到威胁,同时以透明的方式收集并将审计数据整合到企业级的审计整合管理解决方案中;整合并保护从Oracle数据库采集的审计数据;通过简化IT安全官员和内部审计员的工作,大幅度降低企业合规性的成本;使用户拥有最大灵活性的同时,有效监控他们的活动以确保这些行为符合企业的制度。

From Drop Box

3. 如何让EXP出来的文件即使被拿走了,也无法构成威胁?

很遗憾,目前为止还没有这样的防范措施。
我们可以实施TDE(Transparent Data Encryption),但是TDE目前还不支持旧的EXP和IMP技术,那么如果要防范此类问题,升级到Oracle10g,用expdp(Datapump)取代原始的exp,而TDE技术是支持Datapump的。

From Drop Box

What is Oracle Audit Vault

Oracle Audit Vault

Oracle忽然很倾向于使用Vault(保险库)这个词语了,推出了Oracle Database Vault,现在又是Oracle Audit Vault

官方文档的示意图给出Oracle Audit Vault的整体架构。

OAV是一个新的安全产品(塞班斯法案害人不浅啊),如果说Oracle Database Vault是完善了对于数据库SYSDBA的权限控制,那么Oracle Audit Vault则是对于企业内部违规者的进一步预防和监控。目前OAV只针对于Oracle的数据库产品,支持Oracle Database 9i到10gR2的所有数据库版本,实现的是自动获捕获,存储,分析审计数据的功能。

OAV的元数据可以是数据库redo日志数据库Audit日志以及操作系统Audit日志,这些元数据被Audit Agent通过预先制定的捕获规则抓取到Audit Server中,而Audit Server端则提供了多样的报表查询,并且根据预先定义的企业策略提供违规操作告警功能。

OAV是针对Sarbanes-Oxley (SOX)的应景之作,它还有很长的路要走,作为一个安全产品,仅仅是面向Oracle数据库还是远远不够的,Oracle也承诺将在以后逐步完善对于Microsoft SQL Server和IBM UDB的支持。

目前Oracle Audit Vault已经推出了大部分平台上的版本,包括Linux, AIX, HP-UX, Soalris,而Windows和HP-Itanium的版本也将在不久推出,不知道国内的企业什么时候才会准备考虑这些安全方面的产品?

How to disable Oracle database vault in Windows

Oracle database vault是Oracle10g新推出的增强性安全管理组件,让人头疼的是安全性跟操作简便性总是一对冤家。

在安装了Oracle database vault组件的数据库中很多sys用户的特权都被取消了,比如你无法用操作系统验证直接登录sys用户(甚至在修改数据库密码文件之前任何方法都无法使用SYSDBA权限登录数据库),比如你无法运行alter system dump datafile命令来转储block的信息,还有更多需要sysdba权限的数据库功能都受到影响,比如Data Guard,RMAN,RAC svrctl, ASM, Oracle Enterprise Manager Database Control等等。

SQL> show user;
USER is “SYS”
SQL> alter system dump datafile 4 block 11;
alter system dump datafile 4 block 11
*
ERROR at line 1:
ORA-01031: insufficient privileges

如果想暂时禁用Oracle database vault功能,在Windows操作系统中需要如下操作。

1. 在service中停止Oracle服务,必须停止Oracle服务,仅仅在SQL*Plus中关闭数据库是不够的
2. 修改$ORACLE_HOME\bin\oradv10.dll文件名,随便改成什么,比如oradv10.dll.bak
3. 重新启动Oracle服务,打开数据库

在Linux中操作则更加复杂一些。

利用OLS实现行级安全性 Step By Step

前言:
在Oracle9i中有一个组件称为Oracle Label Security,这个组件实现了基于自定义策略而对数据库中的表甚或是整个Schema提供行级安全性功能。实际上Oracle Label Security是在Oracle8.1.7中提出的,在9i版本中功能得到了大幅度增强。

本文通过一个简单的例子对Oracle Label Security的功能作初步的探讨,本文使用的环境是Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 for Windows 32 bit。

流程:
首先我们了解一下实现Oracle Label Security的大体流程。
通过Oracle提供的一系列存储过程,先创建一个policy,然后在policy中创建level,compartment,group,之后通过这些定义好的level,compartment,group再定义label,然后将policy绑定到某张表或者某个schema,最后再给相应的用户设置label。

其中牵涉到几个名词,解释一下:
Policy:就是安全策略,一个安全策略是level,compartment,group,label的集合。
Level:等级,这是最基础的安全控制等级,必须设置。
Compartment:分隔(这不是官方翻译),提供第二级的安全控制,是可选的。
Group:组(这不是官方翻译),提供第三级的安全控制,是可选的。
Label:标签,最终体现到每一行上的安全标签,必须设置。只有用户被赋予的标签和此行上的标签相同或者等级更高的时候,该行才能够被用户存取。

方法:
然后再来了解一下Oracle实现Label Security的大体方法。
在设置完Label以后,通过SQL Trace,我们可以看到用户发出的select语句执行计划有了变化,即使是全表扫描,也会多出一个filter的操作。
select *
from
documents

Rows Row Source Operation
——- —————————————————
5 FILTER (cr=7 pr=0 pw=0 time=184 us)
5 TABLE ACCESS FULL DOCUMENTS (cr=7 pr=0 pw=0 time=131 us)
通过查看raw trace file可以看到Oracle在parse这个SQL的时候,自动添加了一个条件:
begin :con := LBAC_RLS.READ_FILTER(:sn, : on); end;
而这个条件的具体操作在trace file中也有保存,此处就不多说了。总之,通过trace我们知道对于设置了label的表的select操作,Oracle自动添加了条件来保证用户只能选择到自己能够看到的记录。

那么,对于DML(insert,update,delete)操作呢?其实,Oracle是自动在表上添加了触发器,这一点我们可以在设置完label以后,通过dba_triggers视图验证,添加的是INSERT AFTER EACH ROW,UPDATE AFTER EACH ROW和DELETE BEFORE EACH ROW三个trigger,Oracle的很多功能在内部其实都是通过trigger完成,比如高级复制同样如此,但是Oracle一直声称这些trigger是内部实现的,所以比用户自定义的trigger效率要高。当然,内部trigger和自定义trigger在实现机制上是否真的不同,还有待验证。

目的:
下面我们的例子将实现这样的功能。

给DOCUMENTS表中的数据设置8个标签:
第一个标签是PUBLIC,表示该类记录所有人都可以读取。
第二个标签是HR部门的员工才可以读取的。
第三个标签是HR部门并且是WEST地区的员工才可以读取的。
第四个标签是HR部门并且是EAST地区的员工才可以读取的。
第五个标签是FIN部门的员工才可以读取的。
第六个标签是FIN部门并且是WEST地区的员工才可以读取的。
第七个标签是FIN部门并且是EAST地区的员工才可以读取的。
第八个标签是无论哪个部门,无论哪个地区,都可以读取。

这8个标签用于控制DOCUMENTS表中的所有记录,记录一共分成5种类型,这里我们简化为5条记录。
SQL> select * from kamus.documents;

DOCID DOCNAME
———- —————————————-
1 SHARE_WARE
2 INTERNAL_HR_WEST
3 INTERNAL_HR_EAST
4 INTERNAL_FIN_EAST
5 INTERNAL_FIN_WEST

如果一个用户被赋予了第一个标签,那么他只能读取DOCID=1的第一条记录。
如果一个用户被赋予了第二个标签,那么他能读取1,2,3这三条记录。
如果一个用户被赋予了第三个标签,那么他能读取1,2这两条记录。
如果一个用户被赋予了第四个标签,那么他能读取1,3这两条记录。
如果一个用户被赋予了第五个标签,那么他能读取1,4,5这三条记录。
如果一个用户被赋予了第六个标签,那么他能读取1,5这两条记录。
如果一个用户被赋予了第七个标签,那么他能读取1,4这两条记录。
如果一个用户被赋予了第八个标签,那么他能读取所有的5条记录。

因为是初次探讨Label Security功能,所以可能在标签设置上还有更加简化的方法,也希望大家能够在看了本文以后思考一下,看看是否能更加简单地实现相同的功能。

步骤:
我们需要用到3个用户,一个是拥有DOCUMENTS表的KAMUS用户,一个是用于设置OLS策略的LBACSYS用户,另外一个是不受OLS策略制约的SYS用户(用来方便的插入和更新测试数据)。
1. 安装Oracle Label Security
在安装数据库软件的时候必须保证选择了Oracle Label Security组件,否则所有功能都无法使用。如果当时没有选择,可以重新运行Universal Installer进行安装。
LBACSYS用户可以利用$ORACLE_HOME/rdbms/admin/catols.sql创建。
SQL> CONN / AS SYSDBA;
SQL> @?/rdbms/admin/catols

在这个脚本的最后会自动关闭数据库,所以请不要在生产库上直接测试。

再次打开数据库,就可以使用LBACSYS用户登录了,默认密码就是lbacsys,如果投放在生产环境中,请立刻修改默认密码。

2. 创建安全策略
SQL> CONN lbacsys/lbacsys
SQL> EXEC sa_sysdba.create_policy(‘DOC_POLICY’, ‘DOC_LABEL’);

第一个参数DOC_POLICY是策略的名称,第二个参数DOC_LABEL是即将添加到DOCUMENTS表中的用于存储标签的字段名,这个字段将在后面apply table policy的时候自动完成,所以不必预先添加。

可以从DBA_SA_POLICIES视图中查询安全策略的情况。

3. 定义Level
SQL> EXEC sa_components.create_level(‘DOC_POLICY’, 1000,’PUBLIC’, ‘Public Level’);
SQL> EXEC sa_components.create_level(‘DOC_POLICY’, 2000,’INTERNAL’, ‘Internal Level’);

第一个参数是上一步创建的安全策略的名字。第二个参数是Level的等级,数字越大表示权限越高,比如此处具有INTERNAL等级的就可以同时查看有PUBLIC等级的数据。第三个参数是Level的短名,随便定义。第四个参数是Level的长名,只是起到一个说明的作用,随便定义。

可以从DBA_SA_LEVELS视图中查询安全等级的情况。

4. 定义Compartment。
本步操作是可选项,仅仅使用上一步中的Level就已经可以控制数据的行级安全性了,但是如果要实现更加复杂的控制,就可能需要定义Compartment和下一步的Group。

SQL> EXEC sa_components.create_compartment(‘DOC_POLICY’, 200,’FIN’, ‘FINANCE’);
SQL> EXEC sa_components.create_compartment(‘DOC_POLICY’, 100,’HR’, ‘HUMAN_R’);

参数依次是安全策略名,Compartment数字,短名,长名,此处的Compartment数字不涉及到权限的高低,仅仅是一个标识符而已。
可以从DBA_SA_COMPARTMENTS视图中查询安全间隔的情况。

5. 定义Group。
SQL> EXEC sa_components.create_group(‘DOC_POLICY’, 10,’ALL’, ‘ALL_REGIONS’);
SQL> EXEC sa_components.create_group(‘DOC_POLICY’, 20,’WEST’, ‘WEST_REGIONS’);
SQL> EXEC sa_components.create_group(‘DOC_POLICY’, 30,’EAST’, ‘EAST_REGIONS’);

参数依次是安全策略名,Group数字,短名,长名,此处的Group数字不涉及到权限的高低,仅仅是一个标识符而已。

可以从DBA_SA_GROUPS视图中查询安全组的情况。

注意,create_group存储过程有第5个参数,是parent_name,通过这个参数可以实现几乎无限制的多层权限控制,本文就不再深入了。

6. 创建Label。
SQL> EXEC sa_label_admin.create_label(‘DOC_POLICY’, ‘10000’, ‘PUBLIC’, TRUE);
SQL> EXEC sa_label_admin.create_label(‘DOC_POLICY’, ‘30000’, ‘INTERNAL:HR:WEST,EAST’, TRUE);
SQL> EXEC sa_label_admin.create_label(‘DOC_POLICY’, ‘35000’, ‘INTERNAL:HR:WEST’, TRUE);
SQL> EXEC sa_label_admin.create_label(‘DOC_POLICY’, ‘36000’, ‘INTERNAL:HR:EAST’, TRUE);
SQL> EXEC sa_label_admin.create_label(‘DOC_POLICY’, ‘40000’, ‘INTERNAL:FIN:WEST,EAST’, TRUE);
SQL> EXEC sa_label_admin.create_label(‘DOC_POLICY’, ‘45000’, ‘INTERNAL:FIN:WEST’, TRUE);
SQL> EXEC sa_label_admin.create_label(‘DOC_POLICY’, ‘46000’, ‘INTERNAL:FIN:EAST’, TRUE);
SQL> EXEC sa_label_admin.create_label(‘DOC_POLICY’, ‘50000’, ‘INTERNAL:FIN,HR:EAST,WEST’, TRUE);

创建了上文提到的8个label。

参数依次是安全策略名,Label Tag,Label值,是否为data label。
其中Label Tag必须是不同于系统中任何策略number的数字。
Label值是最关键的地方,通过组合前面几步中定义的level,compartment,group来设置标签,各个级别之间用冒号(:)隔开,一个级别中的多个元素用逗号(,)隔开。
是否为data label是一个布尔值,只有为TRUE的时候,这个标签才可以用于控制表数据的安全性。

可以从DBA_SA_LABELS视图中查询安全标签的情况。

7. 将策略赋予表。。
SQL> EXEC sa_policy_admin.apply_table_policy –
> ( policy_name => ‘DOC_POLICY’ –
> , schema_name => ‘KAMUS’ –
> , table_name => ‘DOCUMENTS’ –
> , table_options => ‘LABEL_DEFAULT, READ_CONTROL,WRITE_CONTROL,HIDE’);

前三个参数表示我们将DOC_POLICY策略附加到KAMUS用户的DOCUMENTS表上,执行这步操作的时候,Oracle会自动将第二步中定义的列添加到表中,如果这步执行成功,我们立刻用KAMUS用户检索DOCUMENTS表,会发现一条记录都没有了,这说明Label Security已经起作用了。

第四个参数用于设定策略如何控制表的安全性。LABEL_DEFAULT表示如果以后一个用户新增数据的时候没有指定Label那么将会使用该用户的default session label(这个default值在下面一步的用户Label设定中定义),READ_CONTROL,WRITE_CONTROL表示对于表的读写操作都受到安全策略的制约,HIDE表示不在desc表结构的时候显示DOC_LABEL列名,如果想要显示就省略HIDE字样。

注意,一旦apply策略完成,那么要修改table_options的值,比如想把HIDE去掉,那么就必须先用sa_policy_admin.remove_table_policy函数删除policy定义,然后重新apply。

8. 将Label赋予用户。
使用sa_user_admin.set_user_labels存储过程来将label赋予用户,这个存储过程有不少参数,但是必须输入的只有policy_name,user_name,max_read_label三项,其它参数如果省略的话,都有默认值。
比如def_label参数(用户新增数据的时候没有指定Label时的默认Label)如果没有设定,那么默认为跟max_read_label相同。

我们通过给KAMUS用户赋予不同的Label,来完成测试的目的。每次用LBACSYS用户设置完KAMUS用户的label,KAMUS用户都必须重新登录一次,设置才会生效。

–如果一个用户被赋予了第一个标签,那么他只能读取DOCID=1的第一条记录。
SQL> EXEC sa_user_admin.set_user_labels(policy_name=> ‘DOC_POLICY’,user_name =>’KAMUS’,max_read_label =>’PUBLIC’);

SQL> conn kamus/kamus
Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.1.0
Connected as kamus

SQL> select * from documents;

DOCID DOCNAME DOC_LABEL
———- —————————————- ———–
1 SHARE_WARE 10000

–如果一个用户被赋予了第二个标签,那么他能读取1,2,3这三条记录。
SQL> EXEC sa_user_admin.set_user_labels(policy_name=> ‘DOC_POLICY’,user_name =>’KAMUS’,max_read_label =>’INTERNAL:HR:EAST,WEST’);

SQL> conn kamus/kamus
Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.1.0
Connected as kamus

SQL> select * from documents;

DOCID DOCNAME
———- —————————————-
1 SHARE_WARE
2 INTERNAL_HR_WEST
3 INTERNAL_HR_EAST

–如果一个用户被赋予了第三个标签,那么他能读取1,2这两条记录。
SQL> EXEC sa_user_admin.set_user_labels(policy_name=> ‘DOC_POLICY’,user_name =>’KAMUS’,max_read_label =>’INTERNAL:HR:WEST’);

SQL> conn kamus/kamus
Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.1.0
Connected as kamus

SQL> select * from documents;

DOCID DOCNAME
———- —————————————-
1 SHARE_WARE
2 INTERNAL_HR_WEST

–如果 …… 此处省略中间的测试,大同小异。

–如果一个用户被赋予了第八个标签,那么他能读取所有的5条记录。
SQL> EXEC sa_user_admin.set_user_labels(policy_name=> ‘DOC_POLICY’,user_name =>’KAMUS’,max_read_label =>’INTERNAL:FIN,HR:EAST,WEST’);

SQL> conn kamus/kamus
Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.1.0
Connected as kamus

SQL> select * from documents;

DOCID DOCNAME
———- —————————————-
1 SHARE_WARE
2 INTERNAL_HR_WEST
3 INTERNAL_HR_EAST
4 INTERNAL_FIN_EAST
5 INTERNAL_FIN_WEST

至此,这个Oracle Label Security 的实验基本上是完成了,达到了我们预先计划的目标。

其它:
Label Security对于exp同样具有安全控制作用,但是并不全面。常规路径的EXP受到了安全控制。

D:\Temp>exp kamus/kamus tables=documents file=d.dmp

Export: Release 10.2.0.1.0 – Production on 星期四 1月 11 22:08:48 2007

Copyright (c) 1982, 2005, Oracle. All rights reserved.

连接到: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 – Production
With the Partitioning, Oracle Label Security, OLAP and Data Mining options
已导出 ZHS16GBK 字符集和 AL16UTF16 NCHAR 字符集

即将导出指定的表通过常规路径…
EXP-00079: 表 “DOCUMENTS” 中的数据是被保护的。常规路径只能导出部分表。
. . 正在导出表 DOCUMENTS导出了 2 行
EXP-00091: 正在导出有问题的统计信息。
导出成功终止, 但出现警告。

但是只要加上direct=y这样用直接路径导出,就跳过了Label Security的控制。

D:\Temp>exp kamus/kamus tables=documents file=d.dmp direct=y

Export: Release 10.2.0.1.0 – Production on 星期四 1月 11 22:08:53 2007

Copyright (c) 1982, 2005, Oracle. All rights reserved.

连接到: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 – Production
With the Partitioning, Oracle Label Security, OLAP and Data Mining options
已导出 ZHS16GBK 字符集和 AL16UTF16 NCHAR 字符集

即将导出指定的表通过直接路径…
. . 正在导出表 DOCUMENTS导出了 5 行
成功终止导出, 没有出现警告。

而关于性能方面,如果表中数据量很大,那么出于性能考虑,可能需要在Label列上(本例中的DOC_LABEL)添加合适的索引,根据cardinality的多少,选择B-Tree或者bitmap索引。

提问:
大家可能注意到在第5步定义Group的时候,我定义了3个组,其中ALL组一直没有用到,那么现在的问题就是:
新创建一个Label:
EXEC sa_label_admin.create_label(‘DOC_POLICY’, ‘20000’, ‘INTERNAL:HR:ALL’, TRUE);
新插入一条数据
insert into kamus.documents values(6,’INTERNAL_HR_ALL’,20000);
而此时KAMUS用户的max_read_label是最高等级的’INTERNAL:FIN,HR:EAST,WEST’
那么select * from documents;会有几行数据返回?

注意:插入数据,可以通过直接指定Label Tag数值或者使用CHAR_TO_LABEL函数,比如上面的insert语句等值于:
insert into kamus.documents values(6,’INTERNAL_HR_ALL’, CHAR_TO_LABEL(‘DOC_POLICY’,’ INTERNAL:HR:ALL’));

结论:
通过Oracle Label Security策略可以很方便地在数据库这个层面上完成对于应用数据的安全性保护,个人认为跟基于VPD和SYS_CONTEXT的行级安全保护方法相比,OLS在分层控制方面更有效,设置更简单,而后者则因为手动编写VPD策略函数,所以具有更大的灵活性。但是无论是使用OLS还是VPD策略函数,都无法防止SYSDBA用户查看业务数据,针对此问题,Oracle的解决方案是Oracle Data Vault。

后续:
Oracle数据库安全领域有很多我还没有接触到的东西需要学习,下面一篇文章我将会介绍Oracle10g的新增组件Oracle Data Vault ,敬请期待。

利用VPD细粒度访问策略实现行级安全性 Step By Step

Oracle8i以后的版本都提供了VPD(virtual private database 虚拟专用数据库)这样一个强大的功能来实现呼声日益增高的系统安全性要求。

通过设置基于VPD的细粒度访问策略,我们可以只通过DBA的工作(不需要修改应用,也就是应用透明化)就可以实现用户只能访问自己有权限访问的数据,当然如果需要更加复杂的权限控制开发人员的参与还是必不可少的。

下面用一个简单的例子来实现这样的功能,在EMP表中的用户登录数据库以后只能查询和更新自己所属部门的其它员工资料,不是本部门的不会显示也不允许更新。

1. 我们需要用到3个用户,一个是拥有EMP表的SCOTT用户,一个是用于设置VPD策略的KAMUS用户,另外一个是在EMP表中有记录的SMITH用户。
SCOTT用户可以利用$ORACLE_HOME/rdbms/admin/scott.sql创建。
@?/rdbms/admin/scott.sql
KAMUS用户需要能够执行DBMS_RLS包的权限。
grant execute on dbms_rls to kamus;
SMITH用户需要能够读取并更新EMP表的权限。
grant select on scott.emp to smith;

2. 首先用KAMUS用户创建策略权限表。为方便起见我们直接通过EMP表创建,本策略表中包含了员工姓名和所属部门编号。为了更加完善策略函数,我们创建完策略表后在表中新增一条记录,让SMITH用户同时属于20和10这两个部门。

SQL> create table access_policy as select ename,deptno from scott.emp;

Table created

SQL> select * from access_policy;

ENAME DEPTNO
———- ——
SMITH 20
ALLEN 30
WARD 30
JONES 20
MARTIN 30
BLAKE 30
CLARK 10
KING 10
TURNER 30
JAMES 30
FORD 20
MILLER 10

12 rows selected

SQL> insert into access_policy values(‘SMITH’,10);

1 row inserted

SQL> commit;

Commit complete

3. KAMUS用户创建VPD策略需要的函数。
create or replace function get_user_dept_id
(
p_schema in varchar2,
p_table in varchar2
)
return varchar2
as
l_retstr varchar2(2000);
begin
if (p_schema = user) then
l_retstr := null;
else
for user_rec in
(
select deptno
from access_policy
where ename = USER
) loop
l_retstr := l_retstr||’,’||user_rec.deptno;
end loop;
l_retstr := ltrim(l_retstr,’,’);
if (l_retstr is null) then
l_retstr := ‘1=2’;
else
l_retstr := ‘DEPTNO IN (‘||l_retstr||’)’;
end if;
end if;
return l_retstr;
end;

该函数实现以下功能:
如果使用SCOTT用户登录,因为表是属于该用户的,所以不加任何限制。
如果使用其它用户登录(SYS用户不受此限制),那么根据EMP表中该用户的所属部门决定哪些记录允许该用户操作,本例中10和20这两个部门的员工SMITH用户将都能看见。
如果登录的用户不在EMP表中,那么该用户查看不到任何数据,比如KAMUS用户。

注意:
VPD策略函数必须包含两个参数,本例中是p_schema和p_table,即使这两个参数在函数中没有用到,也必须包含。否则在后面检索EMP表数据的时候将会报:
PLS-00306: 调用 ‘GET_USER_DEPT_ID’ 时参数个数或类型错误。

我们用SMITH用户登录数据库来测试一下这个函数的返回值。

SQL> select kamus.get_user_dept_id(‘SCOTT’,’EMP’) from dual;

KAMUS.GET_USER_DEPT_ID(‘SCOTT’
——————————————————————————–
DEPTNO IN (20,10)

也就是说基于VPD的细粒度访问策略实际上就是在用户提交一个SQL以后会将策略函数返回值添加到where语句后面,通过这种方式来限制用户对于表中数据的访问。

4. 用KAMUS用户创建VPD策略。

begin
dbms_rls.add_policy (
object_schema => ‘SCOTT’,
object_name => ‘EMP’,
policy_name => ‘EMP_SEL_POLICY’,
function_schema => ‘KAMUS’,
policy_function => ‘GET_USER_DEPT_ID’,
statement_types => ‘SELECT’
);
end;
/

这是用于select的策略。

begin
dbms_rls.add_policy (
object_schema => ‘SCOTT’,
object_name => ‘EMP’,
policy_name => ‘EMP_IUD_POLICY’,
function_schema => ‘KAMUS’,
policy_function => ‘GET_USER_DEPT_ID’,
statement_types => ‘INSERT, UPDATE, DELETE’,
update_check => TRUE
);
end;
/

这是用于DML的策略。

5. 至此为止我们的VPD方案就已经设置完毕了。下面我们测试一下。

SQL> conn scott/tiger
已连接。
–SCOTT用户可以选择出全部的12条记录
SQL> select count(*) from emp;

COUNT(*)
———-
12

SQL> conn smith/smith
已连接。
–SMITH用户只能选择出属于10,20部门的6条记录
SQL> select count(*) from scott.emp;

COUNT(*)
———-
6
–更新也只能更新6行记录
SQL> update scott.emp set sal=sal+100;

已更新6行。
–如果尝试插入一个其它部门的员工将会报错
SQL> insert into scott.emp(empno,ename,deptno) values(9999,’VPD’,30);
insert into scott.emp(empno,ename,deptno) values(9999,’VPD’,30)
*
第 1 行出现错误:
ORA-28115: 策略违反检验选项
–即使指定了要更新30部门的数据也是一条都无法更新
SQL> update scott.emp set sal=sal+100 where deptno=30;

已更新0行。
–同样删除也只能删除6行数据
SQL> delete scott.emp;

已删除6行。

结论:
通过基于VPD的细粒度访问策略可以很简单地在数据库这个层面上完成对于应用数据的安全性保护,而如果通过SYS_CONTEXT以及数据库登录触发器来编写更加复杂的VPD策略函数的话,就能实现非常强大的数据安全性功能。

后续:
Oracle数据库安全领域有很多我还没有接触到的东西需要学习,下面一篇文章我将会介绍同样是基于VPD的更深一步的安全策略解决方案 - Label Security,敬请期待