安全保护项目: 一种分阶段的数据库基础架构保护方法 (第二阶段)

第 2 阶段

持续时间: 一周

这是安全性和合规性项目的第 2 阶段。 看看如何在 5 个工作日内保护您的基础架构。

尽管“安全保护项目”的第 1 阶段仅持续了 24 小时,但在该阶段您已完成了很多操作。 现在将进入第 2 阶段,持续时间大约为一周。 在本阶段,您将接着上一阶段执行的操作继续执行操作,并取得一些新的进展。 与以前一样,您将采取一些简单但却高效的操作来保护数据库。

您可能会问,为什么本阶段要持续一周的时间呢?

  • 某些更改需要设置参数,而这些设置将导致数据库重复启动,并可能执行一些规划。
  • 某些更改基于第 1 阶段操作并可能需要一些仔细的规划。

下面我们就开始吧!

这一部分涉及:
· 2.1 删除 utl_file_dir
· 2.2 限制 OS 验证
· 2.3 禁用远程 OS 验证
· 2.4 使用产品配置文件保护 SQL*Plus
· 2.5 控制 SQL*Plus
· 2.6 包装机密代码
· 2.7 将间接授权转换为直接授权
· 2.8 限制表空间限额
· 2.9 监控监听器日志以获知尝试的非法侵入
· 2.10 审计和分析用户访问

2.1 删除 utl_file_dir

背景
Oracle 支持通过 SQL 和/或 PL/SQL 从数据库中操作 OS 文件,而不必访问主机操作系统。 此功能由内置的 PL/SQL 程序包 utl_file 提供。 例如,下面的代码打开目录 /tmp 中一个名为 myfile.txt 的文件并向其中写入行“Some Text”:

1  declare
2    l_filename  utl_file.file_type;
3  begin
4    l_filename := utl_file.fopen ('/tmp','myfile.txt','W');
5    utl_file.put_line (l_filename, 'Some Text', TRUE);
6    utl_file.fclose(l_filename);
7  end;

如果文件 myfile.txt 不存在,则此代码将创建 myfile.txt。 但要使此代码正常运行,您必须通过以下初始化参数将 /tmp 声明为一个可以由 utl_file 程序包打开的目录:

utl_file_dir = '/tmp'

然后重新启动数据库。

只要该目录由 Oracle 软件拥有者拥有,使用此参数表示用户可以在目录 /tmp 中创建文件,也可以覆盖其中的任何文件。 那么,设置该参数有错么?

没有,但大多数系统不会将此参数设置为 /tmp。 相反,为了使开发人员或用户可以操作文件,而事先并不知道创建文件的位置,该设置通常为“*”,如下所示:

utl_file_dir = '*'

这意味着只要 Oracle 软件拥有者拥有文件(甚至是 Oracle 数据文件)的读取或写入权限,用户便可以打开文件。从理论上来讲,这将使恶意攻击者可以写入一个故意破坏数据文件的程序。 如果该文件恰好用于 SYSTEM 表空间,则整个数据库将崩溃。(当然,您可以从备份恢复它,但损害已经在所难免。) 更糟糕的是,恶意攻击者可能会破坏存档的日志文件,从而导致无法通过此存档日志进行恢复。恶意攻击者甚至还可以使用 utl_file.fremove 提供的程序包删除文件。

因此,将 utl_file_dir 设置为“*”并不可取。

策略
在 Oracle9i 数据库和更高版本中,无需使用 utl_file_dir - 程序将使用 directory 对象指定位置,而非绝对目录。 因此,在以上示例中(在该示例中,该应用程序需要打开 /tmp 目录中的文件 myfile.txt),该应用程序可以通过以下代码执行此操作:

1  declare
2    l_filename  utl_file.file_type;
3  begin
4    l_filename := utl_file.fopen ('TMP_DIR','myfile.txt','W');
5    utl_file.put_line (l_filename, 'Some Text', TRUE);
6    utl_file.fclose(l_filename);
7  end;

目录对象 TMP_DIR 必须已在前面通过以下命令创建:

create directory TMP_DIR as '/tmp';

该命令(即 create directory)只提供一次。 随后,任何具有该目录访问权限的用户均可以从中创建或读取文件。

您可以通过精细的方式授予此目录对象。 例如,假设您为警报日志所在的目录创建了一个目录对象,并创建了一个读取和操作此警报日志的应用程序。 您可以将该目录的读取权限授予 SCOTT,而将写入权限授予 DBA ananda。

因此,请从数据库参数中删除 utl_file_dir 并使用目录对象替换此代码。

随后,您还应删除 PUBLIC 以及任何其他用户所拥有的 create directory 系统权限。

可能的影响
可能的影响取决于 utl_file 程序包用于操作外部文件的频次。 如果从未使用此程序包,则可以立即删除它。 如果将要使用它,则首先需要进行规划。

操作计划

  1. 浏览此代码可以看到以下字符串: utl_file.fopen。

  2. 收集第一个参数中的所有名称。 例如,当您看到 utl_file.fopen('/tmp'、'myfile.txt'、'W')时,请记录值“/tmp”。 浏览所有文件以获得所有目录位置。可能有 10 个文件使用“/tmp”,有 5 个文件使用“/ftpdata”等等。

  3. 以用户 SYS 的身份分别为这些目录创建一个目录对象,例如:

    create directory TMPDIR for '/tmp';
  4. 将这些目录授予访问它们的用户,例如:
  5. grant read on directory TMPDIR to SCOTT;
  6. 从代码中删除目录名,并使用目录对象名称替换它。 例如,行:
  7. utl_file.fopen ('/tmp','myfile.txt','W')

    将变为

    utl_file.fopen ('TMPDIR','myfile.txt','W')
  8. 重新编译程序。

  9. 删除 PUBLIC 以及除 DBA 以外的所有用户所拥有的 create any directory 系统权限。
    revoke create any directory from public;

 


2.2 限制 OS 验证

背景
可以通过不同的方式(最常见的方式是通过数据库验证)验证 Oracle 用户。 使用 create user ananda identified by abc123 命令行创建用户后,该用户登录数据库的唯一方法就是传递它的用户 ID 和口令。

一种替带方法是操作系统验证,该方法使用以下命令行创建用户:

create user ops$ananda identified externally;

如果主机操作系统有一个名为“ananda”的用户 ID,则 Oracle 将不再检查它的证书。 它只假设该主机一定已经执行了它的验证,从而允许用户登录数据库而不必进行任何进一步的检查。

