FGA_LOG$
![]() |
Oracle Database 11g:
作者:Arup Nanda |
安全性
Oracle Database 11g 提供了丰富的安全性新功能 — 区分大小写的口令、透明表空间加密以及适用于 UTL_TCP/HTTP/SMTP 的访问控制列表。
默认口令
Oracle Database 11g 现在提供一种快速识别使用默认口令的用户的方法。该方法实施起来极为简单,只需检查一个数据字典视图:DBA_USERS_WITH_DEFPWD。(注意,DBA_ 是一个标准前缀,它不仅包含使用默认口令的 DBA 用户。)您可以执行以下命令来识别这些用户:
select * from dba_users_with_defpwd
输出如下:
USERNAME ------------------------------ DIP MDSYS WK_TEST CTXSYS OLAPSYS OUTLN EXFSYS SCOTT MDDATA ORDPLUGINS ORDSYS XDB LBACSYS SI_INFORMTN_SCHEMA WMSYS
由于 SCOTT 使用了默认口令 TIGER,因此您会看到他出现在上面的清单中。使用下面的语句进行更改:
SQL> alter user scott identified by tiger1; User altered.
现在,如果您查看该视图:
SQL> select * from dba_users_with_defpwd;
您就不会在该清单中看到 SCOTT 了。就这么简单!
区分大小写的口令
在版本 11g 之前的 Oracle 数据库中,用户口令是不区分大小写的。例如:
SQL> conn scott/tiger Connected. SQL> conn scott/TIGER Connected.
对于支付卡行业 (PCI) 数据安全标准等要求口令区分大小写的标准而言,这种方法存在问题。
该问题已得到解决,Oracle Database 11g 支持区分大小写的口令。通过 DBCA 创建数据库时,系统会提示您是否希望升级到“新的安全标准”,其中之一就是区分大小写的口令。如果您接受该标准,口令在创建时的大小写状态将被记录下来。假如您接受了新标准,相应的操作结果如下:
SQL> conn scott/tiger Connected. SQL> conn scott/TIGER ERROR: ORA-01017: invalid username/password; logon denied Warning: You are no longer connected to ORACLE.
注意对“tiger”和“TIGER”的不同处理方式。
现在,您的某些应用程序可能无法立即传递大小写正确的口令。典型示例是用户输入表单:很多表单在接受口令时不会进行大小写转换。然而,在 Oracle Database 11g中,这种登录方式可能会失败,除非用户以区分大小写格式输入口令,或者开发人员对应用程序进行了修改,使其能够进行大小写转换(这一点不可能迅速实现)。
不过,如果您希望的话,仍然可以通过更改系统参数 SEC_CASE_SENSITIVE_LOGON 恢复到不区分大小写的状态,如以下示例所示。
SQL> conn / as sysdba Connected. SQL> alter system set sec_case_sensitive_logon = false; System altered. SQL> conn scott/TIGER Connected.
在将现有 Oracle 10g 数据库升级到 11g 时,可将口令迁移到新标准。可以通过查询 DBA_USERS 视图来检查口令状态,尤其是新的 PASSWORD_VERSIONS 列。
select username, password, password_versions from dba_users; USERNAME PASSWORD PASSWORD ------------------------- ------------------------------ -------- SYSTEM 10G 11G SYS 10G 11G MGMT_VIEW 10G 11G
您首先会注意到 PASSWORD 列为空,没有像 Oracle Database 10g 和以前的版本中那样使用散列值填充。那么,口令出什么问题了?口令仍然存储在数据库中(在 USER$ 表中),但它在 DBA_USERS 视图中不可见。当用户被创建为全局或外部认证的用户时,其状态指示为 GLOBAL 或 EXTERNAL,但不显示口令的散列值。
接下来,注意 PASSWORD_VERSIONS 列,它是 Oracle Database 11g 中新增的。该列表明口令是否区分大小写。值“10G 11G”的意思是,用户要么是在 10g 中创建然后迁移到 11g 中的,要么是直接在 11g 中创建的。
如果您希望的话,在创建口令文件时,您也可以输入一个新参数 ignorecase 来实现 SYSDBA 口令的大小写区分,如下所示:
$ orapwd file=orapwPRODB3 password=abc123 entries=10 ignorecase=n
在以上示例中,SYSDBA 的口令将为 abc123,而不是 ABC123 或任何其他大小写变体。
通过采用区分大小写的口令,不仅使得强行破解口令更为困难,同时能够使您满足更多合规性要求。更重要的是,您可以动态地执行口令要求而不必关闭数据库。在进行升级或因升级原有应用程序而对登录问题进行调试时,这是非常有用的。
配置文件和口令验证功能
还记得 Oracle Database 中的口令验证功能吗?很多人甚至可能都不知道它的存在,更不要说使用它了。该功能是确保数据库口令质量的快捷、轻松的手段 — 例如,口令应包含一定数目的字符,不应与用户名相同,等等。也许它的最佳特色在于它是内置的,您只需要启用它即可。但很可能的是,您并没有启用该功能。
在 Oracle Database 11g 中,口令管理功能具有新的经过改进的验证逻辑。如果您查看 $ORACLE_HOME/rdbms/admin 下的口令验证文件 utlpwdmg.sql,就会发现脚本新建了一个名为 verify_fnction_11g 的口令函数。脚本末尾的语句如下所示:
ALTER PROFILE DEFAULT LIMIT PASSWORD_LIFE_TIME 180 PASSWORD_GRACE_TIME 7 PASSWORD_REUSE_TIME UNLIMITED PASSWORD_REUSE_MAX UNLIMITED FAILED_LOGIN_ATTEMPTS 10 PASSWORD_LOCK_TIME 1 PASSWORD_VERIFY_FUNCTION verify_function_11G;
脚本将该函数附加到配置文件 DEFAULT 中。除非明确分配了其他文件,该文件是所有用户的默认配置文件。这使得认证符合许多规定的要求。您要做的只是运行该脚本以创建 11 g 版的口令检查函数,该脚本将通过将自身附加到默认配置文件中来启用口令验证功能。
改进的即需即用的审计
审计是另一个常见难题。Oracle Database 包括强大的审计功能,可用于跟踪用户活动。大多数人由于担心 I/O 争用问题,并不利用审计功能。但事实上,可以安全、低风险地启动部分审计功能。
相关的示例包括 CREATE SESSION,它在会话开始时编写一条记录,然后在会话结束时更新该记录。该审计对 I/O 的影响极小,但带来了众多好处。
在 Oracle Database 11g 中,进行了两个简单的改动以提供更强大的审计解决方案。首先,数据库参数 audit_trail 现在默认情况下设置为 DB,在以前的版本中,它的默认值为 NONE。这允许您对任何对象、语句或权限打开审计,而无需重复使用数据库。
第二处改动是,默认情况下更多语句处于审计范围内。清单如下:
ALTER SYSTEM SYSTEM AUDIT CREATE SESSION CREATE USER ALTER USER DROP USER ROLE CREATE ANY TABLE ALTER ANY TABLE DROP ANY TABLE CREATE PUBLIC DATABASE LINK GRANT ANY ROLE ALTER DATABASE CREATE ANY PROCEDURE ALTER ANY PROCEDURE DROP ANY PROCEDURE ALTER PROFILE DROP PROFILE GRANT ANY PRIVILEGE CREATE ANY LIBRARY EXEMPT ACCESS POLICY GRANT ANY OBJECT PRIVILEGE CREATE ANY JOB CREATE EXTERNAL JOB
如您所见,审计这些活动不会导致严重的 I/O 问题,因此,可将审计活动维持在可接受水平,同时对性能的影响最小。
这两处改动带来了一些强大的即需即用的审计功能。当然,它们只是一些数据库参数和审计设置;如果需要的话,您可以轻松地关闭它们。但如果您看看这些语句清单,您实际上会发现即使在开发数据库中,它们也是值得审计的。不过,您可能想对它们进行细微的调整。(例如,在数据仓库中,用户创建并删除大量临时表,因此审计 CREATE/DROP TABLE 可能会在审计线索中泛滥。)
警告: 升级到 Oracle Database 11g 后,默认情况下上述语句的审计将打开。因此,审计线索将写入到 SYSTEM 表空间中的表 AUD$ 中,这些审计线索将迅速填充。密切关注该表空间。
透明表空间加密
由于各种新的法律法规,人们现在对加密的重视程度越来越高。您需要以某种方式对数据进行加密,但最大的问题在于如何加密?
对于仍然使用 Oracle Database 10g 第 1 版和以前版本的人来说,DBMS_CRYPTO 和 DBMS_OBFUSCATION_TOOLKIT 工具包允许您构建自己的加密框架。在 Oracle Database 10g 第 2 版中,该框架通过透明数据加密特性得以增强。
透明数据加密使您可以对特定列进行加密,这足以满足大多数要求。然而,性能仍然是该特性的一个问题(或者说,任何其他加密解决方案都存在着性能问题):索引范围扫描不能应用于加密列,这会对性能造成严重的负面影响。
这正是 Oracle Database 11g 中透明表空间加密的真正出色之处。当表空间声明已加密时,表空间(包括透明表空间、备份等)上的任何数据都已加密,而不仅仅是单独声明为已加密的表。但在进行索引扫描时,扫描发生在未对数据进行加密的内存中,因而不会对性能造成影响。
感觉激动吗?让我们看一下它的工作原理。加密过程与透明数据加密过程相同:您需要创建一个钱夹以存储主加密密钥。如果您还没有设置透明数据加密,则需要创建钱夹和密钥。
首先,创建钱夹的文件位置;默认位置为 $ORACLE_BASE/admin//wallet。默认情况下钱夹子目录并不存在,您需要进行创建。因此,在我的示例中,该目录为 /home/oracle/app/admin/PRODB3/wallet。
接下来,执行下面的语句以在钱夹中创建加密密钥:
alter system set encryption key identified by "abcd1234!";
该语句同时创建钱夹和密钥。如果您现在检查该目录,会看到刚刚创建的钱夹文件 (ewallet.p12)。
$ cd /home/oracle/app/admin/PRODB3/wallet $ ls ewallet.p12
钱夹要使用口令才能打开,在本例中,口令为 abcd1234!。该语句也可以打开钱夹。以后,您无需再创建钱夹了。数据库启动后,您只需通过执行以下语句来打开钱夹:
alter system set wallet open identified by "abcd1234!"
有关钱夹的更详细的讨论,请阅读这篇 Oracle Magazine 文章。
现在创建表空间:
create tablespace secure1 datafile '/home/oracle/oradata/PRODB3/secure1_01.dbf' size 1M encryption using 'AES128' default storage (encrypt) /
子句“encryption using ... default storage (encrypt)”将表空间标记为经过加密的。(注意:我们对此表空间使用了 AES 128 位加密算法。其他选择包括 Triple DES 168 位密钥算法、AES 192 位密钥算法和 AES 256 位密钥算法。)
既然已经创建了表空间,您就可以像在常规表空间中那样创建表了。
create table secure_trans tablespace secure1 as select * from trans where rownum < 201 / create table secure_res tablespace secure1 as select * from res where rownum < 201 /
上述语句在加密的表空间 SECURE1 中创建了表。为进行比较,以正常方式(不加密)创建另一个名为 INSECURE1 的表空间,并在其中创建表 INSECURE_TRANS 和 INSECURE_RES。INSECURE_TRANS 和 SECURE_TRANS 在结构和数据方面相同,但位于不同的表空间中。SECURE_RES 和 INSECURE_RES 也是如此。
现在更新这些表中的一个文本字段,以便在数据文件中搜索该字段:
update secure_trans set comments = 'Transaction Comments'; update insecure_trans set comments = 'Transaction Comments'; commit;
通过使表空间先脱机再联机,将内容强制写到磁盘上:
alter tablespace secure1 offline; alter tablespace secure1 online; alter tablespace insecure1 offline; alter tablespace insecure1 online;
此时,缓存中的数据已经写到磁盘上。搜索该字段,看会发生什么?
$ strings insecure1_01.dbf | grep Transaction Transaction Comments ...
该字符串以明文形式出现在数据文件中。现在,对经过加密的 SECURE1 表空间执行同样的操作。
$ strings secure1_01.dbf | grep Transaction $
该操作不会返回任何结果,因为数据文件是加密的,您无法以明文形式看到各列的值。一切都完美无缺,但性能怎么样呢?我们运行以下查询来体验一下。
select hotel_id, sum(amt) from secure_trans t, secure_res r where t.res_id = r.res_id group by hotel_id
运行该查询时,我们也会对其进行跟踪。下面是跟踪文件的节选。
call count cpu elapsed disk query current rows现在,对 INSECURE_RES 和 INSECURE_TEST 运行相同的测试,它们处于正常的(未加密的)表空间内。
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 14 0.01 0.01 4 6 0 186
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 16 0.01 0.01 4 6 0 186
Rows Row Source Operation
------- ---------------------------------------------------
186 HASH GROUP BY (cr=6 pr=4 pw=4 time=5 us cost=8 size=10400 card=200)
200 HASH JOIN (cr=6 pr=4 pw=4 time=45 us cost=7 size=10400 card=200)
200 TABLE ACCESS FULL SECURE_TRANS (cr=3 pr=2 pw=2 time=8 us cost=3 size=5200 card=200)
200 TABLE ACCESS FULL SECURE_RES (cr=3 pr=2 pw=2 time=9 us cost=3 size=5200 card=200)
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 14 0.00 0.01 4 6 0 186
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 16 0.01 0.01 4 6 0 186
Rows Row Source Operation
------- ---------------------------------------------------
186 HASH GROUP BY (cr=6 pr=4 pw=4 time=4 us cost=8 size=10400 card=200)
200 HASH JOIN (cr=6 pr=4 pw=4 time=46 us cost=7 size=10400 card=200)
200 TABLE ACCESS FULL INSECURE_TRANS (cr=3 pr=2 pw=2 time=8 us cost=3 size=5200 card=200)
200 TABLE ACCESS FULL INSECURE_RES (cr=3 pr=2 pw=2 time=9 us cost=3 size=5200 card=200)
注意各例中的执行时间,它们都是相似的。因解密而导致的 CPU 消耗也并不显著。因此,表空间加密不会对性能产生影响。
DBA_TABLESPACES 视图有一个新列 ENCRYPTED,用于显示某个表空间是否已加密。此外,一个名为 V$ ENCRYPTED_TABLESPACES 的新视图用于显示针对该表空间启用的加密类型。
SQL> desc v$encrypted_tablespaces
Name Null? Type
----------------------------------------- -------- ------------
TS# NUMBER
ENCRYPTIONALG VARCHAR2(7)
ENCRYPTEDTS VARCHAR2(3)
SQL> select * from v$encrypted_tablespaces;
TS# ENCRYPT ENC
---------- ------- ---
5 AES128 YES
该视图可以和 V$TABLESPACE 视图的 TS# 列结合,以获得完整的信息。下面是该视图的外观:
SQL> desc v$tablespace Name Null? Type ----------------------------------------- -------- ------------ TS# NUMBER NAME VARCHAR2(30) INCLUDED_IN_DATABASE_BACKUP VARCHAR2(3) BIGFILE VARCHAR2(3) FLASHBACK_ON VARCHAR2(3) ENCRYPT_IN_BACKUP VARCHAR2(3)
注意,ENCRYPT_IN_BACKUP 列和透明表空间加密没有任何关系。相反,它是备份期间表空间的 RMAN 加密,是在 Oracle Database 10g 第 2 版中引入的。
如您所见,透明表空间加密以一种相当完美的方式解决了两个问题:它对磁盘上处于静止状态的数据进行加密,由于数据管理发生在 SGA 内,因此不会影响性能。
Data Pump 转储文件的加密
Oracle Database 10g 引入了用于数据移动的最强大的特性之一:Data Pump,它用于代替原来的导出/导入工具。除了速度更快之外,Data Pump 还具有很多优点,如并行化进程和重新映射表空间。在 Oracle Database 11g 中,它还通过一个新参数 ENCRYPTION 来帮助保护转储文件的安全。
转储文件位于数据库和数据库安全领域之外,并且包含潜在的敏感数据。在如今的安全意识环境中,它们构成了一组独特的问题。在一些真正具有安全意识的环境中,DBA 在导出数据后通过第三方实用程序对转储文件进行加密 — 如果导出工作量巨大,那么这绝不是一种非常便捷的方法。
首先,我们了解一下典型转储文件的易受攻击程度。假设您有一个名为 TRANS 的表,它包含一个名为 COMMENTS 的列。该列中的值为“Transaction Comments”。如果您以正常方式导出该表:
$ expdp scott/tiger tables=trans dumpfile=insec.dmp directory=tmp_dir
检查转储文件以查看该列值是否存在:
$ strings /tmp/insec.dmp | grep Transaction
将出现大量匹配项。转储文件中的数据未加密,处于明文状态。
现在,使用新参数 ENCRYPTION 执行导出。您还必须指定要使用的算法类型。我们将使用 AES 128 位算法。
$ expdp scott/tiger tables=trans dumpfile=sec.dmp directory=在此 转储文件中搜索是否存在该文本字符串:
tmp_dir encryption=data_only encryption_algorithm=aes128
Export: Release 11.1.0.5.0 - Beta on Sunday, 22 July, 2007 18:17:30
Copyright (c) 2003, 2007, Oracle. All rights reserved.
Connected to: Oracle Database 11g Enterprise Edition Release 11.1.0.5.0 - Beta
With the Partitioning, Oracle Label Security, OLAP, Data Mining
and Real Application Testing options
Starting "SYS"."SYS_EXPORT_TABLE_01":
'/******** AS SYSDBA' tables=scott.insecure_trans dumpfile=
sec.dmp directory=tmp_dir encryption=data_only encryption_algorithm=aes128
Estimate in progress using BLOCKS method...
Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
Total estimation using BLOCKS method: 64 KB
Processing object type TABLE_EXPORT/TABLE/TABLE
. . exported "SCOTT"."TRANS" 16.82 KB 200 rows
Master table "SYS"."SYS_EXPORT_TABLE_01" successfully loaded/unloaded
******************************************************************************
Dump file set for SYS.SYS_EXPORT_TABLE_01 is:
/tmp/sec.dmp
Job "SYS"."SYS_EXPORT_TABLE_01" successfully completed at 18:17:44
$ cat /tmp/sec.dmp | grep Transaction $
由于转储文件中的值是经过加密的,不是明文,因此不会出现任何匹配项。
“但是等一下”,您会说,“加密不需要密钥吗?我们将要使用的密钥传递到什么地方了?更重要的是,解密时如果没有密钥如何解密呢?”
答案非常简单:密钥将来自于您在前面看到的透明表空间加密中使用的钱夹。您无需为了使用 Data Pump 加密而使用透明表空间加密特性,但您需要执行相关步骤来创建钱夹。不必说,在加密和解密过程中,钱夹必须是打开的。
如果您熟悉 Data Pump 工具,您可能会想起一个类似的特性是通过参数 ENCRYPTION_PASSWORD 实现的。现在,您可能想知道二者有何区别。
问得好。10g 版对那些处于透明数据加密状态的列进行加密,而不是对整个转储文件进行加密。如果您不使用透明数据加密,就不会进行转储文件加密。在该工具的 11g 版中,无论是否使用了透明数据加密,您都可以对转储文件进行加密。这会为您带来更大的灵活性,同时具有一些实用价值。您可能不想对数据库中的数据进行加密,原因有很多,性能和增加的安全性是最明显的原因。但当数据位于数据库领域之外时,您一定希望对它们进行加密。在这种情况下,Data Pump 加密的威力就无可匹敌了。
适用于 UTL_TCP/HTTP/SMTP 的访问控制列表
您可能熟悉 UTL_TCP、UTL_HTTP 和 UTL_SMTP 这些程序包,它们支持数据库领域外的服务器之间的通信。例如,utl_tcp 用于在两台主机间建立 TCP/IP 通信,而不是通过数据库链接。类似地,utl_http 用于从 Web 服务器发出 http 请求,utl_smtp 用于在主机间进行 SMTP 邮件呼叫。
开发人员偶尔会使用这些强大的工具 — 例如,使用 utl_smtp 从数据库内发送电子邮件,使用 utl_http 提取可在 PL/SQL 程序内处理的 Web 页面等等。然而,这些工具带来了巨大的安全风险。使用 utl_tcp,数据库用户可以到达该主机可到达的任何其他计算机,甚至不会遇到系统提示。这曾是 Voyager 蠕虫的惯用伎俩,该病毒一年前刚骚扰过 Oracle 用户社区。
为了消除这一风险,很多专家建议撤销“从公网执行”这些程序包的权限。在我的“安全保护项目”系列文章中,我也推荐了这种方法。但如果开发人员出于合理原因希望执行这些程序包,该怎么办?
Oracle Database 11g 有一个新的解决方案:您可以将执行权限程序包授予任何人,但要控制他们可以调用的资源。例如,utl_tcp 可限制为仅调用几个 IP 地址,这种机制称为访问控制列表 (ACL)。如果主机在 ACL 中,用户可以在 utl_tcp 中使用;但是仅仅拥有对 utl_tcp 的执行权限是不够的。因此,恶意进程不可能取代 utl_tcp 程序包和建立非法连接。
我们来看一下它的工作原理。首先,创建一个 ACL:
begin dbms_network_acl_admin.create_acl ( acl => 'utlpkg.xml', description => 'Normal Access', principal => 'CONNECT', is_grant => TRUE, privilege => 'connect', start_date => null, end_date => null ); end;
在这里,参数 principal => 'CONNECT' 表示该 ACL 适用于 CONNECT 角色。您可以在此处定义一个用户或角色。该 ACL 是作为一个 utlpkg.xml 文件创建的。
创建完毕后,您可以进行检查以确保该 ACL 已添加:
SELECT any_path输出结果如下:
FROM resource_view
WHERE any_path like '/sys/acls/%.xml';
ANY_PATH
----------------------------------------------------------------------------
/sys/acls/ANONYMOUS/ANONYMOUS3553d2be53ca40e040a8c0680777c_acl.xml
/sys/acls/OLAP_XS_ADMIN/OLAP_XS_ADMIN3551b25f93feb8dde040a8c068075b7_acl.xml
/sys/acls/OLAP_XS_ADMIN/OLAP_XS_ADMIN3551b25f944b8dde040a8c068075b7_acl.xml
/sys/acls/OLAP_XS_ADMIN/OLAP_XS_ADMIN3551b25f948b8dde040a8c068075b7_acl.xml
/sys/acls/OLAP_XS_ADMIN/OLAP_XS_ADMIN3551b25f94cb8dde040a8c068075b7_acl.xml
/sys/acls/all_all_acl.xml
/sys/acls/all_owner_acl.xml
/sys/acls/bootstrap_acl.xml
/sys/acls/ro_all_acl.xml
/sys/acls/ro_anonymous_acl.xml
/sys/acls/utlpkg.xml
注意输出结果中的最后一行,其中显示了您刚刚创建的 ACL。接下来,为该 ACL 添加一个权限。在本示例中,您将尝试将该 ACL 局限于用户 SCOTT。您还可以定义开始和结束日期。
begin dbms_network_acl_admin.add_privilege ( acl => 'utlpkg.xml', principal => 'SCOTT', is_grant => TRUE, privilege => 'connect', start_date => null, end_date => null); end;
分配将受该 ACL 制约的主机以及其他详细信息:
begin dbms_network_acl_admin.assign_acl ( acl => 'utlpkg.xml', host => 'www.proligence.com', lower_port => 22, upper_port => 55); end;
在本示例中,您指定“用户 SCOTT 只能调用主机 www.proligence.com,并且只能使用 22 到 55 端口。”现在让我们来试一下:
SQL> grant execute on utl_http to scott 2 / Grant succeeded. SQL> conn scott/tiger Connected. SQL> select utl_http.request('http://www.proligence.com') from dual; select utl_http.request('http://www.proligence.com') from dual * ERROR at line 1: ORA-29273: HTTP request failed ORA-06512: at "SYS.UTL_HTTP", line 1577 ORA-24247: network access denied by access control list (ACL) ORA-06512: at line 1
注意错误“ORA-24247:network access denied by access control list (ACL)”。用户在端口 80 上调用 http 服务器,由于该服务器在允许的 22-55 范围之外,因此该操作被阻止。
现在,添加另一条规则以允许该通信:
1 begin 2 dbms_network_acl_admin.assign_acl ( 3 acl => 'utlpkg.xml', 4 host => 'www.proligence.com', 5 lower_port => 1, 6 upper_port => 10000); 7* end; 8 / PL/SQL procedure successfully completed. SQL> conn scott/tiger Connected. SQL> select utl_http.request('http://www.proligence.com') from dual; UTL_HTTP.REQUEST('HTTP://WWW.PROLIGENCE.COM') -------------------------------------------------------------------------------- </iframe><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML><HEAD><TITLE>Proligence Home</TITLE> <META http-equiv=Content-Language content=en-us> ...
但该规则仅适用于 www.proligence.com。如果您调用其他 Web 站点,调用将失败,错误原因仍为 ORA-24247。这是最细粒度水平上的安全性。如果您的企业需要连接到主机 www.proligence.com,您可以在允许该连接的同时阻止对任何其他主机的访问,从而防止恶意用户使用该功能来访问所有其他的主机。
要了解 ACL 的详细信息,请查询 DBA_NETWORK_ACLS 视图:
select host, lower_port, upper_port, acl, aclid from dba_network_acls where ACL='/sys/acls/utlpkg.xml'; HOST --------------------------------------- LOWER_PORT UPPER_PORT ---------- ---------- ACL --------------------------------------- ACLID -------------------------------- prolin3.proligence.com 80 100 /sys/acls/utlpkg.xml 35D4278980DE6407E040A8C0680037D6 ... and so on ...
在我看来,这是 Oracle Database 11g 最好的新安全特性之一。
数据屏蔽
在许多组织中,临时数据库或 QA 数据库经常根据生产数据库进行刷新,从而允许开发人员在投入生产前针对数据库运行生产前代码。然而,该过程存在潜在的安全问题 — 当数据从生产数据库刷新到 QA 数据库以保持同步时,可能会泄露敏感的数据元素。为了应对该风险,很多组织在非生产数据库中将敏感数据更换为某些无意义的值,这种做法称为数据屏蔽。例如,您可能希望临时用一个随机的 9 个字符的编号来更新社会保险编号,从而屏蔽真实的 SSN。
然而,知易行难,实现更改并不容易 — 您必须编写 SQL 脚本,确保进程可重新启动,小心避免系统崩溃等等。导入数据时,为什么不让 Oracle 来处理上述事宜呢?在 Oracle Database 11g 中,Data Pump 有一个新参数 remap_data,用于在导入过程中更改数据。
首先创建一个重映射函数:
create or replace package pkg_mask as function fn_mask_ssn (p_in varchar2) return varchar2; end; / create or replace package body pkg_mask as function fn_mask_ssn (p_in varchar2) return varchar2 is begin return lpad ( round(dbms_random.value (001000000,999999999)), 9,0); end; end; /
该函数接受一个 varchar 参数,返回 9 个字符。我们将使用该函数来屏蔽 SSN。ACCOUNTS 表如下所示。
SQL> select * from accounts; ACC_NO ACC_NAME ACC_SSN ---------- ------------------------------ --------- 1 John Smith 123456789 2 Jane Doe 234567890
您要屏蔽 ACC_SSN 列,它是帐户持有者的 SSN。您使用 Data Pump 导出该表。导出时,您使用新参数 remap_data 屏蔽导出转储文件中的数据。
$ expdp scott/tiger tables=scott.accounts dumpfile= accounts.dmp directory=tmp_dirremap_data=accounts.acc_ssn:pkg_mask.fn_mask_ssn
该参数将重映射函数 fn_mask_ssn 中生成的值放到 pkg_mask 程序包中。注意该参数的格式。它遵循以下模式:
[<SchemaName>.]<TableName>.<ColumnName>:[<SchemaName>.]<PackageName>.<FunctionName>
现在,您可以将表导入到非生产数据库中。导入完成后,如果您检查该表的值:
SQL> select * from accounts; ACC_NO ACC_NAME ACC_SSN ---------- ------------------------------ --------- 1 John Smith 645270861 2 Jane Doe 538996590
注意各个 ACC_SSN 值是如何变化的。这些值是由我们在前面编写并储存在导出转储文件中的重映射函数 pkg_mask.fn_mask_ssn 生成的。当我们导入时,该值就被导入了。
如果您已经导出了表但没有使用该 remap_data 参数,则转储文件中的值已经是准确值。您可以在导入时屏蔽这些值,仍然使用这个神奇的参数。
$ impdp scott/tiger dumpfile=accounts.dmp remap_data= accounts.acc_ssn:pkg_mask.fn_mask_ssn directory=tmp_dir tables=accounts
我们在此处使用了一个随机值函数,我们还可以使用任何其他逻辑。例如,假设要求将 SSN 除后四位之外的所有数字全部用 X 代替。这也很简单。您只需编写一个类似于下面的函数:
create or replace package pkg_mask as function fn_mask_ssn (p_in varchar2) return varchar2; end; / create or replace package body pkg_mask as function fn_mask_ssn (p_in varchar2) return varchar2 is begin return 'XXXXX'|| substr (p_in,6,4); end; end; /
打包的函数也是可重用的;它可用于对任何列的任何导入中。屏蔽数据的方法是无限的 — 只要您能创建一个可返回一个值的函数,您就可以用它来屏蔽该值。这就减少了您的开发和维护任务,同时使得从生产数据库向非生产数据库进行安全的数据刷新成为可能。
其他注意事项
在以前的版本中,大多数安全操作是通过一个名叫 Oracle Security Manager 的工具进行的。在 Oracle Database 11g 中,Oracle Enterprise Manager 包括用于执行这些任务的所有工具。下面是 Database 主页上 Server 选项卡的屏幕截图。注意右下方名为 Security 的部分。
![图 1](https://www.oracle.com/ocom/groups/public/@otn/documents/digitalasset/109106.jpg)
该部分包含到所有与安全性有关的工具的超链接,这些工具用于用户、配置文件和角色管理等过程。您现在还可以找到向导来启动虚拟专用数据库和 Oracle Label Security,或者在 Enterprise Manager 屏幕中创建并管理应用程序上下文。
默认确定安全设置风格(仅限第 2 版)
在 11g 第 1 版中,安装数据库软件时,您将看到一条选择提示:您希望保留 10g 风格的安全性还是使用新风格的安全性。如果您选择了后者,数据库创建时将使用 11g 特有的特性,例如区分大小写的口令、口令策略、用户配置文件等。
在第 2 版中,您不再需要选择;数据库创建时将自动使用 11g 风格的特性。这意味着,数据库在创建时将使用区分大小写的口令、内置的口令验证功能以及强制实施这种口令验证功能的用户配置文件。这应该是一项受欢迎的更改,因为它能提高数据库安全性。
如果您仍然希望留出更多时间来迁移用户和应用程序以使用新的区分大小写特性,又应该如何?您可以通过执行以下 SQL 命令来临时禁用区分大小写的检查:
SQL> alter system set sec_case_sensitive_logon = false; System altered.
审计线索清除(仅限第 2 版)
通过记录谁 做了什么,审计可提供对数据库安全性的重要洞察。根据各种数据库参数设置和审计类型记录线索。例如,数据库标准审计写入一个名为 AUD$ 的表,细粒度审计 (FGA) 写入 FGA_LOG$ 表,两个表均处于 SYS 模式。如果数据库审计设置为 OS 或 XML,常规文件将写入指定目录。
审计线索具有其他任何类型的数据都不具备的与众不同的特性:它将随活动的增加而增长。只有在插入新记录时,用户数据才会增长,在许多数据库中,常规清除后用户数据的整体大小基本不变。另一方面,审计线索将不断增长,即便在用户只是选择数据时。
就像其他不断增长的任何内容一样,您要不时地删减线索。迄今为止,唯一受支持的删减方法就是停止审计并截断表。11g 第 2 版中提供了一个新的程序包 dbms_audit_mgmt,其中所包含的 API 可用于管理审计线索中的记录。它允许您手动清除审计跟踪记录,或者安排一个定期运行的计划作业来进行清除。
在开始之前,您必须先初始化清除过程。以下 SQL 代码将初始化此过程,每隔 7*24 小时(即一周)执行一次清除。请注意,这并不意味着您必须每周清除一次。如果需要的话,您也可以执行即席清理。
begin dbms_audit_mgmt.init_cleanup( audit_trail_type => dbms_audit_mgmt.audit_trail_all, default_cleanup_interval => 7*24 ); end; /
接下来,为了执行实际的清除,您必须执行一个打包的过程 dbms_audit_mgmt.clean_audit_trail()。
begin dbms_audit_mgmt.clean_audit_trail( audit_trail_type => dbms_audit_mgmt.audit_trail_all ); end; /
请注意:这将执行一个 DELETE 操作,因此将存在大量重做和撤销。初始清除完成后,您可能希望设置一个自动化过程来定期执行此任务。您将需要创建一个 DBMS Scheduler 作业,如下所示。该作业将每周运行一次。
begin dbms_audit_mgmt.create_purge_job ( audit_trail_type => dbms_audit_mgmt.audit_trail_all, audit_trail_purge_interval => 7*24, audit_trail_purge_name => 'all_audit_trails_job' ); end; /
请注意,参数 audit_trail_type 设置为 dbms_audit_mgmt.audit_trail_all,这表示所有审计线索:AUD$、SYS Audit、FGA 审计线索、OS 文件和 XML 文件。您还可以具体指定这些线索。
如果线索过大又会如何?由于上述 SQL 执行一项 DELETE 操作,因此不适于大批量删除操作。您可能需要将其拆分为小块。要将其拆分为每 100,000 条记录提交一次,应为此类线索设置一个属性。对于数据库审计线索,您必须进行如下设置:
begin dbms_audit_mgmt.set_audit_trail_property( audit_trail_type => dbms_audit_mgmt.audit_trail_aud_std, audit_trail_property => dbms_audit_mgmt.db_delete_batch_size, audit_trail_property_value => 100000); end; /
对于 FGA:
begin dbms_audit_mgmt.set_audit_trail_property( audit_trail_type => dbms_audit_mgmt.audit_trail_fga_std, audit_trail_property => dbms_audit_mgmt.db_delete_batch_size, audit_trail_property_value => 100000); end; /
请注意参数 audit_trail_type 的变化。该参数因相关联的原因接受以下值:
参数 |
目的:删除: |
dbms_audit_mgmt.audit_trail_aud_std |
数据库中的常规 AUD$ 审计线索 |
dbms_audit_mgmt.audit_trail_fga_std |
FGA_LOG$ 表,用于细粒度审计 |
dbms_audit_mgmt.audit_trail_db_std |
常规审计线索和 FGA 审计线索 |
dbms_audit_mgmt.audit_trail_os |
OS 文件审计线索 |
dbms_audit_mgmt.audit_trail_xml |
XML 审计线索文件 |
dbms_audit_mgmt.audit_trail_files |
OS 和 XML 审计线索 |
dbms_audit_mgmt.audit_trail_all |
以上全部 |
进行了这些设置之后,显然您需要对它们进行管理。要检查审计线索清除作业,请执行:
SQL> select * from DBA_AUDIT_MGMT_CLEANUP_JOBS 2 / JOB_NAME ------------------------------------- JOB_STAT AUDIT_TRAIL -------- ---------------------------- JOB_FREQUENCY ------------------------------------- ALL_AUDIT_TRAILS_JOB ENABLED ALL AUDIT TRAILS FREQ=HOURLY;INTERVAL=168
这将告知您哪些作业处于活动状态。要显示审计线索清除过程的各种参数,例如,最大大小、默认表空间等等,您可以查询一个名为 DBA_AUDIT_MGMT_CONFIG_PARAMS 的视图。
SQL> select * from dba_audit_mgmt_config_params;
PARAMETER_NAME PARAMETER_VALUE AUDIT_TRAIL
------------------------------ --------------- ------------------------------
DB AUDIT TABLESPACE AUDIT_TS STANDARD AUDIT TRAIL
DB AUDIT TABLESPACE AUDIT_TS FGA AUDIT TRAIL
AUDIT FILE MAX SIZE 10000 OS AUDIT TRAIL
AUDIT FILE MAX SIZE 10000 XML AUDIT TRAIL
AUDIT FILE MAX AGE 5 OS AUDIT TRAIL
AUDIT FILE MAX AGE 5 XML AUDIT TRAIL
DB AUDIT CLEAN BATCH SIZE 10000 STANDARD AUDIT TRAIL
DB AUDIT CLEAN BATCH SIZE 10000 FGA AUDIT TRAIL
OS FILE CLEAN BATCH SIZE 1000 OS AUDIT TRAIL
OS FILE CLEAN BATCH SIZE 1000 XML AUDIT TRAIL
DEFAULT CLEAN UP INTERVAL 168 STANDARD AUDIT TRAIL
DEFAULT CLEAN UP INTERVAL 168 FGA AUDIT TRAIL
DEFAULT CLEAN UP INTERVAL 168 OS AUDIT TRAIL
DEFAULT CLEAN UP INTERVAL 168 XML AUDIT TRAIL
审计线索的清除是一项至关重要、必不可少的任务。现在有了一个专门实现此目标的工具。
将审计线索重定位到其他位置(仅限第 2 版)
适用于任何版本的 Oracle Database 的一个关键事实是:审计线索将不断增长。它基于活动,而非数据更改量。默认情况下,数据库审计线索(AUD$ 表)位于 SYSTEM 表空间中。如果该表空间被填满,将导致严重的后果。位于 SYSAUX 表空间中的 FGA_LOG$ 也存在相同的担忧。如果您能将这两个表从 SYSTEM 表空间移至其各自的表空间中,即可解决 SYSTEM 表空间不断扩张的问题。但在先前版本的数据库中,将审计线索移至其他表空间是不可接受的做法。
在 11g 第 2 版中,您可以将部分或全部审计线索移至各自的表空间中。当然,首先必须创建表空间:
create tablespace audit_ts datafile '+AUDITDG' size 1000M segment space management auto /
您必须非常谨慎地考虑一种可能性:打开数据库时,这个表空间将需要联机。如果表空间在数据库打开后脱机,而您执行了一项可审计的操作,则将收到 ORA-02002 错误。当然,解决办法是关闭数据库的审计,然后重新启动。显然,您需要将审计表空间放在一个可靠的磁盘位置上,可能还需要通过镜像提供保护。
随后使用一个特殊的程序包将 AUD$ 表移至新的表空间中:
begin dbms_audit_mgmt.set_audit_trail_location( audit_trail_type => dbms_audit_mgmt.audit_trail_aud_std, audit_trail_location_value => 'AUDIT_TS'); end; /
要将 FGA_LOG$ 表移至此表空间中:
begin dbms_audit_mgmt.set_audit_trail_location( audit_trail_type => dbms_audit_mgmt.audit_trail_fga_std, audit_trail_location_value => 'AUDIT_TS'); end; /
以上命令将表移至新的表空间中,然后释放 system 和 sysaux 表空间。初次构建数据库时建议采用这种做法。
真正全局应用程序上下文(仅限第 2 版)
您通常会在希望跨会话边界共享值时使用全局应用程序上下文,也就是说,您可以在一个会话中设置值,然后在另一个会话中进行引用。通过全局程序包变量也可实现相同目标,但全局变量不安全,任何位置的任何用户都可对其进行设置。应用程序上下文允许有选择性地设置值,仅利用其“受信任的”过程,从而使之高度安全。
然而,在先前版本的 Oracle Database 中,“全局性”仅限于单一实例。在 RAC 数据库中,您可以看到会话之间的应用程序上下文值,但前提是会话均处于同一实例中。
在 11g 第 2 版中,您可以在一个实例中设置一个全局应用程序上下文,然后在另一个实例中进行引用。这就使全局应用程序上下文实现了真正的全局性 — 无论是在哪个实例中设置的,都能在整个数据库中实现全局性。
这个新特性使您能够非常轻松地进行安全的应用程序开发。在实例之间使用这项特性的方法如下:
创建一个上下文,假设其名称为 gctx。
SQL> create context gctx 2 using set_gctx 3 accessed globally;
Context created.
现在,创建该上下文的受信任过程。
SQL> create or replace procedure set_gctx 2 ( 3 p_attr1_val varchar2 4 ) as 5 begin 6 dbms_session.set_context ('GCTX','ATTR1', p_attr1_val); 7 end; 8 / Procedure created.
受信任程序包的角色极为重要。设置上下文属性的唯一方法就是调用其受信任的程序包,别无他法。为了进行演示,我们在实例 1 中检查 ATTR1 属性的值:
SQL> select sys_context('GCTX','ATTR1') 2 from dual; SYS_CONTEXT('GCTX','ATTR1') ---------------------------
值未设置。现在将该值设为“Attrib1_Value”。
SQL> exec set_gctx('Attrib1_Value') PL/SQL procedure successfully completed.
现在,如果再次在实例 1 中检查该值:
SQL> select sys_context('GCTX','ATTR1') 2 from dual; SYS_CONTEXT('GCTX','ATTR1') --------------------------- Attrib1_Value
可以看到该值是如何设置的。现在,通过另一个实例(实例 2)检查该值:
SQL> select sys_context('GCTX','ATTR1') 2 from dual; SYS_CONTEXT('GCTX','ATTR1') --------------------------- Attrib1_Value
返回了相同的值。现在,我们在这个实例(实例 2)中更改该属性的值,并检查更改后的值是否跨所有实例可见。首先检查实例:
SQL> select instance_name from v$instance; INSTANCE_NAME ---------------- DB112H2
这是实例 2,名为 DB112H2。设置上下文值,并在此实例中检查该值:
SQL> exec set_gctx('Attrib1_NewValue') PL/SQL procedure successfully completed. SQL> select sys_context('GCTX','ATTR1') 2 from dual; SYS_CONTEXT('GCTX','ATTR1') --------------------------- Attrib1_NewValue
现在连接到另一个实例,并检查该值。
SQL> select instance_name from v$instance; INSTANCE_NAME ---------------- DB112H2 SQL> select sys_context('GCTX','ATTR1') 2 from dual; SYS_CONTEXT('GCTX','ATTR1') --------------------------- Attrib1_NewValue
如您所见,这个属性的值不仅在该实例中可见,而且在另一个实例中也是可见的。现在,您可以在整个数据库中安全地使用这个值。
监听器口令已弃用(仅限第 2 版)
还记得监听器的口令设置吗?在 Oracle Database 10g 之前,任何称职的安全性措施都要求必须设置此口令。在 10g 中,该口令不再是强制要求。对 Oracle 软件所有者而言,监听器口令并非必需(即便设置,也可忽略)。仍然可以为 Oracle 软件所有者以外的任何用户设置口令。
然而,其他用户几乎不需要或者完全不需要启动监听器。最有可能启动监听器的就是 Oracle 用户。因此,口令的存在价值极低。Oracle 的这个版本弃用了口令。
目录对象的细粒度安全性(仅限第 2 版)
在这方面,实际上有两项主要增强。我们将分别进行介绍。
首先,提供了一种新权限:目录对象的 execute 权限。我相信您了解外部表,外部表使您能够将平面文件以表的形式显示给 Oracle 数据库用户。当您获得一个压缩文件的时候,怎么办?您总是可以先解压缩这个文件,然后再从外部表中选取。这是一个额外的步骤。
11g 第 2 版消除了这个额外的步骤。它允许您针对加载文件或使用外部表提供一个预处理器选项。这些预处理器像解压缩程序或某些用户私下编写的动态转换加载数据的程序一样简单。这个预处理器实用程序实际上是一个操作系统可执行文件。现在的问题是,您打算将它放在什么地方?
放在哪里并不像如何防止其未经授权的使用那么重要。如果这是一个解压缩程序,那么问题可能不大,但如果这个可执行程序执行的是专有业务逻辑,情况又会如何?您不能允许除了加载或选择数据的用户之外的任何用户访问此实用程序。您可以通过对预处理器所在的目录对象利用新权限 execute 来保护它。您可以通过执行以下 SQL 命令将此权限授予适当的用户:
grant execute, read on directory utility_dir to scott;
现在,SCOTT 可以执行 utility_dir 目录中的程序。没有权限的其他任何人都不能执行这些程序。
现在,让我们来看看与之密切相关的第二个特性。由于这个目录实用程序具有所有这些敏感的程序,因此您可能必须确定执行这些程序的所有用户。一个新的审计选项使您能够捕获目录中程序的执行记录。审计目录中程序执行情况的方法如下:
audit execute on directory utility_dir by session;
执行此命令之后,该目录中实用程序的执行即被审计。这使您能够跟踪使用实用程序的所有用户。这不仅建立了责任跟踪,还提供了确定被授权者是否应具有此权限的基础。
新增的审计选项(仅限第 2 版)
审计使您能了解谁正在做什么。您可以选择审计特定语句,如 INSERT、DELETE 等。如果您希望审计用户发出的所有语句,无论其类型如何,该怎么办?
您确实可以利用一个选项(即 AUDIT ALL 命令)来记录用户执行的所有操作。但问题在于,它记录的是所有操作 而不是语句,无论用户是否直接执行了语句。因此,您最终可能会得到大量审计线索条目,极难管理。在 11g 第 2 版中,AUDIT ALL STATEMENTS 语句允许您只审计用户直接执行的语句。
SQL> audit all statements; Audit succeeded.
非常重要的一点是:切记它只记录顶级 SQL 语句 — 用户直接执行的那些语句,而非过程代码中包含的语句。例如,如果您执行:
delete table1; delete table2;
将对这两条语句进行审计。但如果您使用了一个 PL/SQL 存储过程:
create or replace procedure cleanup as begin delete table1; delete table2; end; /
并执行了存储过程 begin cleanup; end;,则唯一得到审计的语句就是存储过程的执行,不包含其中的 delete 语句。如果这是您希望的结果,那么没有任何问题;否则就会造成无相关审计线索的后果。这个新选项使您可以有选择地审计用户和应用程序的活动。
当前会话审计(仅限第 2 版)
您是否遇到过类似以下的情况?
您有一个存储过程,它调用大量其他过程,而这些过程又调用其他过程和函数,并访问表和视图。在访问语句有如迷宫般复杂的结构中,某些语句因不存在的权限或者某个表的名称拼写错误而失败。例如,某处执行了一条类似于“select * from incorrect_table”的语句,因为没有名称为“incorrect_table”的表而失败,提示 ORA-942 错误。
SQL> select * from incorrect_table; select * from incorrect_table * ERROR at line 1: ORA-00942: table or view does not exist
问题在于,在复杂的应用程序代码中,您可能无法准确找到是哪条 SQL 语句导致了问题。您所具有的全部信息可能就是错误代码 942。这使查明错误原因的任务变得极为困难。
如何才能找到实际的语句?一个选择是通过 10046 事件跟踪会话,然后查看所得到的跟踪文件 — 这个方法可行但绝不简单,特别是在跟踪文件非常大的情况下。您可以执行 AUDIT ALL 语句来开启所有活动上的审计,但这将生成大量审计线索,可能无法管理,同时也会影响系统性能。在 11g 第 2 版中,新的审计选项 IN SESSION CURRENT 使您能够将审计范围仅限于当前会话。可通过执行以下命令启用对当前会话中所有活动的审计:
SQL> audit all in session current;
现在,无论整体审计设置如何,都将仅审计当前会话中的所有活动。为了进一步简化此过程,在开始运行应用程序代码之前,先获取会话的审计 sessionid(注意:获取审计 sessionid,不同于 SID):
SQL> select audsid from v$session 2 where sid = (select sid from v$mystat where rownum < 2);
AUDSID ---------- 183324
然后,在该会话中执行您的应用程序。这将为该会话中发生的所有活动生成审计线索。随后,您可以查看审计线索,识别具体是哪条语句失败并引发了 Oracle 错误:
SQL> select timestamp, owner, obj_name, action_name, returncode, sql_text 2 from dba_audit_trail where sessionid = 183324 3 and returncode > 0 4 / TIMESTAMP OWNER --------- ------------------------------ OBJ_NAME --------------------------------------- ACTION_NAME RETURNCODE ---------------------------- ---------- SQL_TEXT --------------------------------------- 03-OCT-09 ARUP INCORRECT_TABLE SELECT 942 select * from incorrect_table
该条目清楚地显示了导致问题的语句以及确切的错误 — 942(RETURNCODE 列)。对象名称 INCORRECT_TABLE 无效,因此会话出现 ORA-942 错误。随后,您可以在应用程序代码中搜索此语句,找到它的出处。
可通过登录后触发器设置 AUDIT CURRENT SESSION 语句,以便在会话连接后执行此语句。
您并不需要 在运行代码之前获得审计 sessionid。您始终可以在应用程序代码运行时通过 AUDSID 列的 V$SESSION 视图获得审计 sessionid。
select audsid from v$session where sid = <SID>
上述示例非常简单。您可以通过不同的方式找到准确的语句,只要它在审计线索中。
统一的万能加密密钥(仅限第 2 版)
在先前版本的透明数据加密 (TDE) 特性中,用于列级 TDE(10g 第 2 版中引入)和表空间级 TDE(11g 第 1 版中引入)的万能密钥是不同的。在 11g 第 2 版中,它们通过统一万能加密密钥变成一样的。
这带来了两大特有优势:
-
如果加密密钥更改,则将针对两类 TDE 同时实现。许多安全法规和法令(如 PCI)都要求不时地更改加密密钥只需一次即可完成所有类型的更改。
-
万能加密密钥可以存储在硬件安全模块中,适用于这两类 TDE。
在表空间级的 TDE 中,加密密钥存储在表空间数据文件的头中(当然,是加密的)。某些安全性法规也要求轮换 TDE 密钥。尽管表空间级密钥不能更改,但在这个版本中,用于对这些密钥进行加密的万能密钥可以更改。
要更改表空间级的 TDE 万能密钥,请执行以下语句:
alter system set encryption key identified by "newpass”;
说到加密,表空间级 TDE 同样可用于 Oracle 数据库云服务器。由于数据库云服务器的工作方式是预先筛选存储单元中的结果(从而减少数据库节点需要处理的数据),因此存在将密钥将密钥置入这些存储单元的技术挑战。如今,这已经不成问题,密钥将自动复制到存储单元中。存储单元在执行数据筛选时有权访问密钥,从而可以在筛选之前解密数据。
仍然回到刚才主题,同样提供了对 Oracle RAC 的强大支持。万能加密密钥存储在一个被称作加密钱夹的位置(或者简称为“钱夹”)。必须先打开钱夹,然后表空间才能进行加密和解密。要打开钱夹,必须执行:
alter system set encryption wallet open identified by "pooh";
本例中的口令是“pooh”。由于这是一条 ALTER SYSTEM 命令,在先前版本的 Oracle 中,它仅适用于这个特定的实例。因此,如果您有一个 RAC 数据库,就必须在所有实例上执行此命令。除了浪费时间之外,健忘的 DBA 或安全管理员也容易发生疏漏。
在这个版本中,此操作将自动应用于所有 RAC 实例。无需分别在所有实例上执行。这种行为也适用于钱夹关闭和重新生成密钥操作。
按会话审计的变动(仅限第 2 版)
审计对某个对象的访问时,有两种不同的方法:按会话和按访问。如果一个用户访问了对象两次,则“按会话”审计只会记录一次,而“按访问”则记录两次。例如,假设您希望按会话审计 CREDIT_CARDS 表上的选择,则需要执行此 SQL 命令:
audit select on credit_cards by session;
在 11g 第 2 版之前的版本中,应该仅有一条会话记录,如下所示:
USERNAME ACTION_NAME TIMESTAMP SES_ACTIONS ---------- ---------------------------- --------- ------------------- ARUP SESSION REC 11-JUN-10 ---------S------
SES_ACTIONS 列记录了所执行的操作。字母“S”代表“成功”,而这个字母的位置表示操作。上面显示的位置针对 SELECT 语句。这表明用户成功执行了未知次数的选择操作。通过审计线索无法了解访问的次数和表名称。
如果用户执行了一些其他操作(如 DELETE 或 UPDATE),SES_ACTIONS 列中值的对应标志应已设置。ACTION_NAME 应显示为“SESSION REC”,表示该记录是活动汇总的整合。
这种审计的局限性显而易见 — 您始终无法了解访问的频率,只知道至少存在一次访问这样的事实。要记录每次执行的访问,您必须“按访问”审计:
SQL> audit select on ccmaster.credit_cards by access;
Audit succeeded.
此后,将针对每次访问显示一条审计记录:
USERNAME ACTION_NAME TIMESTAMP SES_ACTIONS ---------- ---------------------------- --------- ------------------- ARUP SELECT 11-JUN-10
请注意,ACTION_NAME 列现在显示的是所执行的命令。如果此命令在一个会话中出现 10 次,则线索中将有 10 行,而非一行。尽管这能生成更有用的信息,但也会填充更多审计线索。“按会话”通过仅为每个会话生成一条记录而节约了空间。
在 11g 第 2 版中,这种行为发生了变化。现在,即便在“按会话”审计中,也将为每个活动保存一条记录。在所有记录中,都将使用“---------S-----”值填充 SES_ACTIONS,ACTION_NAME 列将仍显示 ESSION REC,但将包含许多条目 — 每个条目对应一次访问。
这对您来说意味着什么?按会话审计的重点在于将审计线索中的活动限制为每个会话一条记录。然而,如您所见,在 11g 第 2 版中,这是不可能实现的,审计记录将按照访问生成。因此,为对象利用会话审计将不再具有实际优势。您应转为使用按访问的审计机制,这将产生更好的效果。
第 2 版其他更新
这是一个 IPv6 风格地址的时代,Oracle 已经跟上了这股潮流。在 11g 第 2 版中,除了原有的 IPv4 风格地址之外,您还可以使用 IPv6 风格的地址。这适用于引用了 IP 地址的程序包。清单如下:
-
DBMS_NETWORK_ACL_ADMIN
-
DBMS_NETWORK_ACL_UTILTIY
-
UTL_TCP、UTL_SMTP
-
UTL_MAIL
-
UTL_HTTP
-
UTL_INADDR
让我们来看一个示例。在上面,您了解了如何通过将访问仅限于特定的一组用户来保护特定的程序包。要将访问限制为特定主机,您需要使用:
begin dbms_network_acl_admin.assign_acl ( acl => 'utlpkg.xml', host => '10.14.104.253', lower_port => 22, upper_port => 55); end;
现在,除了这种格式的 IP 地址之外,您还可以使用 IPv6 地址。新格式如下:
begin dbms_network_acl_admin.assign_acl ( acl => 'utlpkg.xml', host => 'fe80::219:21ff:febb:9aa5', lower_port => 22, upper_port => 55); end;
请注意,对应于主机参数的 IPv6 风格地址。要获知 IPv6 地址,运行 ifconfig 命令即可。
oracle@oradba1 /# /sbin/ifconfig -a eth0 Link encap:Ethernet HWaddr 00:19:21:BB:9A:A5 inet addr:10.14.104.253 Bcast:10.14.107.255 Mask:255.255.252.0 inet6 addr: fe80::219:21ff:febb:9aa5/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:82397559 errors:0 dropped:0 overruns:0 frame:0 TX packets:25308057 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:4122552682 (3.8 GiB) TX bytes:1310294427 (1.2 GiB) Interrupt:209 Base address:0xb800
inet6 addr 的值(以粗体显示)显示了 IPv6 地址。
此外:要提供扩展的活动数据,例如已执行的 SQL 语句,过去您可以使用 db_extended 作为 audit_trail 的值。在这个版本中,这个值已弃用。但不要着急,这种功能并未删除。要使用扩展的审计,您只需使用新格式:
audit_trail = db,extended
返回系列目录