4.1 实现细粒度审计 背景 您可能已经注意到,本文到现在还没有涉及到作为审计机制的触发器。为什么? 因为使用触发器,就意味着 再次 连续地执行 SQL,这增加了整个执行时间。 对生产系统来说,该开销几乎是不可以接受的。
因为细粒度审计 (FGA) 有最小的性能开销,所以在这里它是一个优秀的解决方案。 如果您已经熟悉 FGA,请跳过这一部分,直接阅读策略部分。
Oracle9i 数据库中引入了 FGA 特性,当用户对表进行选择和更改操作时,它将记录一个审计线索。 因这一特性是唯一可记录选择活动的方法,所以它具有里程碑式的意义。 SELECT 语句上的常规审计功能仅仅记录 谁 针对对象发出了语句,但是不记录发送了 什么 语句。
除开详细信息(例如用户名、终端,以及查询时间)之外,FGA 还记录执行过的 SQL 语句和时间实例的 SCN 数量。 当您使用闪回查询重建数据之后,你不仅看到用户提交的语句,还有用户得到结果值。 在 Oracle 数据库 10g 第 1 版对该功能进行了扩展,涵盖其它 DML 语句,例如 插入、更新,以及 删除。
下面提供了一个小示例: 假设模式 BANK 有一个 ACCOUNTS 表。 Name Null?类型
---------------- -------- ------------
ACC_NO NOT NULL NUMBER
CUST_ID NOT NULL NUMBER
BALANCE NUMBER(15,2)
为了对其进行审计,您将需要使用提供的程序包 DBMS_FGA 定义相关 FGA 策略。 begin
dbms_fga.add_policy (
object_schema=>'BANK',
object_name => 'EMP',
policy_name => 'ACCOUNTS_ACCESS',
);
end;
以上代码执行完毕之后,将在 ACCOUNTS 表启用 FGA。 也就是说,没有必要对任何初始化参数进行更改,或对该数据库进行回弹。
执行以上代码时,它们在该表上使用共享锁定,因此您可以在线执行。 现在,如果一个名为 ARUP 的用户提交以下语句,对该表中进行选择操作: select * from bank.accounts;
该行动立即记录在称为 FGA Audit Trail的审计追踪中。 您可以使用以下语句对其进行检查: select timestamp,
db_user,
os_user,
object_schema,
object_name,
sql_text
from dba_fga_audit_trail;
TIMESTAMP DB_USER OS_USER OBJECT_ OBJECT_N SQL_TEXT
--------- ------- ------- ------- -------- ---------------------------
08-FEB-06 ARUP arup BANK ACCOUNTS select * from bank.accounts
该视图也显示许多其它列。
您可以使用多种方法对 FGA 进行配置。 例如,如果您希望记录用户选择 BALANCE 列且余额超过 20,000 时的操作,你可以另外添加一些参数,同时定义 FGA 策略如下: begin
dbms_fga.add_policy (
object_schema =>'BANK',
object_name => 'EMP',
policy_name => 'ACCOUNTS_ACCESS',
audit_column => 'BALANCE',
audit_condition => 'BALANCE >= 20000'
);
end;
角色划分
数据安全中最有争议的问题之一是角色划分。 为了管理数据库,数据库管理员必须拥有某些权限,通常会赋予其 SYSDBA 角色,甚至是 DBA 角色。 然而,这一角色还有其它的一些权力:例如给别人授予权限,从任何表中选择所有数据。 该超用户权限与绝大多数法规相冲突,例如 Sarbanes-Oxley 和 GLBA,因为该权限允许个人拥有太多权力。
其实,DBA 角色是个与物理数据库相关的纯粹技术角色,一般情况下把它分配给一组用户。 如果同样的人群也能够查看并更改任何用户数据,那么这种情况就会产生数据漏洞的严重潜在安全性风险。 当数据库管理员可以删除任何数据,甚至审计线索时,责任可查性将成为问题。 然而,要实现合规性,需要明确划分职责和权限。 因此,管理物理数据库的权限不应该包括查询或修改用户数据权。
传统上,Oracle 数据库不支持这种划分。 所以,在 2006 年 Oracle 宣布了两种革新性的工具(写这篇文章时它们都处于实验阶段)。 首先,Oracle Database Vault (Oracle 数据库 10g 第 2 个企业版的一个选项)通过创建权限“域”实现权限分离。 例如,DBA 不再有无限权利 查询和修改任何表。 相反,DBA 的权限将被限制到一个具体的权限范围,即权限域。 因此,Database Vault 抛弃能删除所有跟踪的万能超级用户的理念。相似地,独立产品 Oracle Audit Vault 提供了一个安全的审计工具,该工具自成一体,位于 DBA 或者应用程序管理人员控制区域外。只有安全管理员可以控制审计线索。 可以使用这两种工具将这里的三种相关角色——管理物理数据库、管理对象权限、管理审计线索——完全分开。达到所有合规性规定的要求。 | FGA 的另一个特性就是当条件满足时,FGA 还能在审计线索中进行记录之外调用存储过程。 在有额外处理(例如发送电子邮件)的情形,这一特性的效果极其显著。 这样的 SP 被称为 FGA 策略的 处理模块。 请记住,选择语句可以激活 FGA,也可以激活这些处理器模块。 在某种意义上说,这使处理器模块“选择触发器”语句。
Oracle 数据库 10g 也介绍更多的 FGA 增强特性,例如这两个值得关注的特性:
绑定变量。 使用 FGA,您可以通过在 DBMS_FGA.ADD_POLICY 过程中使用参数来捕获语句中的绑定变量。 audit_trail => DB_EXTENDED
然后您可以将它们放到数据库初始化文件中,这样 FGA 可以一直对它进行记录。
相关列。 请看以下两个语句: select balance from accounts where account_no = 9995;
select sum(balance) from accounts;
很明显,第一条语句请求了具体的敏感信息(基于此信息可识别客户),您可能想编辑该信息。 第二条语句危险系数较低,用户使用该语句找不到关于该客户的任何具体的敏感数据。 按照您的安全策略,您可能希望记录第一条语句,不记录第二条语句。 这样有助于限制该线索的大小。
要完成这一任务,您可以使用另外一个参数 audit_column_opts => DBMS_FGA.ALL_COLUMNS,同时定义策略如下: begin
dbms_fga.add_policy (
object_schema => 'ANANDA',
object_name => 'EMP',
policy_name => 'ACCOUNTS_ACCESS',
audit_column => 'BALANCE',
audit_condition => 'BALANCE >= 20000'
statement_types => 'SELECT');
audit_column_opts => DBMS_FGA.ALL_COLUMNS
);
end;
默认情况下为 DBMS_FGA.ANY_COLUMNS,无论 哪个 列被选择,它都能触发审计线索。
到这里我们只是精浅地涉及了 FGA。 要对 FGA 有一个全面的了解,获取更多的的示例,请参阅我的系列文章“对实际问题进行细粒度审计。”,分为三章。 " 同时我在 Oracle PL/SQL for DBAs (2005, O'Reilly Media) 一书中也对此也进行详细的讨论。
策略 和常规审计相比,FGA 的最大优点是它不需要任何特定的初始化参数,所有它不需要数据库回弹。 您可以按需在对象上启用或禁用 FGA 策略。
您需要查找具体的敏感列和且有选择地查找这些列中的敏感值。 首先,您需要制定审计策略。 下面是一个典型的策略示例:
在 SALARIES 表中:
- 如果某个用户 仅 选择 SALARY 和 BONUS 列时,您可以进行审计。 如果选择了其它的列,则不进行审计。
- 甚至当用户仅选择一列(例如 SALARY 列),且无需任何可识别信息(例如 EMPNO)时,也进行审计。
- 无论什么时候,只要用户从 EMPNOS 低于 1000(这些 EMPNO 用于管理人员)的表中选择任何列,仍然审计。
- 如果选择了用户 SAP_PAYROLL_APP 项,则不要审计。 这是工资处理应用程序使用的用户 id, 对它进行审计将会生成大量的数据,并填满线索表。
- 人力资源助手 Monica 和 Adam 定期检查和调整工资在 1,000 以下的低等级雇员的工资。您不应该审计工资在 1,000 以下的选择语句。
- 除开审计,请您执行一个存储过程 enqueue_message,该过程向负责安全的官员发送电子邮件。
把该策略记住后,您应该创建两个不同的 FGA 策略。
首先,针对 EMPNO >= 1000、SALARY 列和 BONUS 列的通用策略。 begin
dbms_fga.add_policy (
object_schema => 'ACCMAN',
object_name => 'EMP',
policy_name => 'EMP_SEL_POL',
audit_column => 'SALARY, BONUS',
statement_types => 'SELECT');
audit_option => 'EMPNO >= 1000 and USER NOT IN(''SAP_PAYROLL_APP'', ''MONICA'', ''ADAM'')',
handler_module => 'ENQUEUE_MESSAGE'
);
end;
然后,针对 EMPNO < 1,000 创建用于全部列的策略。 begin
dbms_fga.add_policy (
object_schema => 'ACCMAN',
object_name => 'EMP',
policy_name => 'EMP_SEL_POL',
statement_types => 'SELECT');
audit_option => 'EMPNO < 1000',
handler_module => 'ENQUEUE_MESSAGE'
);
end;
第三,给 MONICA 和 ADAM 添加特殊的策略。 begin
dbms_fga.add_policy (
object_schema => 'ACCMAN',
object_name => 'EMP',
policy_name => 'EMP_SEL_POL',
audit_column => 'SALARY, BONUS',
statement_types => 'SELECT');
audit_option => 'EMPNO >= 1000 AND SAL <= 1000 and USER IN
(''MONICA'', ''ADAM'') AND USER != ''SAP_PAYROLL_APP''',
handler_module => 'ENQUEUE_MESSAGE'
);
end;
正如您所看到的,audit_option 中的条件之间是相互排斥的,所以当用户尝试执行 SELECT 语句时,只有一个策略是有效的,也只有一条记录会被写入。
您可以使用该策略构建 FGA 策略集。 然后,您可以根据需要自由地启用或禁止策略,这不会影响操作。
问题 主要有以下四个问题:
- 当选择做出之后如果处理器模块(如果定义了)抛出错误,将会在 Oracle 不同版本中引起不同的行为:
- 在 Oracle9i 数据库中,处理器模块 以无提示的方式 停止对该行进行检索,不会报错。 因此,如果有 100 行,其中 4 行满足了审计条件,处理器模块运行四次,每次都会失败。 该查询将仅仅返回 96 行,而不报告任何错误,您将绝不会知道事情已经发生了。 很显然,这种做法会产生不精确的结果。
- 在 Oracle Database 10g 第 1 版中,处理器模块将忽略处理器模块中的错误,按照预期检索所有 100 行。
- 在 Oracle Database 10g 第 2 版中,处理器模块将报告执行查询的用户会话方面的错误,而不返回任何行,甚至不返回那些不满足审计条件而没有执行处理器函数的 96 行。
所以,在实施 FGA 处理器模块之前请先对其进行全面测试。
- 审计线索表——FGA_LOG$——在系统表空间中。 当更多的 FGA 条目产生时,空间表就填满了,这可能导致数据库运行中断。
- 审计线索被写入表中,不过是以异步方式进行的。 这会产生事务处理和 I/O,它将增加到数据库中的整体 I/O 中。 如果您的数据库是受 I/O 所限,您将看到实施 FGA 处理器模块后对整个数据库的性能影响。
- 您可以使用自治事务处理以异步方式编写审计线索。 所以,即使用户回滚该事物处理,也不会删除该线索条目,导致错误的正值. 如果您想将 FGA 用作一种简单的机制来识别用户,您应该注意这些错误的正值。
操作清单
- 识别敏感的表和列。
- 识别要访问的敏感度——例如,工资低于 500 的。
- 将所有可能的组合放在一张纸上,然后将这些组合合并成 WHERE 条件(谓词),在这种方式下,只要一个谓词就将满足任何给定的条件。
- 在那些谓词中构建 FGA 策略。
- 启动 FGA 策略。
- 之后,分析 FGA 审计线索文件。
- 制作清除计划,清除 FGA 线索表。
4.2 激活虚拟专用数据库
背景 如果您已经很熟悉应用程序环境和虚拟专用数据库(也称为行级安全性或细粒度访问控制),您可以跳过该节,直接查看策略节。
虚拟专用数据库 (VPD) 是一个很大的主题,因此我在这里只将一些基本的。 要了解背景知识,请参考我的 Oracle 杂志中有关该主题的 文章;您也可以在我的书里面找到关于 FGA 方面的更多信息。
假设您有一个称为 ACCOUNTS 的表,表中有以下数据: SQL> select * from rates;
ACCNO ACC_NAME ACC_BAL
---------- -------------------- ----------
1 John 1000
2 Jill 1500
3 Joe 1200
4 Jack 1300
您想确保只有得到适当授权的人才可以查阅授权范围的帐户余额。也就是说,级别 1 看到的余额应该小于 1,000,级别 2 看到的余额应该小于 1,200,级别 3 可以看到所有的余额。 您还有另一张显示用户和级别的表。 SQL> select * from tab;
USERNAME USERLEVEL
------------------------------ ----------
CLERK1 1
CLERK2 2
CLERK3 3
要存储用户首次登录时的用户级别,因此需要创建应用程序环境: create context user_level_ctx using set_user_level_ctx; 以及相关的可信过程: create or replace procedure set_user_level_ctx
(
p_level in number
)
as
begin
dbms_session.set_context (
'USER_LEVEL_CTX',
'LEVEL',
p_level
);
end;
接着,您需要创建登录触发器以设置适当的应用程序环境。 create or replace trigger tr_set_user_level
after logon
on database
declare
l_level number;
begin
select userlevel
into l_level
from arup.userlevels
where username = user;
set_user_level_ctx (l_level);
exception
when NO_DATA_FOUND then
null;
when OTHERS then
raise;
end;
这设置了一个阶段,您可以按照该阶段在应用程序环境属性设置用户级别。 我们测试一下,以确保: SQL> conn clerk1/clerk1
Connected.
SQL> select sys_context('USER_LEVEL_CTX','LEVEL') from dual;
SYS_CONTEXT('USER_LEVEL_CTX','LEVEL')
--------------------------------------
1
SQL> conn clerk2/clerk2
Connected.
SQL> select sys_context('USER_LEVEL_CTX','LEVEL') from dual;
SYS_CONTEXT('USER_LEVEL_CTX','LEVEL')
--------------------------------------
2
SQL> conn clerk3/clerk3
Connected.
SQL> select sys_context('USER_LEVEL_CTX','LEVEL') from dual;
SYS_CONTEXT('USER_LEVEL_CTX','LEVEL')
--------------------------------------
3
(编辑:aniston)
|