这正是问题的所在。 如果主机操作系统的验证机制比较强大,则它可能是安全的;但在某些脆弱的 OS 中,可以用户身份通过破解口令或不输入口令来进行登录:

sqlplus /

注意,以上命令缺少用户 ID 和口令 - 字符串“/”指示数据库接受用户 ID ananda 到数据库帐户 ops$ananda 的连接。

此类验证通常用于 shell 脚本,因此您不必在脚本中嵌入口令,而只需使用 sqlplus / 调用它。 由于不存在口令,因此该方法不但方便而且在某种程度上比较安全。 但请注意以下情形: 在安全性薄弱的 OS 中,某人可以创建一个名为 ananda 的帐户,然后使用它登录到帐户 ops$ananda。

该帐户一定为 ops$ 么? 不一定;您可以通过设置初始化参数更改它。 在以下示例中,我已将它设置为 osauthent$。

os_authent_prefix = 'osauthent$'

可以使用以下查询找到这些用户:

SQL> select username, password from dba_users
  2  where password = 'EXTERNAL'
  3  /
 
USERNAME                       PASSWORD
------------------------------ ------------------------------
OPS$ANANDA                     EXTERNAL
OPS$ORACLE                     EXTERNAL

按如上所示设置初始化参数时,帐户 ops$ananda 将不起作用;相反,您需要将这些帐户(OS 验证的帐户)创建为 osauthent$ananda。 有趣的是,您还可以将它设置为 ""(空)。 这时,OS 用户 ananda 将映射到 Oracle 用户 ananda。 您甚至还可以为此帐户设置口令:

alter user ops$ananda identified by oracle;

这种情况下,用户可以通过以下两种方法登录数据库:

sqlplus /
sqlplus ops$ananda/oracle

那么,这样做有什么不妥么? 先来看一看下面的情形。 假设参数 os_authent_prefix 设置为 ""(空)。 在安全性薄弱的 OS 中,某人可以创建一个名为 SYSTEM 的用户并使用以下命令登录

sqlplus /

这将把该用户记录为 Oracle 用户 SYSTEM! 登录后,该用户可以执行所需的任何操作 - 创建用户、删除数据文件、查看机密数据以及大量其他操作。 看似方便的事情突然间成了一个大麻烦。

策略
您可以看到,此问题只会在所出现的情况的某些组合中发生。 其中之一是 OS_AUTHENT_PREFIX 不为空,另一个是为 OS 验证的帐户设置口令。 因此,第一个需要检查的对象就是 OS 验证前缀。

SQL> select value    
  2  from v$parameter
  3  where name = 'os_authent_prefix';
 
VALUE
-----------------------
ops$

如果以上查询返回空,则应制订规划来更改它。 实际值并不重要,但您必须包含某个非字母字符。 这样,OS 验证的用户名将始终不会匹配实际用户。

其次,您需要确保 OS 验证的帐户应完全按照 OS 所采用的方式得到验证,并从不包含口令。 例如,如果 OS_AUTHENT_PREFIX 设置为 OPS$,则您将使用以下查询查明是否设置了口令:

SQL> select username, password from dba_users
  2  where username like 'OPS$%';

USERNAME                       PASSWORD
------------------------------ ------------------------------
OPS$ORACLE                     17C96FEC14DC431F
OPS$ANANDA                     EXTERNAL

该查询表明用户 OPS$ORACLE 无法通过 OS 验证路由或口令路由登录。 这正是您希望避免的情况;应只存在一种验证方法。 要更改 OPS$ORACLE 的验证模式,应使用:

alter user OPS$ORACLE identified externally;

该命令将 PASSWORD 列更改为 EXTERNAL。

可能的影响
根据这些帐户的使用情况,这些更改的影响可能会比较广泛。 如果您拥有此类帐户的任何一个,请浏览程序以便了解如何轻松地更改它们。

操作计划

查明哪些程序正在使用 OPS$ 帐户。
如果没有,则
 检查初始化参数 os_authent_prefix
如果它为空,则
  将它更改为 OPS$(需要重新启动数据库)
 检查 OPS$ 帐户的口令
如果不为 EXTERNAL,则
  将其更改为 EXTERNAL
如果找到一些这样的程序,则
 检查它们是否还将该帐户用作口令(例如,OPS$ORACLE/mypass)。
如果使用了口令,则删除它 - 例如,行 sqlplus OPS$ORACLE/mypass 应变为 sqlplus /

 


2.3 禁用远程 OS 验证

背景
远程 OS 验证是一个相似的过程。 在 OS 验证中,您可以创建在本地操作系统中进行验证的用户。 例如,如果 UNIX 服务器上有一个名为 ananda 的用户,而同一服务器上运行的数据库中有一个名为 OPS$ANANDA 的用户,则用户 ananda 只需发出以下命令即可登录到该数据库:

sqlplus /

该方法适用于本地用户 - 数据库运行所在的同一服务器上的用户。但当远程服务器的用户尝试连接到此数据库时,情况将如何? 例如,假设有两个服务器 - node1 和 node2,且数据库在 node1 服务器上运行。 该数据库有一个在外部标识的用户 OPS$ANANDA。 服务器 node2(而非 node1)上有一个用户 ananda。当服务器 node2 上的用户 ananda 通过发出以下命令尝试连接到 node1 上的数据库时:

sqlplus /@node1

他能否连接成功?

答案取决于数据库初始化参数 remote_os_authent 的设置。 如果该参数设置为 TRUE,则此连接尝试将取得成功;如果为 FALSE,则不允许来自远程服务器的 OS 验证连接。 默认值为 FALSE

为什么? 理由很充分: 在您的数据库服务器上,您可能拥有很高的安全性,因此 OS 验证的用户可能并不算是问题。 而客户端计算机则不然。根据 OS 的不同,恶意攻击者能够在远程服务器上创建一个名为 ananda 的帐户,当该帐户连接到数据库服务器时,它可以在无需口令情况下连接到 ops$ananda。 由于您无法轻松地控制客户机,因此该功能将为您带来一个不小的漏洞。

策略
此处的任务很简单。 检查该参数是否设置为 TRUE。 如果为 true,则将其更改为 FALSE,然后重新启动数据库。

 

可能的影响
在许多数据库中,该参数可能已经设置为 FALSE。 但如果它设置为 TRUE,且某些客户机以 OS 验证的用户身份连接,则这些帐户将不起作用。 您可以在进行此更改之前找到它们:

select username, machine, osuser, terminal
from v$session
where username like 'OPS$%'
/

输出可能显示类似如下的内容:

USERNAME      MACHINE              OSUSER       TERMINAL
------------- -------------------- ------------ -----------
OPS$ANANDA    PRONT/ANANDAT42      ananda       ANANDAT42

此处我们看到,用户 ananda 已经以远程 OS 验证的用户身份从计算机 PRONT/ANANDAT42 登录。 此处请注意,ananda 是计算机 PRONT/ANANDAT42(而非数据库运行所在的服务器)中的用户。

 

操作计划

  1. 如果某些用户使用远程验证连接,则删除他们的无口令功能。
  2. 在初始化参数文件中,将 remote_os_authent 更改为 FALSE,然后重新启动数据库。

 


2.4 使用产品配置文件保护 SQL*Plus

背景
使用 SQL*Plus 时,您可能注意到,您可以发出 host 命令转到 *nix 提示符,或发出 run 命令执行某个脚本。一个很少使用但却有可能造成致命破坏的攻击便源自此功能。 您可能编写了某个从 shell 中调用的 SQL*Plus 脚本,如下所示:

sqlplus someuser/somepass@remotedb @myscript.sql

此处的 myscript.sql 是一个先执行然后退出的 SQL*Plus 脚本文件。 在该文件执行过程中,用户可以按 Control-C(或特定 OS 的 break 键序列)中断程序流。 这种情况下,用户将获得 SQL*Plus 提示符(以 someuser 的身份连接)。 在此阶段,用户几乎可以执行从 SQL*Plus 提示符中所能执行的所有操作,并因此而造成某种程度的破坏。

这是一个应立即修复的安全漏洞。

策略
修复方法很简单: 您所要做的就是在运行命令之前,将这些命令限制到一个由 SQL*Plus 引用的“特殊位置”。 此特殊位置是 SYSTEM 模式中一个名为 SQLPLUS_PRODUCT_PROFILE 的表。 如果该表不存在,则您在每次启动 SQL*Plus 时将获得一个类似“Product User Profile Not Loaded”这样的警告。

SQL> select * from system.SQLPLUS_PRODUCT_PROFILE
  2  /
 
no rows selected
 
SQL> insert into system.SQLPLUS_PRODUCT_PROFILE
  2  values ('SQL*Plus','%','HOST',null,null,'DISABLED',null,null)
  3  /
 
1 row created.
 
SQL> commit;
 
Commit complete.

现在,当您启动 SQL*Plus 并输入 host 命令(或它的等价形式“!”)时,您将收到以下错误:

SQL> host;
SP2-0544: Command "host" disabled in Product User Profile

如果要对某个用户禁用此功能,只需使用要限制的用户名替换上面的 insert 命令中的“%”(表示所有用户)。 例如,如果只希望对用户 SCOTT 禁用此功能,请使用以下语句:

SQL> insert into system.SQLPLUS_PRODUCT_PROFILE
  2  values ('SQL*Plus','SCOTT','HOST',null,null,'DISABLED',null,null)
  3  /

还可以在用户名中使用通配府 - 例如,使用 APP% 表示所有以 APP 开头的用户(APPUSER1、APPUSER2)。

该方法也适用于其他命令(及其缩写或简写形式):

accept          edit          repheader
append          execute       run
archive log     exit          save 
attribute       quit          set
break           get           show 
btitle          help          shutdown 
change          host          spool
clear           input         start
column          list          startup 
compute         password      store
connect         pause         timing
copy            print         ttitle 
define          prompt        undefine
del             recover       variable
describe        remark        whenever oserror
disconnect      repfooter     whenever sqlerror

除了 SQL*Plus 以外,该方法还适用于 SQL 命令。 例如,如果要禁用 lock 命令,则需要插入:

insert into system.SQLPLUS_PRODUCT_PROFILE
values ('SQL*Plus','%','LOCK',null,null,'DISABLED',null,null)
/

注意,SQL 命令 lock 已被禁用,此外我们还在上面使用了“SQL*Plus”关键字。

可以禁用的 SQL 命令如下:

alter            drop          revoke
analyze          explain       rollback
associate        flashback     savepoint
audit            grant         select
call             insert        set constraints
comment          lock          set role
commit           merge         set transaction
create           noaudit       truncate
delete           purge         update 
disassociate     rename        validate

可能的影响
开始前,请注意一个重要问题: 该方法适用于在服务器本身中运行的 SQL*Plus, 而不会影响在其他位置运行(如在客户端中运行)的 SQL*Plus。

该操作需要仔细的规划。 如果 shell 脚本依赖于 SQL*Plus 中的 host 命令,则禁用它们将会明显停止这些作业。 一个非常典型的例子就是旧式的 host backup 命令。 一个典型的 SQL 脚本可能如下所示:

alter tablespace xyz begin backup;
host cp /fs1/xyz.dbf /backup/xyz.dbf
alter tablespace xyz end backup;

等等(适用于所有表空间)。 该脚本将注定失败 - 除非以 SYS 用户的身份运行它,这时命令禁用将不起作用。

操作计划
当所有这些命令使用的可能性最小时,从 SQL*Plus 中禁用它们。

 


2.5 控制 SQL*Plus

背景
根据 SQL*Plus 脚本用法的不同,您可能会也可能不会受到前面描述的威胁。 无论在哪种情况下,采取预防性措施降低威胁级别都是很有好处的。 方法之一是按照前面所述在产品配置文件中禁用命令,而自从 Oracle9i 数据库推出后,一个更简单的可用方法是使用 SQL*Plus 限制。 在该方法中,您必须使用一个新参数 restrict 调用 SQL*Plus。 限制分多个不同的级别。 级别 1 只禁用 hostedit 命令。

sqlplus a€“restrict 1 scott/tiger

如果用户在 shell 内部调用 host 命令,则将收到:

SQL> host
SP2-0738: Restricted command "host" not available

注意,此错误消息不同于产品用户配置文件消息。

使用 -restrict 2 除了禁用 hostedit 以外还将禁用 savestorespool 命令。 使用 -restrict 3 可以将 getstart 添加到现有列表。

最重要的差别体现在,所有用户(甚至是 SYS)都将受到此限制的影响。 产品配置文件限制不适用于 SYS。

策略
这可能是一个比使用产品用户配置文件更好的方法。 在本示例中,在 $ORACLE_HOME/bin 中创建一个名为“sqlplus”的 shell 脚本,并将 sqlplus 可执行文件重命名为类似“sqlplus_orig”这样的名称。 在脚本“sqlplus”中放置以下行。

$ORACLE_HOME/bin/sqlplus_orig a€“restrict 1

这将与命令行参数具有相同的效果。 当然,您可以向 restrict 中添加所需的任何参数。

可能的影响
该任务可能产生的影响与前一个任务可能产生的影响类似,但由于它们还适用于 SYS,因此其范围略大一些。 如果脚本调用受限制的命令,则您可能需要修改它们或使用一个非限制版本。

操作计划

标识调用受限制命令的 SQL 脚本。
如果找到它们,则
 修改它们,或
使用非限制版本
否则
 将 sqlplus 重命名为 sqlplus_orig
创建具有限制的文件 sqlplus

 


2.6 包装机密代码

背景
您可能在存储过程和函数的内部放置了口令或密钥等机密信息。 这种情况下,恶意攻击者可以轻松地从代码中选择该信息。 以下是我最近审计的一个网站中的示例:

l_password := 'GobbleDGook';

恶意攻击者可以使用以下查询选择源代码:

select text
from dba_source
where name = 'MYFUNC';

消除此风险的最佳方法是使用 wrap 实用程序。 创建脚本文件以创建过程或函数后,请使用以下代码包装它:

wrap iname=myfunc.sql oname=myfunc.plb

此代码将创建一个采用无法破解的方式存储源代码的文件 myfunc.plb,从而保护您的代码。

在 Oracle 数据库 10g 第 2 版中,您可以通过调用支持的存储过程直接创建包装代码,而不使用脚本:

begin
dbms_ddl.create_wrapped
     ('create or replace function myfunc ...')
end;

也可以使用此代码编写您自己的包装实用程序:

1  declare
2     l_input_code    dbms_sql.varchar2s;
3  begin
4     l_input_code (1) := 'Array to hold the MYP';
5     l_input_code (2) := 'create or replace procedure myproc as ';
6     l_input_code (3) := '  l_key VARCHAR2(200);';
7     l_input_code (4) := 'begin ';
8     l_input_code (5) := '  ...;';
9     l_input_code (6) := 'end;';
10    l_input_code (7) := 'the end';
11    sys.dbms_ddl.create_wrapped (
12             ddl     => l_input_code,
13             lb      => 2,
14             ub      => 6
15     );
16* end;

然后将所有代码置于输入可变数组中以进行包装。

另一个需要注意的问题是: 在 Oracle9i 中,包装实用程序并不包装变量值。 因此,passwordkeys 等机密单词清晰地显示在包装代码的内部。

让我们来看一个示例。 以下是文件 a.sql 的内容:

create or replace procedure myproc
as
    l_v varchar2(200);
begin
    l_v := 'SecretKey';
end;

我将机密单词的值用作 SecretKey。 下面将包装源代码:

$ wrap iname=a.sql oname=a.plb

现在,如果您在包装代码的内部检查,则仍将看到明文中的值:

$ grep SecretKey a.plb
1SecretKey:

Oracle 数据库 10g 第 1 版和更高版本中并不存在此问题。

要保护变量值,应降低代码内部的明文值的可读性。 例如,代码可能显示如下:

create or replace procedure myproc
as
    l_v1 varchar2(200);
    l_v2 varchar2(200);
    l_v3 varchar2(200);
    l_lv varchar2(200);
begin
    l_v1 := 'LotsOfJunktoMakeSureSecurityIsWaterTight';
    l_v2 := 'AdditionalValueToInterpretTheSecretWord';
    l_v3 := 'WowWeDontStopAtTheKeyDoWe';
    l_lv := substr(l_v1,21,3);
    l_lv := l_lv||substr(l_v2,24,3);
    l_lv := l_lv||substr(l_v3,19,3);
end;
/

注意我们如何将机密单词的各个部分嵌套在字符串中并在代码内部使用位置。 您在第一个字符串的内部看不到代码的第一部分。

策略
无法清楚地标识引用此机密数据的源代码。 您最好询问开发组以了解哪些用户可能使用机密单词。 也可以执行初步检查以查明代码是否包含 PASSWORD、SECRET、ENC(针对 ENCrypted、ENCryption、ENCiphered、ENCoded)、DEC 等单词。

select name, text
from dba_source
where upper(text) like '%PASSWORD%'
or upper(text) like '%ENC%'
or upper(text) like '%DEC%'
or upper(text) like '%SECRET%'
or upper(text) like '%PASS%'
/

这可能会提供一些线索来帮助您标识可能要检查的代码段。 标识所有此类代码后,应使用 wrap 实用程序包装它并运行包装代码。

可能的影响
不存在任何可能的影响。 但您应该知道一个非常重要的问题: 包装是单项进行的;您可以包装明文代码,但不能从包装代码中创建明文。 因此,应将明文代码保存在某个安全的位置以便进一步编辑。 如果丢失明文代码,则将永远无法更改代码。

操作计划

标识包含机密数据的代码。
如果在 Oracle9i 中,则
 将值分解为多个部分并将每个部分嵌套在短语中。
创建一个变量以提取短语中的各个部分。
重新构造代码中的值。
否则
 不执行任何操作。
ENDIF
从明文中创建脚本文件。
包装脚本。
运行包装脚本。

 


2.7 将派生授权转换为直接授权

背景
授予权限时,可以选择使用 with grant option 子句,以便被授权者可以进一步授予权限。 以下是一个有关授予用户 A 拥有的表 TAB1 的权限的示例。

Step1
Connect A/******
Grant select on tab1 to B;
Step 2 Connect B/****** Grant select on a.tab1 to C;

用户收到错误

ORA-01031:insufficient privileges

原因是用户 B 无权授予它本身从某个用户那里收到的权限。 但在第 1 步中,如果语句为

Grant select on tab1 to b with grant option;

则用户 B 将有权进一步授予该权限,且第 2 步将成功。

同样,B 也可以使用 grant option 将该权限授予 C,而 C 随后可以将该权限授予 D,依此类推。

表面看来它似乎是一个不错的规划。 最初所有者 A 不必担心向哪个用户授予或撤销权限;该过程是按需进行自我管理的。 那么,问题是什么呢?

来看看以下情形:

Connect A/*****
Revoke select on tab1 from B.

注意,C 从 B 那里获得它对 TAB1 的权限,而并非从 A 那里直接获得;因此,如果 B 丢失了这些权限,那么 C 的权限将如何? C 也将丢失它的权限,这是因为该权限是一个派生的权限。

我们进一步假设 A 已经向 C 直接授予了对 TAB1 的 select 权限。 C 现在对 TAB1 有两个权限,一个来自 B,一个来自 A。当您撤销某个权限时,另一个权限仍然有效,从而使您错误地认为该权限不存在。

尽管该过程表面看来很不错,但实际上缺产生混淆和安全漏洞,并带来难于跟踪的错误。 一种更有意义的做法是在无中间方的情况下直接授予权限。

策略
您的目标是标识哪些权限是通过其他用户授予的,然后直接授予权限。 可以从视图 DBA_TAB_PRIVS 中清楚地看到这些权限,其中的列 grantor 显示了授予权限的用户。

SQL> col grantee format a15
SQL> col privilege format a15
SQL> col owner format a20
SQL> col table_name format a20
SQL> select grantee, privilege, owner, table_name
  2  from dba_tab_privs
  3* where grantor != owner
  4 /

下面显示了一个简单的输出。

PUBLIC          EXECUTE         XDB.DBMS_XMLSCHEMA             SYS
PUBLIC          EXECUTE         XDB.XDB_PRIVILEGES             SYS
PUBLIC          EXECUTE         XDB.DBMS_XMLSCHEMA_INT         SYS
APP1            SELECT          ANANDA.MP                      RUSER

前三行可以忽略,在这三行中授权是由用户 SYS 向角色 PUBLIC 发出的。 该权限是模式 XDB 拥有的程序包 DBMS_XMLSCHEMA 的权限。 作为由 Oracle 提供的特殊程序包,这样做是允许的;但应注意第四行。 由 ANANDA 拥有的表 MP 是由 RUSER 授予的,因此应对其进行更正。 修复方法其实很简单: 将该对象的 select 直接授予 APP1,即使 RUSER 拥有 with grant option 权限。

执行该操作有两种方法:

  1. 对象拥有者直接授予该权限。
  2. SYS 这样的超级用户授予该权限。

第二种方法更易于实施。 SYS 用户实际上并不继承授权;它通过使用系统权限 grant any object privilege 授予权限。 当 SYS 使用以下代码授予权限时:

grant select on a.tab1 to c;

GRANTOR 列将显示 A 而不是 SYS;这正是您所需要的。

set lines 300
set pages 0
spool grant_direct.sql
select 'grant '||privilege||' on '||owner||
   '.'||table_name||' to '||grantee||';'
from dba_tab_privs
where grantor != owner
/
spool off

现在,运行文件 grant_direct.sql 以直接授予权限。

成功授予权限后,必须撤销间接授予的权限。 该操作无法在单个语句中实现,原因是您还必须以授权者的身份连接。

break on conn skip 2
select 'connect '||grantor conn,
   'revoke '||privilege||' on '||owner||
   '.'||table_name||' from '||grantee||';' line
from dba_tab_privs
where GRANTOR != 'SYS'
and grantor != owner
order by 1,2
/

将该脚本假脱机到某个文件,编辑该脚本以为每个用户提供口令,然后执行它以撤销授权。

可能的影响
有两个可能的影响。 首先,由于您要撤销权限并重新授予它们,因此可能由于无法重新授予权限而引起错误。 因此,必须在此更改的前后获得权限快照以确保成功。 使用以下脚本查找权限:

SQL> select grantee, privilege, owner, table_name
  2  from dba_tab_privs
  3* where grantor != owner
  4 /

在更改的前后运行该脚本,保存输出,然后比较它们以确保权限保持原样。

第二个可能的影响更明显。 授予和撤销周期将使这些对象的游标在库缓存中无效并将迫使对游标进行重新分析,从而将临时降低性能。

此外,某些相关对象将失效。 由于再次授予了权限,因此对象在被引用时将正常编译,但您可能需要采取某个主动式操作并事先重新编译它们。

操作计划

  1. 查找由其他用户使用 grantable 选项授予的权限。
  2. 撤销权限。
  3. 在不使用 grant 选项的情况下重新授予权限。
  4. 检查无效对象并重新编译它们。

 


2.8 限制表空间份额

背景
用户可以使用表空间内部多大的空间?用户可以写入多少个表空间? 答案取决于可供用户使用的表空间的份额。 可以按如下所示指定份额:

alter user ananda quota 12M on users;

此代码允许用户 ananda 创建总大小不超过 12MB 的存储对象,如表、索引以及物化视图。 要确认或查明用户已经使用的空间大小,请发出以下查询

SQL> col used format 999,999.999 head "Used (MB)"
SQL> col quota format 999,999.999 head "Quota (MB)"
SQL> col tablespace_name format a15
SQL> select username, tablespace_name,
  2  bytes/1024/1024 used,
  3  max_bytes/1024/1024 quota
  4  from dba_ts_quotas
  5  order by username
  6  /

示例输出如下。

USERNAME            TABLESPACE_NAME    Used (MB)   Quota (MB)
------------------- --------------- ------------ ------------
USER1               USERS                   .000      100.000
USER1               APP1_INDEX           504.875        -.000
USER2               USERS                   .125        5.000

我们需要对以上输出进行一下说明。 该输出表明用户 USER1 在表空间 USERS 中的份额为 100MB(显示在列 Quota 的下面)。 而用户未使用该分额中的任何表空间(显示在列 Used 的下面)。 第二行很有趣 - 您可以看到 Quota 列显示“-0”。 它指示用户在该表空间 (APP1_INDEX) 中具有无限的表空间权限。 用户 USER2 在表空间 USERS 中的份额为 5MB,并只使用了其中的 0.125 MB。

您应监视的是无限的表空间。 可以使用以下代码向用户提供无限份额:

alter user ananda quota unlimited on users;

但该操作可能对安全性产生影响;如果常规用户对业务关键的表空间具有无限的表空间份额,则该用户可能会用尽该表空间 - 这一点类似于拒绝服务攻击。

一个更严重的风险是系统权限 UNLIMITED TABLESPACE,它使用户在所有表空间中均具有无限份额,而没有向他们授予特定份额。 请让我再次重申一下: 用户在所有表空间(包括 SYSTEM)中均具有无限的份额,因此用户可以从中创建对象。 这样并不好。

首先,检查 SYSTEM 上的任何显式表空间份额:

select
username,
   bytes/1024/1024 used,
   max_bytes/1024/1024 quota
from dba_ts_quotas
where tablespace_name = 'SYSTEM'
order by username;

如果该查询显示某些内容,则应对其进行评估并在必要情况下撤销该份额。

下一步是标识具有无限表空间系统权限的用户。

select grantee
from dba_sys_privs
where privilege = 'UNLIMITED TABLESPACE';

由于该系统权限也包含 SYSTEM 表空间的权限,因此应对该列表进行仔细评估。

策略
您现在已经标识了所有用户及其表空间份额,下一个任务就是降低它们的风险。 此处有两个任务,一个任务比另一个任务更具破坏性。

首先,尝试删除 SYSTEM 表空间中的无限份额。 执行该操作不会对应用程序造成严重的破坏。 但在执行该操作之前,您需要确保 SYSTEM 表空间不包含 SYS 模式外部的对象。 以下查询可以实现此目的。

select owner, segment_type, segment_name
from dba_segments
where tablespace_name = 'SYSTEM'
and owner not in ('SYS','SYSTEM');

输出如下

OWNER           SEGMENT_TYPE    SEGMENT_NAME
--------------- --------------- --------------
OUTLN           INDEX           OL$HNT_NUM
OUTLN           INDEX           OL$SIGNATURE
OUTLN           INDEX           OL$NAME
OUTLN           TABLE           OL$NODES
OUTLN           TABLE           OL$HINTS
OUTLN           TABLE           OL$

在该示例中,只有 OUTLN 对象位于 SYSTEM 表空间中,这是可以接受的。 如果看到任何其他对象,则应移动它们。

该问题的根本原因可能是

select username
from dba_users
where default_tablespace = 'SYSTEM';

它将只返回以下内容。

USERNAME
----------
SYSTEM
SYS
OUTLN

如果它显示其他用户名,请将该用户更改到其他表空间。 例如,要将用户 SCOTT 的默认表空间更改为 USER_DATA,请发出以下命令

alter user scott default tablespace user_data;

然后将所有对象移出系统表空间。

alter table scott.tab1 move tablespace user_data;

现在,您的下一个任务是确保所有用户在 SYSTEM 表空间中的份额为 0。 份额无限有两个基本原因,其中之一就是直接授予了无限的表空间。 另一个原因是授予了角色 RESOURCE,该角色在 Oracle9i 数据库和更早版本中具有系统权限 UNLIMITED TABLESPACE。 相比之下,Oracle 数据库 10g 并不将系统权限授予 RESOURCE 角色。

对于 Oracle9i 数据库

确保实际上已将 UNLIMITED TABLESPACE 授予 RESOURCE 角色。

SQL> select *
  2  from dba_sys_privs
  3  where grantee = 'RESOURCE';

GRANTEE                        PRIVILEGE                                ADM
------------------------------ ---------------------------------------- ---
RESOURCE                       CREATE TYPE                              NO
RESOURCE                       CREATE TABLE                             NO
RESOURCE                       CREATE CLUSTER                           NO
RESOURCE                       CREATE TRIGGER                           NO
RESOURCE                       CREATE OPERATOR                          NO
RESOURCE                       CREATE SEQUENCE                          NO
RESOURCE                       CREATE INDEXTYPE                         NO
RESOURCE                       CREATE PROCEDURE                         NO
RESOURCE                       UNLIMITED TABLESPACE                     NO

如果未列出 UNLIMITED TABLESPACE,则您不必在此阶段执行任何操作。 向前转至“常见任务”。

对于 Oracle 数据库 10g

确保未将 UNLIMITED TABLESPACE 授予 RESOURCE 角色。

SQL> select *
  2  from dba_sys_privs
  3  where grantee = 'RESOURCE';

GRANTEE                        PRIVILEGE                                ADM
------------------------------ ---------------------------------------- ---
RESOURCE                       CREATE TYPE                              NO
RESOURCE                       CREATE TABLE                             NO
RESOURCE                       CREATE CLUSTER                           NO
RESOURCE                       CREATE TRIGGER                           NO
RESOURCE                       CREATE OPERATOR                          NO
RESOURCE                       CREATE SEQUENCE                          NO
RESOURCE                       CREATE INDEXTYPE                         NO
RESOURCE                       CREATE PROCEDURE                         NO

常见任务

标识具有 UNLIMITED TABLESPACE 权限的用户,并将其份额更改为在所有表空间中均为 unlimited

set lines 300
set pages 0
spool quota.sql
select 'alter user '||grantee||' quota unlimited on '||
tablespace_name||';'
from dba_sys_privs p, dba_tablespaces t
where p.grantee in (
select username
from dba_users
)
and p.privilege = 'UNLIMITED TABLESPACE'
and t.tablespace_name not in ('SYSTEM','SYSAUX')
order by grantee, tablespace_name
/
spool off

此代码创建一个包含类似如下内容的文件

alter user ORAAGENT quota unlimited on INDEX01;
alter user ORAAGENT quota unlimited on INDEX02;
alter user ORADBA quota unlimited on INDEX02;

接下来,您可以执行此脚本文件以拥有这些用户的无限份额。 最后,删除 UNLIMITED TABLESPACE

set lines 300
set pages 0
spool revoke_ut.sql
select 'revoke unlimited tablespace from '||grantee||';'
from dba_sys_privs
where privilege = 'UNLIMITED TABLESPACE'
/
spool off

然后,执行此脚本文件以撤销权限。

可能的影响
删除这些权限以及将 SYSTEM 表空间的份额减少为 0 不会产生影响。 但如果 SYSTEM 表空间中存在段,并且您将其移动到其他表空间,则将产生两个结果:

  • rowid 将因为物理移动而更改。 如果您有一个基于 rowid 的应用程序,则应注意这一点。
  • 表索引将不可用 - 您必须重建它们。

此更改还可以使某些独立过程无效。

操作计划

找到 SYS、SYSTEM 和 OUTLN 之外的用户的默认表空间。
如果默认表空间为 SYSTEM,则将其更改为非 SYSTEM 表空间。
找到属于 SYS、SYSTEM 和 OUTLN 之外的用户的 SYSTEM 表空间段。
如果找到,则

 

将它们移出到它们的表空间
重新构建索引、物化视图等。

ENDIF
找到具有 UNLIMITED TABLESPACE 系统权限的用户
如果找到,则
 向他们授予所有表空间(SYSTEM 和 SYSAUX 除外)的无限份额
撤销系统权限 UNLIMITED TABLESPACE
ENDIF

 


2.9 监控监听器日志以获知尝试的非法入侵

背景
阶段 1.7 中,您了解了如何通过限制在线更改参数的能力来保护 Oracle Listener。 这样做很不错,但您如何知道是否有人尝试非法入侵以及何时尝试非法入侵? 防止入侵只是预防措施的一部分;跟踪防御的有效性同样重要。

您可以从监听器日志文件中浏览已尝试的失败登录。 当用户提供错误口令并尝试修改监听器时,以下消息将写入监听器日志:

12-NOV-2005 23:23:12 * (CONNECT_DATA=(CID=(PROGRAM=)(HOST=prolin01)(USER=ananda
))(COMMAND=stop)(ARGUMENTS=64)(SERVICE=LISTENER_PROLIN01)(VERSION=168821760)) * stop * 1190
TNS-01190: The user is not authorized to execute the requested listener command

该消息表明 11 月 12 日晚上 11:23,用户“ananda”尝试停止监听器(注意 (COMMAND=stop) 的存在),但提供了错误的口令。 这是否表示尝试的非法入侵? 有可能。 ananda 也可能是一个合法用户,但在输入口令时出现输入错误,从而产生此错误。 但如果您多次看到此错误,则它实际上可能指示尝试的非法入侵。应访问用户 ananda 并验证它实际上是否尝试停止监听器。

同样,在监听器中限制 admin 选项时,用户无法只从命令行设置参数。 如果用户尝试使用以下命令:

$ lsnrctl
LSNRCTL> set trc_level support

他将立即获得错误。

TNS-12508: TNS:listener could not resolve the COMMAND given

以下条目将出现在监听器日志文件中。

12-NOV-2005 23:26:34 * trc_level * 12508
TNS-12508: TNS:listener could not resolve the COMMAND given

该条目指示某人曾尝试直接对 LSNRCTL 提示设置 trc_level。 这可能也是个正常的错误,但重复尝试可能表示存在攻击。

策略
最好的方法是定期检查这些模式的监听器日志文件。 可以通过多种方法执行该操作。

首先,您可以使用以下代码编写一个 shell 脚本:

$ grep "(COMMAND=stop)" listener.log | cut -f4 -d"*"

以下输出将指示监听器命令 STOP 已发出三次:

 0
 0
 0

还可以使用复杂工具(如 awk)或脚本语言(如 PERL)使该脚本提供更丰富的信息。 但如果您对 SQL 最熟悉(这种情况很有可能),则使用 SQL 从此日志文件中提取信息将更具有吸引力。

此处的技巧是将监听器日志用作外部表。 首先,为监听器日志所在的目录创建一个 directory 对象。

create directory listener_log_dir
as
'/u01/app/oracle/10.1/db1/network/log'
/

然后,为日志文件创建外部表。 仔细留意日志文件的内容;它通常包含六个由“*”字符分隔的信息部分。 这些部分将成为外部表的列。

create table listener_log
(
   log_date      date,
   connect_data  varchar2(300), 
   protocol_data varchar2(300),
   command       varchar2(15),
   service_name  varchar2(15),
   return_code   number(10)
)
organization external (
type oracle_loader
   default directory LISTENER_LOG_DIR
access parameters
   (
records delimited by newline
      nobadfile 
      nologfile
      nodiscardfile
      fields terminated by "*" lrtrim
      missing field values are null
      (
          log_datechar(30) date_format 
          date mask "DD-MON-YYYY HH24:MI:SS",
          connect_data,
          protocol_data,
command,
          service_name,
          return_code
      )
   )
   location ('listener_prolin01.log')
)
reject limit unlimited
/

创建表后,可以从中进行选择以确保定义正确。

这些行的描述性很高,但嵌入的命令(如 (COMMAND=stop))可能使它难于破解。 这种情况下,编写另一个函数以提取字符串中的值:

create or replace function extract_value
(
    p_in varchar2,
    p_param in varchar2
)
return varchar2
as
    l_begin     number(3);
    l_end       number(3);
    l_val       varchar2(2000);
begin
    l_begin := instr (upper(p_in), '('||p_param||'=');
    l_begin := instr (upper(p_in), '=', l_begin);
    l_end := instr (upper(p_in), ')', l_begin);
    l_val := substr (p_in, l_begin+1, l_end - l_begin - 1);
    return l_val;
end;

这样,监控将变得非常简单。 发现失败登录尝试所要执行的操作就是发出

col l_user format a10with the embedde
col service format a20
col logdate format a20
col host format a10
col RC format a5
select to_char(log_date,'mm/dd/yy hh24:mi:ss') logdate,
       extract_value (connect_data,'HOST')    host,
       extract_value (connect_data,'USER')    l_user,
       extract_value (connect_data,'SERVICE') service,
       action                                 RC
from listener_log
where extract_value (connect_data, 'COMMAND') in
(
        'password',
        'rawmode',
        'displaymode',
        'trc_file',
        'trc_directory',
        'trc_level',
        'log_file',
        'log_directory',
        'log_status',
        'current_listener',
        'inbound_connect_timeout',
        'startup_waittime',
        'save_config_on_stop',
'start',
'stop',
'status',
        'services',
        'version',
        'reload',
        'save_config',
        'trace',
        'spawn',
        'change_password',
        'quit',
        'exit'
)

这返回类似如下所示的输出

LOGDATE              COMMAND         HOST       L_USER     SERVICE              RC
-------------------- --------------- ---------- ---------- -------------------- -----
10/02/05 02:57:36    stop            prlddb01   oraprld    LISTENER_PRLDDB01    0
10/02/05 04:47:03    stop            prlddb01   oraprld    listener_prlddb01    0
10/03/05 15:14:53    stop            prlddb01   oraprld    LISTENER_PRLDDB01    0
11/18/05 23:48:26    reload          prlddb01   oraprld    LISTENER_PRLDDB01    0

您可以看到,该输出显示了命令的日期和时间以及返回代码。 也可以修改此查询以只显示返回代码不为 0 的值。此外,还可以添加一个谓词以只显示某个日期之后的记录,以便只显示当天的尝试。 如果每天均运行此脚本,则只能看到当日的尝试。

上面只显示了无效口令的数据。 对于管理限制的监听器,该错误字符串只显示三个字段,因此表 LISTENER_LOG 的列具有不同的含义: 第二列显示用户发出的命令,第三列显示返回代码。

select
	log_date,
	connect_data	       command,
	protocol_data	       return_code
from listener_log
where connect_data in
(
        'password',
        'rawmode',
        'displaymode',
        'trc_file',
        'trc_directory',
        'trc_level',
        'log_file',
        'log_directory',
        'log_status',
        'current_listener',
        'inbound_connect_timeout',
        'startup_waittime',
        'save_config_on_stop',
'start',
'stop',
'status',
        'services',
        'version',
        'reload',
        'save_config',
        'trace',
        'spawn',
        'change_password',
        'quit',
        'exit'
)
/

这返回:

LOG_DATE  COMMAND              RETURN_CODE
--------- -------------------- ---------------
06-NOV-05 change_password      0
06-NOV-05 save_config          0
06-NOV-05 log_file             0
06-NOV-05 trc_level            12508
06-NOV-05 save_config_on_stop  12508
06-NOV-05 log_directory        12508
06-NOV-05 log_directory        12508
06-NOV-05 stop                 1169
06-NOV-05 stop                 1169
06-NOV-05 services             1169
06-NOV-05 status               1169
06-NOV-05 reload               1169
06-NOV-05 status               1169
06-NOV-05 stop                 1169
06-NOV-05 status               1169
06-NOV-05 stop                 1169

可能的影响
无;该活动只是一个诊断活动。

 

操作计划

  1. 创建监听器日志外部表。
  2. 选择在无口令情况下发出管理命令的记录(可以由非零返回值标识)。
  3. 选择根据监听器控制提示发出命令的记录。
  4. 如果找到无法由任何 DBA 执行的活动解释的记录,则您可能标识了错误内容。

 


2.10 审计和分析用户访问

背景
您对用户的了解程度如何? 您是否知道他们从哪些计算机连接、他们在连接时的活动等问题?或许您并不知道。 但请注意,一个成功的安全性规划需要了解这些详细信息,或至少了解重要信息。 这正是 Oracle 数据库中的审计功能的用途所在。

Oracle 数据库中的审计功能非常全面。 此处,您只需要启用该功能的一部分来创建数据库的“配置文件”。您将尝试的所有操作就是查看用户连接、用户连接所使用的用户 ID 以及所使用的验证类型。 您还将发现无效的登录尝试 - 例如,用户 ID/口令组合何时错误。 正如以上所介绍的,查找这些异常事件的模式可以为发现可能的攻击提供线索。

策略
要启用审计,请在数据库初始化参数文件中设置以下参数。

audit_trail = db

这是一个静态参数;您必须重新利用数据库才能使其生效。 执行此操作后,发出以下命令以执行审计。

AUDIT SESSION;

该命令将在用户登录或注销时创建一个记录。 即使登录失败也将创建登录跟踪。 在数据库运行一段时间后,可以在审计跟踪中搜索模式。 列 RETURNCODE 记录用户在执行该操作时收到的 Oracle 错误代码。

SQL> select returncode, count(1)
  2  from dba_audit_trail
  3  group by returncode
  4  /

RETURNCODE   COUNT(1)
---------- ----------
         0    1710880
       604          3
       955         17
       987          2
      1013          2
      1017       1428
      1045          1
      1555          4
      1652          4
      1950          1
      2002          1
      2004          4
     28000          4
     28009          3

以上代码显示了错误模式;大多数操作均成功(其中的返回代码为 0)。 对于剩余代码,您可以通过从 *nix 提示符中发出以下命令获得描述

oerr ora <errorno>

。 例如,要查明错误代码 1017 的含义,请发出

oerr ora 1017

这将返回

01017, 00000, "invalid username/password; logon denied"
// *Cause:
// *Action:

这个最常见的错误是分析的目标,因为它将最有效地显示攻击模式。 无效/口令组合的偶然性如果很高,则可能指示尝试的意外入侵。

现在,您将看到这些会话的来源。 特定用户 ID 的口令无效可能指示对该用户 ID 的攻击。 可以通过以下代码查看用户 ID:

select username, count(1)
from dba_audit_trail
where returncode = 1017
group by username
order by 2 desc;

该输出如下所示:

USERNAME                         COUNT(1)
------------------------------ ----------
ARAO                                  569
DBSNMP                                381
DW_DQS                                181

此处,我们看到用户 ARAO(表面看来是一个实际用户)已经尝试使用无效口令 569 次。 下一个用户 ID DBSNMP(381 次无效的口令尝试)不是一个实际用户;它的用户 ID 为 Enterprise Manager。 这应立即引发警报信号 - —DBSNMP 是一个首选的攻击目标。

为进一步检查它,我们将查看这些攻击的来源:

select userhost, terminal, os_username, count(1)
from dba_audit_trail
where returncode = 1017
and username = 'DBSNMP'
group by userhost, terminal, os_username;

输出如下:

USERHOST                  TERMINAL        OS_USERNAM   COUNT(1)
------------------------- --------------- ---------- ----------
prlpdb01                                  oraprlp           199
prlpdb01                  pts/2           oraprlp             4
prlpdb01                  pts/7           oraprlp             9
prlpdb02                                  oraprlp           130
PRONT/PRANANDAT42         PRANANDAT42     ananda              3
progcpdb                  unknown         oracle             34

注意,此数据库运行所在的服务器为 prlpdb01。 由于这是一个 RAC 数据库,因此还存在第二个节点,且服务器名称为 prlpdb02。 大多数错误连接尝试均来自这些服务器,并使用作为 Oracle 软件拥有者的 OS 用户 (oraprlp)。 如果这是实际的攻击,则用户可以访问 Oracle 软件所有者并可以 SYSDBA 的身份登录。 不需要以 DBSNMP 的身份登录,该口令明显是错误的。 因此,它并不像攻击。

您还可以看到无效登录来自其他两个计算机: PRONT/PRANANDAT42 和 progcpdb。 它们看似可疑,我们可以确认这些计算机的身份 - 第一个计算机属于名为“ananda”的 DBA,另一个计算机是网格控制服务器,它应使用此用户 ID 连接。

接下来,请分析这些失败的模式。 如果这些失败集中在特定时间发生,则可能指示攻击。

SQL> select to_char (timestamp,'mm/dd/yy') ts, count(1)
  2  from dba_audit_trail
  3  where returncode = 1017
  4  and username = 'DBSNMP'
  5  group by to_char (timestamp,'mm/dd/yy')
  6  /

TS                     COUNT(1)
-------------------- ----------
10/14/05                      9
10/16/05                    222
10/27/05                     15
10/28/05                    125
11/09/05                      4
11/11/05                      2
11/12/05                      2
11/14/05                      2

您可以看到,有两个频繁出现失败的时间: 10/16 和 10/28。您应进行全面的调查。

可能的影响
审计对性能的影响最低;但仍存在一定程度的影响。 此外,请注意,审计跟踪写入表空间 SYSTEM(可能已被填满)中。 因此,您必须注意 SYSTEM 表空间内部的可用空间。

操作计划

  1. 通过设置 AUDIT_TRAIL 初始化参数打开审计。
  2. 对会话启用审计。
  3. 查找无效或失败的登录尝试。
  4. 检查失败的模式尝试(日期集群)。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值