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

http://www.oracle.com/technology/global/cn/pub/articles/project_lockdown/phase3.html

第 3 阶段

持续时间:1 个月

这是安全性和合规性项目的第 3 阶段。我们将了解一下如何在大约 1 个月的时间内保护您的数据库基础架构。

在 1 个月内您可以完成哪些操作呢?可以完成很多操作,不过需要仔细的规划。本阶段涉及一些需要进行额外分析的潜在破坏性任务。

这一部分涉及:
·
3.1 从脚本中删除口令
· 3.2 从 RMAN 中删除口令
· 3.3 将 DBA 脚本移动到计划程序
· 3.4 锁定对象
· 3.5 创建数据库用户的配置文件
· 3.6 创建并分析对象访问配置文件
· 3.7 对未来对象启用审计
· 3.8 只限制来自特定节点的访问

3.1 从脚本中删除口令

背景
某些最严重的潜在威胁是由于在应用程序、程序以及脚本中使用硬编码口令而导致的。在许多情况下,清除这些口令非常容易,并且收效显著。

例如,在我审计过的许多安装中,STATSPACK 作为 shell 脚本运行,如下所示:

export ORACLE_HOME=/u01/app/oracle/10.1/db
export ORACLE_SID=MYSID
cd $ORACLE_HOME/bin
$ORACLE_HOME/bin/sqlplus -s perfstat/perfstat @statspack.sql

然后,通过 cron 或 Windows 计划程序计划此 shell 脚本。该方法存在两个主要风险:

  • 入侵者可能会找到文件 statspack.sh 并看到用户 perfstat 的口令。
  • 当 shell 脚本正在运行时,*nix 服务器上的某人可以执行 ps -aef 命令,并在查看该命令运行的同时清楚地看到口令。

当我询问使用该方法的原因时,得到的答案几乎完全相同:因为以前的 DBA 就是如法炮制的。无论原因如何,威胁都是显而易见的,并且必须予以清除。

策略
消除口令曝露有多种方法。不要误认为以下语句会隐藏口令:

sqlplus -s scott/$SCOTTPASSWORD @script.sql

其中的 SCOTTPASSWORD 是在执行该脚本前定义的一个环境变量。当用户执行 /usr/ucb/ps uxgaeww 命令时,他可以看到将曝露口令的过程中使用的所有环境变量。因此,必须通过某种方法有效地隐藏口令。下面将对这些方法加以介绍。

方法 1.一种简单的方法是在 SQL*Plus 中使用 nolog 参数。在此方法中,前面的脚本应改为

export ORACLE_HOME=/u01/app/oracle/10.1/db
export ORACLE_SID=MYSID
cd $ORACLE_HOME/bin
$ORACLE_HOME/bin/sqlplus /nolog @statspack.sql

使用此脚本可以建立一个 SQL*Plus 会话,但该会话尚未连接到数据库。在 statspack.sql 脚本内部,应设置用户 ID 和口令:

connect perfstat/perfstat
... the rest of the script comes here ... 

这样一来,当某人执行 ps -aef 命令时,他将看不到用户 ID 和口令。(顺便提一下,对于以交互方式启动 SQL*Plus 会话而言,这也是一个最佳实践。)

方法 2.以上方法的这一小小变化形式在以下场合下很有用:SQL 语句不在 SQL 脚本中,而是直接嵌套入到 shell 脚本中,例如:

$ORACLE_HOME/bin/sqlplus user/pass << EOF
... SQL statements come here ... 
EOF

可以将此 shell 脚本改为

$ORACLE_HOME/bin/sqlplus /nolog << EOF
connect user/pass
... SQL statements come here ... 
EOF

该方法对于构建快捷而质量不高的 shell 脚本(用来处理 SQL)而言也是一个最佳实践。

方法 3.在该方法中,您可以创建一个包含用户 ID 和口令的口令文件,并可以在运行时间读取它们。首先,创建一个名为 .passwords 并包含所有用户 ID 和口令的文件(注意文件名前面的句点)。由于该文件名以句点开头,因此某人在使用 ls -l 命令时将看不到该文件名(但在使用 ls -la 命令时可以看到该文件名)。然后,将权限更改为 0600,以便只有拥有者能够读取它。

该文件应包含由空格分隔的用户 ID 和口令(每行一个)。

scott tiger
jane tarzan
... 等等... 

现在使用以下代码行创建另一个文件,即一个名为 .getpass.sh 的 shell 脚本(注意句点)。

fgrep $1 $HOME/.passwords | cut -d " " -f2

将此脚本的权限设置为 0700,以便任何其他人都无法看到以及执行该脚本。随后,当需要以 scott 的身份运行脚本时,您只需按如下所示对这些行进行编码即可:

.getpass.sh scott | sqlplus -s scott @script.sql

这将从文件中获得 scott 的口令并将其传递给 sqlplus 命令。如果有人执行 ps 命令,他将看不到该口令。

作为一个额外的好处,您现在已经实现了一个灵活的口令管理机制。每当 scott 的口令更改(作为一个良好的习惯,它应当定期更改)时,您只需编辑口令文件即可。

方法 4.该方法涉及由 OS 验证的用户。(在第 2 阶段您对其已经有所了解。)简单地说,如果有一个名为 ananda 的 *nix 用户,则可以使用以下语句创建一个 Oracle 用户:

create user ops$ananda identified externally;

此处,用户可以使用以下命令登录数据库

sqlplus /

注意,以上命令没有用户 ID 和口令。数据库实际上并不验证用户;它假设用户 ananda 已经在 OS 级别得到了正确地验证。尽管这不并是一个很棒的实践,但却是一个极具吸引力的实践 - 例如,对于 shell 脚本来说。您的脚本可能如下所示:

sqlplus -s / @script.sql

由于未传递用户名和口令,因此不存在通过 ps 命令将其曝露的风险。

可能的影响
无;使用口令管理系统替换硬编码的口令不会影响脚本的功能,只会影响提供口令的方式。但请确保备份口令文件或保存其副本,并且不断对其进行更新。

操作项目

  1. 使用硬编码的口令标识脚本。
  2. 为实施挑选一种方法:
    1. 在 SQL 脚本内部使用 Connect 命令
    2. 在 shell 脚本内部使用 Connect 命令(无 SQL 脚本)
    3. 使用口令文件
    4. 使用 OS 验证的帐户
  3. 修改脚本以删除口令。

 


3.2 从 RMAN 中删除口令

背景
硬编码的口令并不局限于脚本。恢复管理器 (RMAN) 脚本容易受到相同不良习惯的影响。

下面是一个用于备份的脚本内部的典型 RMAN 命令:

rman target=/ rcvcat=catowner/catpass@catalog_connect_string

在该命令中,connect 字符串 catalog_connect_string 中引用了目录数据库,该目录的用户 ID 和口令分别是 catowner 和 catpass。如前所述,如果某人执行 ps 命令,则会清楚地看到该用户 ID 和口令。

删除这些硬编码的口令有两种方法:

方法 1.在该方法中,请在 RMAN 脚本内部使用 connect 字符串,如下所示:

connect target /
connect catalog catowner/catpass@catalog_connect_string
run {
	allocate channel ...
... 等等... 

这显然是首选方法 - 不仅是因为它从过程列表中隐藏了口令,还因为它使得检查目录 connect 字符串中的错误更加容易了。

方法 2.另一种方法是对目录连接使用 OS 验证。但是您需要进行一些额外的更改。首先,目录可能位于不同的数据库中,而不是位于正被备份的数据库中。要在这种情况下启用 OS 验证,您需要对目录数据库启用远程 OS 验证。

在目录数据库上,添加下列初始化参数,然后重新启动。

remote_os_authent=TRUE

现在,在 catalog 数据库上创建一个用户 ID OPS$ORACLE,如下所示。

create user ops$oracle identified externally;

现在,您的 RMAN 连接将如下所示:

rman target=/ rcvcat=/@catalog_connect_string

这将不会显示 RMAN 用户的口令或口令。

由于您现在是以 OPS$ORACLE 而不是 catowner 的身份连接的,因此必须重建信息库。连接之后,使用

RMAN> register database;

命令重建目录。您现在准备在 RMAN 备份中使用此脚本。

可能的影响
此处有一些可能的影响。首先,目录数据库中的更改使具有登录身份“oracle”的任何人可以从外部服务器对该数据库进行访问。这是其自身的一个严重的安全漏洞;由于您无法控制客户端,因此某人可能会进入客户端服务器(可能通过一个本身不安全的操作系统),创建一个称作“oracle”的 ID,并登录到目录数据库。

有多种方法可以避免这样的进入。最简单的方法是启用节点过滤(如 3.8 所述),以防任何随机服务器连接到该节点。

此外,您还应意识到,源数据库服务器上的 Oracle 软件所有者可能具有不同的名称。如果您在数据库服务器 A 上使用“orasoft”,而在数据库服务器 B 上使用“oracle”,则您需要在目录数据库上创建的用户分别是 OPS$ORASOFT 和 OPS$ORACLE。因此,将存在两个信息库,而不是一个。这并不一定是坏事。但是,如果您想要对目录中的备份进行报告,则您必须知道数据库中的所有信息库。

操作计划

  1. 选择一种用于隐藏 RMAN 目录所有者口令的方法:
    1. 在脚本内部使用 Connect 命令
    2. 以 OS 验证的用户身份连接
  2. 如果选择 b.,则
    1. 对目录数据库启用远程 OS 验证(需要重新启动)。
    2. 在目录数据库中启用节点验证,以拒绝除已知的少数几个节点之外的所有节点。
    3. 创建名为 OPS$ORACLE 的用户。
    4. 修改 RMAN 目录连接字符串以使用 OPS$ORACLE。
  3. 重建目录。

 


3.3 将 DBA 脚本移动到计划程序

背景
那些需要登录数据库来执行统计数据收集、索引重建等操作的非常常见的 DBA 脚本如何?以往,DBA 使用 cron(或在 Windows 中使用 AT)作业方法运行工作,但是该方法存在两个风险:

  1. 如果此脚本需要登录到数据库(大部分 DBA 脚本均如此),则必须在脚本中设置用户 ID 和口令,或者以某种方式将其传递到脚本。因此,任何可以访问该脚本的用户都能够知道该口令。
  2. 更糟糕的是,任何可以访问服务器的用户都可以执行 ps -aef 命令来查看过程名称中的口令。

您需要防止口令曝露!

策略
可以遵循前面所述的相同策略,即在 SQL 脚本中传递口令,或者让 shell 脚本从文本文件中读取口令。该方法将避免某人在 ps -aef 输出中得知口令;不过,它不会解决某人访问脚本的问题。

在 Oracle 数据库 10g 第 1 版以及更高版本中,您可以通过数据库作业来管理此过程,这是一个极好的方法。注意,在 Oracle 数据库 10g 之前,对数据库作业的管理是通过 dbms_job 提供的程序包进行的,该程序包可以执行一个 PL/SQL 程序包、代码段或普通的 SQL,但无法执行 OS 可执行文件。在 Oracle 数据库 10g 中,新的作业管理系统是提供的程序包 dbms_scheduler(简写为 Scheduler)。除了提供一个明显改进的用户界面以外,该工具还有一个很大的优点:它甚至可以执行 OS 可执行文件 - 全部从 Oracle 数据库中执行!此功能使得实施一站式作业管理系统变得非常容易。

下面是一个例子。假设您有一个收集优化程序统计数据的 cron 作业,如下所示。

00 22 * * 6 /proprd/oracle/dbawork/utils/bin/DbAnalyze -d PROPRD1 -f DbAnalyze_PROPRD1_1.cfg 2>&1 1> /tmp/DbAnalyze1.log 

您可以看到,以下作业:

  • 运行一个名为 /proprd/oracle/dbawork/utils/bin/DbAnalyze -d PROPRD1 -f DbAnalyze_PROPRD1_1.cfg 的程序。
  • 在每周六午夜零点 22 分运行
  • 将输出写入文件 /tmp/DbAnalyze1.log

现在,为将该作业转换为一个 Scheduler 工作,您将使用下列代码段:

1  BEGIN
2   DBMS_SCHEDULER.create_job
3     (job_name        => 'Dbanalyze',
4      repeat_interval => 'FREQ=WEEKLY; BYDAY=SAT BYHOUR=0 BYMINUTE=22',
5      job_type        => 'EXECUTABLE',
6      job_action      => '/proprd/oracle/dbawork/utils/bin/DbAnalyze -d
PROPRD1 -f DbAnalyze_PROPRD1_1.cfg',
7      enabled         => TRUE,
8      comments        => 'Anlyze'
  9   );
10  END;

该过程的参数具有自我说明性;日历语法与英语几乎相同。(有关 Scheduler 的更多详细信息,请参阅此 OTN 文章或我撰写的图书 Oracle PL/SQLfor DBA (O'Reilly Media,2005)

既然功能强大的 cron 可供使用,为什么还要为 Scheduler 而费心呢?实际上,原因是多方面的:

  • 仅当数据库可用时 Scheduler 才运行作业,这是支持以数据库为中心的作业的一大特性。您不必为检查数据库是否打开而担心。
  • 各个 OS 之间的 Scheduler 语法是一致的。如果要移植,只需将代码移动到新的服务器上即可,并且只需执行一个非常简单的导出导入操作便可以启用您的计划作业。
  • 与对象一样,Scheduler 作业归用户所有,这使您可以实现更好级别的权限(例如,由不同的用户执行一项作业),这一点与 cron不同,后者通常是由单个 Oracle 软件拥有者帐户使用的。
  • 最值得称道的是,由于您不必在任何位置设置口令,因此并不存在意外泄露口令的风险。由于口令未存储在任何位置,因此即使 SYS 用户也无法知道用户的口令。此功能使 Scheduler 这一工具对于安全地管理 DBA(或常规用户的)的工作极具吸引力。
  • 此外,您不必担心所做的更改,如用户口令更改。

可能的影响
无,只要作业与数据库相关。有一点可以肯定的是,即使当数据库不可用时,某些作业也必须运行 - 例如,将警报日志移动到不同的位置或检查数据库是否启动并正在运行的作业。这些作业应位于数据库的外部以及 cron 的内部。

操作计划

  1. 标识 cron 中的数据库作业。
  2. 确定即使在数据库关闭时仍应运行的工作(例如:每天将监听器日志移动到其他位置的作业)
  3. 对于其余的作业,创建 Scheduler 作业,这些作业最初通过在 CREATE_JOB 过程中声明 ENABLED=FALSE 而被禁用。
  4. 使用 dbms_scheduler.run_job() 过程测试作业的执行情况。
  5. 如果成功,则关闭 cron 作业并使用 dbms_scheduler.enable() 过程启用 Scheduler 作业。

 


3.4 锁定对象

背景
程序包、过程、函数、类型主体以及对象方法等编程对象包含企业的业务逻辑。对它们所做的任何改动都可能会影响总体处理逻辑,并且根据其配置情况,对生产系统的影响可能是灾难性的。

许多企业通过实施一个安全的更改-控制过程来解决此问题。在此过程中,更改首先经过讨论和审批(理想情况下在至少两个人之间进行),然后才能实施。所面临的难题是让系统自动运行,这实际上也是许多辖区和行业中的要求。

策略
这个安全的更改-控制过程可以按照以下方式运行:

  • 应用程序超级拥有者(如果需要,可以是 DBA)将要更改的程序“解锁”
  • 应用程序拥有者更改程序主体
  • 超级拥有者锁定程序

鉴于 Oracle 数据库不包含适用于 DDL 的原生锁定机制,您将如何实施该过程?

方法之一是撤消模式拥有者的 create session 系统特权,使其始终无法登录以进行更改。取而代之的是,由有权更改指定模式的对象的应用程序拥有者进行更改。这是一个非常不错的关键数据库对象保护方法,具体体现在它支持为对象更改创建审计跟踪,而其中的跟踪可以追溯到实际用户,而非一般的模式名称。

例如,假设模式为 BANK,表名称为 ACCOUNTS。通过撤消 BANK 的 create session 权限可以禁止其登录数据库。取而代之的是,您允许拥有 create session 权限的 SCOTT 修改 ACCOUNTS。Oracle 用户 SCOTT 实际上由真用户 Scott 拥有,任何其他人都无法访问此用户 ID。SCOTT 对 ACCOUNTS 所做的任何更改都可以直接归因于用户 Scott,从而使职责性成为安全基础架构可行性的主要组成部分。

通常情况下,要使用该方法锁定程序,您应当撤消 SCOTT 的权限。当需要更改程序时,您可以再次赋予该权限(即允许 SCOTT 更改程序),然后再次撤消该授权。

可以肯定的是,这并不是一个处理安全性的巧妙方法。很快您就会遇到问题 - 权限管理并不像“每个对象一个用户”那样简单。在典型的数据库基础架构中,数以百计的用户将获得数以千计的对象的多种类型的权限。撤消权限将消除复杂的依赖关系并带来令人头痛的管理问题。

一个可管理性更高的解决方案是使用 DDL 触发器。使用此方法,您可以根据需要建立授权,但通过 DDL 触发器控制更改。

例如,假设您想要保护模式 ARUP 中一个名为 SECURE_PKG 的程序包。您将创建一个 DDL 模式触发器,如下所示:

1  create or replace trigger no_pkg_alter
2  before ddl
3  on arup.schema
4  begin
5     if (
6          ora_dict_obj_name = 'SECURE_PKG'
7          and
8          ora_sysevent = 'CREATE'
  9     )
10     then
11          raise_application_error (-20001,'Can''t Alter SECURE_PKG');
12     end if;
13  end;
 14  /

在第 6 行和第 8 行中,您检查是否对该程序包进行了更改。注意,对程序包的更改是由 create or replace package 语句做出的;因此,检查的事件是 create。如果您要确保表不受更改,可以在该值中使用 alter。在第 11 行中,当程序包被更改时将产生错误。

设置该触发器后,当拥有权限的用户尝试更改此程序包,甚至当对象的拥有者 (ARUP) 尝试通过运行程序包创建脚本重新创建该程序包时:

create or replace package secure_pkg

他将收到错误:

ERROR at line 1:
ORA-00604:error occurred at recursive SQL level 1
ORA-20001:Can't Alter SECURE_PKG
ORA-06512:at line 8

如果您确实要修改此程序包,可以请求 DBA 通过禁用触发器对它解锁:

alter trigger no_pkg_alter disable
/ 

现在,程序包创建脚本将开始运行。完成运行后,请求 DBA 启用触发器以将其锁定。基础权限保持不变。即便当您允许模式拥有者登录并修改他们所拥有的对象时,该方法也会保护这些对象。此策略支持对更改管理采用一种二人方法。

可能的影响
无,只要每个人都知道当对象准备更改时,DBA 必须解除对象锁定即可。如果您在正式的更改控制过程中加入了此步骤,它将以最主动的方式对可靠性产生影响。

操作计划

  1. 为所有应锁定的对象创建一个列表。注意,并非所有对象都需要进行如此严格的控制,例如,应用程序所有者为保存中间值而创建的临时表就不需要。
  2. 根据列表中的所有这些对象名称创建触发器。使该触发器在初始状态下处于禁用状态。不要将此功能添加到现有触发器中。您应该能够独立控制此触发器。
  3. 标识应解除对象的用户。该用户也许是您。
  4. 记录应何时锁定和解除锁定对象、工作流等。
  5. 启用该触发器。

 


3.5 创建数据库用户的配置文件

背景
在设计任何安全性系统时,最初都应彻底、准确地了解用户如何访问该系统及其访问模式,否则您将没有比较“基线”。作为一名 DBA,您应了解用户及其应用程序和访问机制(如访问源、涉及的 DDL 等)。

策略
在这种情况下使用 Oracle 审计将非常方便。您不必编写大量登录/注销触发器以及复杂的 PL/SQL 代码片断。相反,只需在数据库初始化参数文件中设置以下参数即可启用审计:

audit_trail = db 

然后重新利用数据库。设置后,请以 DBA 用户的身份执行以下命令。

audit session;

该语句将对所有会话级的活动(如登录和注销)启用审计。它至少显示了登录用户、登录时间、登录源自的终端、IP 地址、主机等等。

打开审计后,可以通过执行以下 SQL 监视活动。

select to_char(timestamp,'mm/dd/yy hh24:mi:ss') logon_ts,
username,
os_username,
userhost,
terminal,
to_char(logoff_time,'mm/dd/yy hh24:mi:ss') logoff_ts
from dba_audit_trail
where logoff_time is not null;

示例输出如下:

LOGON_TS           USERNAME        OS_USERNAM USERHOST        TERMINAL        LOGOFF_TS
------------------ --------------- ---------- --------------- --------------- ------------------
01/11/06 20:47:06  DELPHI          sgoper     stcdelpas01     unknown         01/11/06 20:48:46
01/11/06 20:48:21  DELPHI          sgoper     stcdelpas01     unknown         01/11/06 20:48:38
01/11/06 20:48:41  DELPHI          sgoper     stcdelpas01     unknown         01/11/06 20:49:19
01/11/06 20:36:03  STMT            crmapps    stcdwhpd        pts/3           01/11/06 20:36:03
01/11/06 20:36:04  STMT            crmapps    stcdwhpd        pts/3           01/11/06 20:37:40

从该输出中您可以清楚地看到连接到数据库的用户 ID、他们的 OS 用户 ID (OS_USERNAME) 以及他们注销的时间。如果他们从与数据库服务器相同的服务器中连接,则他们的终端 ID 将显示在 TERMINAL 列的下方 (pts/3)。如果他们从其他服务器连接,则此终端 ID 将显示在 USERHOST 列 (stcdelpas01) 中。

了解如何显示该信息后,可以构造查询来获得更有用的信息。例如,一个典型的问题是“用户通常从哪些计算机连接?”以下 SQL 语句将快速获得答案:

select userhost, count(1)
from dba_audit_trail
group by userhost
order by 2
/
审计最佳实践

您在本文已经了解了如何使用审计实施某些基础级别的职责。但该方法有一个很大的限制:您必须通过设置初始化参数 AUDIT_TRAIL 来启用审计。该参数不是动态的;因此要启用它,必须重新利用数据库。但如果计划所需的中断比较困难(对于很多 DBA 而言比较困难),那么您将采用哪些方法?

我在创建数据库时始终将该参数设置为 DB(针对 Oracle9i 和更高版本)和 DB_EXTENDED(针对 Oracle 数据库 10g)。且慢,这样做是否会启用审计并填满 SYSTEM 表空间中的 AUD$ 表,从而导致数据库中断?

不会,将 AUDIT_TRAIL 设置为某个值不会启用审计。它只是为审计准备数据库 - 指定将跟踪写入到的位置(如写入到 OS 或数据库)、已完成的审计量和类型以及格式是否为 XML(在 Oracle 数据库 10g 第 2 版中引入)。

要启用审计,必须对对象使用 AUDIT 命令。例如,使用以下命令对表 credit_cards 开始进行审计。

audit select, insert, update, delete on ccmaster.credit_cards;

创建数据库时设置参数 AUDIT_TRAIL 还使您可以针对安全性以外的原因捕获审计,如收集有关会话使用的 CPU 和 IO 的信息(该信息将输入到资源管理器中)。因此,当您下次重新启动数据库时,请先设置 AUDIT_TRAIL 参数。

示例输出可能如下所示(直到输出结尾):

USERHOST          COUNT(1)
--------------- ----------
stccampas01            736
stcdwhpd              1235
stcdelpas01           2498

您可以看到,该输出表明大多数连接均来自客户机 stcdelpas01,而下一个最大连接数来自 stcdwhpd(数据库服务器本身的名称)。您可能对此感到吃惊,因为您可能已经假设连接来自外部。

下一个问题可能是:“哪个用户直接从服务器访问数据库?”另一个 SQL 片断将为您提供该信息:

select os_username, username, count(1)
from dba_audit_trail
where userhost = 'stcdwhpd'
group by os_username, username
order by 3
/

示例输出:

OS_USERNAME USERNAME COUNT(1)
----------- -------- --------
oracle      SYS           100
oracle      DBSNMP        123
oracle      PERFSTAT      234
infrap      DW_ETL       1986

该输出清楚地表明 OS 用户 infrap 在服务器本身中运行了某个程序并以 DW_ETL 的身份连接。这是否正常?请询问该用户。如果未收到合理的响应,则应收集更多信息。关键是要知道有关用户的所有信息:他们的身份、他们来自哪里以及他们执行了什么操作。

另一个可以从审计跟踪中获得的重要信息部分是关于过去可能进行的攻击的证据。当恶意攻击者发起攻击时,他可能不会每次都获得正确的口令,因此他可能采用强行攻击方法,即不断尝试猜测口令,然后登录。

可以通过从审计跟踪中标识用户名/口令组合的模式来检测此类攻击。线索体现在 RETURNCODE 列,该列存储用户在进行连接尝试时引发的 Oracle 错误代码。如果提供了错误口令,则用户将引发以下错误:

ORA-1017:invalid username/password; logon denied

因此,应查找 ORA-1017,如以下 SQL 语句所示:

select username, os_username, terminal, userhost, 
to_char(timestamp,'mm/dd/yy hh24:mi:ss') logon_ts
from dba_audit_trail
where returncode = 1017;

下面是一个示例输出:

USERNAME        OS_USERNAM TERMINAL        USERHOST        LOGON_TS
--------------- ---------- --------------- --------------- ------------------
ABCD_APP        jnelson    STJNELSONT40    STJNELSONT40    01/11/06 10:42:19
ABCD_APP        jnelson    STJNELSONT40    STJNELSONT40    01/11/06 10:42:28
ABCD_APP        jnelson    STJNELSONT40    STJNELSONT40    01/11/06 10:43:11
PERFSTAT        oracle     pts/5           stcdwhpd        01/11/06 12:05:26
ARUP            jnelson    STANANDAT42     STJNELSONT40    01/11/06 14:09:20
ARUP            jnelson    STANANDAT42     STJNELSONT40    01/11/06 14:23:41

在该输出中,您可以清楚地看到哪个用户曾尝试使用错误口令进行连接。许多尝试可能属于正常的错误,而其他尝试可能需要调查。例如,OS 用户 jnelson 在短时间内从同一客户机以 ABCD_APP 的身份重复尝试登录并失败。紧接着,jnelson 尝试以用户 ARUP 的身份登录。现在,这一点比较可疑。注意,由于大多数攻击均来自企业内部的合法用户,因此任何模式都不值得掩盖。

在相同代码行中,您可以监视使用可能已“猜中”的用户 ID 尝试进行的登录。

select username from dba_audit_trail where returncode = 1017
minus
select username from dba_users;

输出如下:

USERNAME
---------------
A
SCOTT
HR

此处,某人尝试以不存在的用户身份(即 SCOTT,您已经审慎地从数据库中删除了该用户)登录。该用户的身份到底如何呢?他是错误地期望连接到开发数据库的无恶意用户,还是试探 SCOTT 是否存在的恶意用户?请再次搜索模式并标识进行此尝试的实际用户。直到您获得满意的解释为止。

可能的影响
打开审计确实会影响性能。但您在该步骤中启用的初级审计对性能的影响可以忽略不计,它的好处远远超过了不利影响。

另一个应仔细考虑的影响是审计跟踪的存储空间。审计跟踪条目存储在 SYSTEM 表空间中,其大小随审计跟踪的扩大而扩大。如果 SYSTEM 表空间已经占满并且没有可供审计记录使用的空间,则所有数据库交互将失败。因此,必须仔细留意可用空间。

操作计划

  1. 将初始化参数 audit_trail 设置为数据库中的 DB 并重新利用它。
  2. 对会话启用审计。
  3. 从审计跟踪中提取信息并根据这些信息分析攻击模式。

 


3.6 创建和分析对象访问配置文件

背景
只知道用户名和相关属性(如 OS 用户名、他们的连接源自的终端等)是不够的。要正确锁定数据库,还必须知道哪些用户正在访问。您可以通过此信息创建一个对象“访问配置文件” - 凡是不符合该信息的内容均可能表示攻击或入侵,

策略
此处将再次使用审计的强大功能。在上一步中,您启用了用于查看会话详细信息的会话级审计。现在,您必须启用对象访问审计。

例如,您可以选择对非常机密的对象(如存储信用卡卡号的表或通过加密值返回明文信用卡卡号的属性)进行的访问进行审计。

假设您要对访问 ccmaster 拥有的表 credit_cards 的任何用户进行审计。您可以发出以下命令

audit select on ccmaster.credit_cards by access;

随后,任何从该表中进行选择的用户将留下一个审计跟踪。

您可以采用两种方法记录该信息。在第一种方法(如上面的关键字 access 所示)中,每当某个用户从表中进行选择时,审计跟踪中便会出现一个记录。如果同一用户在同一会话中从表中选择两次,则审计跟踪中将出现两个记录。

如果该信息量太大,无法处理,则可以使用另一个方法,即在每个会话中只记录一次:

audit select on ccmaster.credit_cards by session;

在该示例中,当用户在会话中从表中进行多次选择时,审计跟踪中将只出现一个记录。

启用审计后,可以分析审计跟踪以了解访问模式。

在每个方法中,审计跟踪均呈现不同的状态。如果会话启用了审计,则每个对象的每个会话中将只显示一个记录。该示例中的 action_name 列将显示 SESSION REC,且操作将记录到 ses_actions 列中。

select username, timestamp, ses_actions
from dba_audit_trail
where obj_name = 'CREDIT_CARDS'
and action_name = 'SESSION REC'
/	

输出结果如下:

USERNAME                       TIMESTAMP SES_ACTIONS
------------------------------ --------- -------------------
ARUP                           16-JAN-06 ---------S------

当然,您还可以使用其他列,如 os_usernameterminal 等。

注意,ses_actions 列显示了一系列的连字符和一个字母“S”。这表示用户 ARUP 执行了某些操作,这些操作记录在审计跟踪的单个记录中。值遵循某个模式,其中的每个位置均表示一个特定操作:

位置

操作

1

更改

2

审计

3

注释

4

删除

5

授权

6

索引

7

插入

8

锁定

9

重命名

10

选择

11

更新

12

引用

13

执行

14

未使用

15

未使用

16

未使用

在以上示例中,ses_actions 显示了以下内容:

 ---------S------ 

“S"”位于第 10 个位置,表示用户 ARUP 从表 credit_cards 中进行了选择。但它并未显示用户在此会话中从该表进行选择的频率,这是因为您只对会话而非访问启用了审计。如果用户还在查询中执行了插入和更新操作,则列值将为:

------S--SS----- 

注意,第 7 个位置 (Insert)、第 10 个位置 (Select) 和第 11 个位置 (Update) 分别有一个 S。

为什么会显示“S”?启用审计时,可以指定在访问成功或失败时是否记录跟踪。例如,如果只在访问由于某种原因(如权限不足)而失败的情况下记录审计跟踪,可以按如下所示启用审计。

audit select on ccmaster.credit_cards by session whenever not successful; 

随后,当用户 ARUP 成功地从表中进行选择时,审计跟踪中将没有记录。如果访问失败,则将有一个记录。这种情况下,ses_actions 列中的字母将为“F”(表示失败)。

同样,如果只想在访问成功时进行审计,请将子句“whenever not successful”替换为“whenever successful”。默认情况下,如果未指定该子句,则将同时记录成功和失败的访问。那么,如果在单个会话中,某些访问成功,而其他访问失败,则将出现什么情况?这种情况下字母将为“B”(表示成功和失败)。

例如,下面演示了对于用户 ARUP(他没有表 credit_cards 的选择权限)而言,字母值如何随时间而更改。

  1. ARUP 执行命令语句 select * from CCMASTER.CREDIT_CARDS
  2. 该语句失败,从而引发 ORA-00942:table or view does not exist
  3. 审计跟踪中出现一个记录,且 ses_actions 值为 ---------F------。(注意,“F”位于第 10 个位置,表示失败。)
  4. ARUP 未与会话断开连接。表 credit_cards 的拥有者 CCMASTERselect 权限授予 ARUP。
  5. ARUP 现在成功地从表中进行选择。
  6. ses_action 列值现在将更改为 ---------B------。(注意,第 10 位置已从“F”更改为“B”(成功和失败)。)

对该对象进行了一段时间的审计并开发了它的访问配置文件后,可以针对成功尝试关闭审计,并仅针对失败尝试启用审计。表示潜在攻击的通常是失败尝试。只对失败尝试进行审计还将降低审计跟踪的总长度。

如果按访问启用了审计,则可能使用了一个不同的查询,这是因为每个访问将有一个记录。ses_actions 列将不被填充,而 action_name 列将显示实际操作(如 selectinsert)而非值 SESSION REC。因此,您将使用:

col ts format a15
col username format a15
col userhost format a15
col action_name format a10
select to_char(timestamp,a€?mm/dd/yy hh24:mi:ssa€?) ts, 
username, userhost, action_name
from dba_audit_trail
where owner = 'CCMASTER'
and obj_name = 'CREDIT_CARDS';

TS                USERNAME   USERHOST        ACTION_NAM
----------------- ---------- --------------- ----------
01/16/06 00:27:44 ARUP       stcdwhpd        SELECT
01/16/06 11:03:24 ARUP       stcdwhpd        UPDATE
01/16/06 12:34:00 ARUP       stcdwhpd        SELECT

注意,每个访问(selectupdate 等)均有一个记录,这将为您提供更高的粒度来建立访问模式 - 这与会话级审计相反,该审计只显示 ARUP 从表 credit_cards 中执行了选择和更新操作,但未显示操作次数或时间。

既然如此,应使用哪种类型的审计 - 会话级还是访问级?注意,由于访问级审计针对每个访问写入一个记录,因此写入的审计信息数量明显大于每个会话只写入一个记录时的信息数量。如果只尝试确定表的访问用户和访问方式,则应先打开会话级审计。这将使您可以了解用户如何访问每个对象。要跟踪特定用户的错误使用,可以打开访问级的审计。

可能的影响
根据前面的描述,审计不会影响性能。但审计的好处可能远远超过不利影响,尤其是当您巧妙地启用它时。此外,您不必始终打开它;您可以根据需要动态打开或关闭对象审计。

操作计划

  1. 在不审计所有对象的情况下,标识要审计的主要对象(表、程序包、视图)
  2. 对这些对象打开会话级审计。
  3. 一段时间之后(您认为该段时间代表典型的工作周期),分析审计跟踪。等待收集记录的时间通常取决于特定情况。例如,在零售业中,您可能要等待一个月的时间,在这段时间内通常会捕获所有过程,如月终处理、帐目汇总等。
  4. 开发配置文件后,请跟踪失败尝试。记录用户以及他们尝试访问的对象。
  5. 关闭会话级审计并只对这些对象打开访问级审计。
  6. 通过突出显示失败尝试、时间、尝试源自的终端等信息来分析访问模式,并确定尝试失败的原因。如果没有合理的原因,请将该尝试视为潜在的安全漏洞。

 


3.7 对未来对象启用审计

背景
到现在为止,您已经了解了如何针对特定的机密对象使用审计。您还可能决定对所有对象而非对象子集启用审计 - 您并不知道哪些对象是机密对象,也许它们全部是机密对象。这种情况下,将出现如下问题:不断在数据库中创建对象,并在对象物化时,您必须记住对它们启用审计。

策略
默认审计在此处非常有用。要对任何尚未创建的对象启用审计,请执行以下命令:

audit select on default by session; 

随后,当您在任何模式中创建表时,将对该表的 select 自动启用审计选项。要检查在数据库中当前设置的默认审计选项,请执行以下语句:

SQL> select * from all_def_audit_opts;

ALT AUD COM DEL GRA IND INS LOC REN SEL UPD REF EXE FBK REA
--- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
-/- -/- -/- -/- -/- -/- -/- -/- -/- S/S -/- -/- -/- -/- -/-

注意 SEL 列下有一个值“S/S”。左侧值表示操作成功时的审计选项。此处该值为“S”,表示“会话级”。右侧部分指示操作何时失败,值也显示为“S”(也表示会话级)。由于您未指定应何时执行审计,从而为成功和失败设置了选项 - 因此值为“S/S”。

假设您要在成功时在会话级以及在失败时在访问级对 select 启用默认审计。您将执行下面的语句:

SQL> audit select on default by session whenever successful;

Audit succeeded.

SQL> audit select on default by access whenever not successful;

Audit succeeded.

现在,如果您查看默认选项,则将看到以下语句:

SQL> select * from all_def_audit_opts;

ALT AUD COM DEL GRA IND INS LOC REN SEL UPD REF EXE FBK REA
--- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
-/- -/- -/- -/- -/- -/- -/- -/- -/- S/A -/- -/- -/- -/- -/-

此处,请注意列 SEL,该列显示“S/A” - 表示在成功时为会话级(“S”,位于“/”的左侧),在失败时为访问级(“A”,“/”的右侧)。

当您要限制成功访问下的审计条目数时,这样的安排将比较常见,因此对成功访问启用会话级审计。但由于您要跟踪出现的每个失败访问,因此对失败启用了访问级审计。

要禁用默认审计,请执行以下语句:

noaudit select on default;

稍后,您应签入 all_def_audit_opts 视图以确保实际上关闭了默认审计选项。

可能的影响
在许多审计中,始终存在性能方面的问题,但针对其中包含的信息而言,代价可能比较小。

但其中也存在一个潜在的危险。由于对随后创建的所有对象均启用了默认审计而与创建它们的用户以及从中进行选择的用户无关,因此作为 DBA 的您将无法控制表的审计选项。恶意攻击者可能会利用这种情况,他可以随意创建对象、插入到对象中、从对象中进行选择,并最终删除对象 - 而所有这些操作恰好在表空间级强制使用的份额中发生。

但由于对每个创建的对象均打开了审计,因此审计跟踪中的记录不断增多,并最终填满 AUD$ 表。由于该表位于 SYSTEM 表空间中,因此它最终将被填满并终止数据库,这实际上相当于创建了一个拒绝服务攻击!

尽管这种情况很少出现,但却完全有可能出现。幸运地是,防范方法比较简单:只需密切监视 SYSTEM 表空间。如果空间很快耗尽,请调查一下审计记录的创建为何如此之快。如果看到大量创建或选择的对象,而这些对象并不属于使用审计构建的配置文件,则必须进行调查。

作为一个立杆见影的措施,您可以关闭默认审计,然后关闭对那些填满审计跟踪条目的对象的审计(可以联机执行)。然后,在将其存储到其他表空间中的某个表之后,您应删除审计跟踪中的记录以便将来分析。

操作计划

  1. 确定执行哪些操作来启用默认审计。
  2. 确定所需的默认审计级别 - 会话级或访问级。
  3. 启用默认审计。

 


3.8 只限制来自特定节点的访问

背景
在许多情况下,只有指定的客户机集将连接到数据库服务器。以下是一个典型的体系结构:

 

 

此处,数据库服务器为 findb01 和 hrdb01,且数据库名为 FINDB(财务数据库)和 HRDB(HR 数据库)。HR 部门中的客户机只连接到 HRDB;如果它们需要 FINDB 中的某些数据,则连接到在财务部门的服务器上运行的应用程序并获取数据。同样,财务部门中的应用服务器从不直接连接到 HRDB。

如果财务部门中的客户机 finas01 尝试连接到 HRDB,则将出现什么情况?只要它知道有效的用户 ID 和口令,便可以成功连接。通常,您应保护用户的口令,但有时存在一些使用已知口令的普通用户。例子包括使用不安全口令(如“hrapp”、 “password”甚至“abc123”)的应用程序用户。即使实施了口令管理策略(如第 4 阶段所述),口令仍有可能是为人所熟知的。

因此,必须在服务器周围构建一个防护墙,以防计算机授权列表以外的客户机连接到这些服务器。

策略
如何确保只允许来自 HR 部门的客户连接进入数据库 HRDB?方法有两种,即登录触发器和监听器节点验证。

登录触发器。在该方法中,您将创建一个触发器,它在登录时引发,检查 IP 地址,然后当 IP 地址不在允许的计算机列表中时失败。此触发器如下所示:

1  create or replace trigger valid_ip
2  after logon on database
3  begin
4    if sys_context('USERENV','IP_ADDRESS') not in (
  5      '100.14.32.9'
6    ) then
7         raise_application_error (-20001,'Login not allowed from this IP');
8    end if;
9* end;

在第 5 行中,您可以设置有效客户机的所有 IP 地址(括在引号中并由逗号分隔)。在此触发器生效后,当 SCOTT 尝试从触发器列表以外的 IP 地址连接时:

$ sqlplus scott/tiger@hrdb


ERROR:
ORA-00604:error occurred at recursive SQL level 1
ORA-20001:Login not allowed from this IP
ORA-06512:at line 5

注意错误 ORA-20001:Login not allowed from this IP,该错误置于触发器中。您可以根据需要使此消息具备说明性。还可以使触发器更强大,以收集有用信息(如将类似尝试记录在表中)。

但请注意一个非常重要的问题:由于登录触发器不会对 DBA 用户触发,因此不要在启用 DBA 角色的情况下禁止某人以用户身份登录。该风险并非想象那样恐怖;实际上,您可能需要让 DBA 从任何客户机登录。

监听器节点验证。另一个方法是在监听器本身禁用登录尝试。监听器禁止指向数据库服务器的连接尝试,因此并不需要触发器。要启用节点验证,只需在服务器 hrdb01 上的文件 $ORACLE_HOME/network/admin/sqlnet.ora 中设置以下行。

tcp.validnode_checking = yes 
tcp.invited_nodes = (hrdb01, hras01, hras02)

此处,您已经指定了允许连接到监听器的客户机(hras01 和 hras02)。还可以将主机名指定为 IP 地址。将所有节点名称置于由逗号分隔的单个不中断行中(非常重要)。别忘了添加数据库服务器名称 (hrdb01)。

重新启动后,如果客户端尝试从 hras01hras02 以外的计算机登录,则将收到错误

$ sqlplus scott/tiger@hrdb

ERROR:
ORA-12537:TNS:connection closed

这个非常不直观的错误是由在监听器级发生的过滤导致的。当监听器本身终止连接尝试时,您将收到 connection closed 错误。即使用户具有 DBA 角色也会出现该错误,这是因为该尝试尚未到达数据库。

节点验证是一个非常强大的特性。有关该特性的详细信息,请阅读我撰写的 DBAzine 文章“使用 Oracle Net 构建一个简单的防火墙”。

因此,您应选择哪个方法来防止多余的客户端连接?下面我们将介绍一下这两个方法的优点和缺点。

  • 节点验证在监听器级进行,因此将禁止所有用户连接 - 即使具有 DBA 角色的用户也不例外。而这可能并不是所需的。例如,如果您在台式机上安装了一个 DBA 工具并且您的台式机启用了 DHCP(每当该台式机连接到网络时将分配一个新的 IP),则无法将 IP 地址置于有效节点列表中;因此,您将无法连接。
  • 节点验证需要重新启动监听器。监听器将在短时间内关闭,因此客户端将无法连接。尽管这可能算不上是问题,但您应该注意它。每当更改有效节点列表时,您必须要重新启动监听器。
  • 如果要临时禁用节点验证,则应将 tcp.valid_node_checking=no 置于文件 sqlnet.ora 中并重新启动监听器。对于登录触发器而言,您所要做的就是禁用触发器。您可以在需要时重新启用它。
  • 在节点验证中,可以将所有允许的客户端置于一行中,但只能置于一个不中断行中。如果该列表太长无法放在一行中,则您将无法使用该方法。而触发器方法几乎没有限制。您也可以使用另一个名为连接管理器的特性来限制长度超过一行的 IP 地址。
  • 必须在节点验证中使用特定 IP 地址或主机名 - 不要使用“10.20.%.%”这样的通配符,因为它们表示子网 10.20 中的所有客户端。在触发器方法中,您可以使用通配符也可以使用连接管理器。
  • 通过触发器方法,您可以构建一个复杂的跟踪系统,以针对所有尝试(成功或被拒绝)写入某个跟踪表。而节点验证中不存在这样的功能。
  • 在触发器方法中,您可以根据 IP 以外的参数(如一天中的某个时间、用户连接等)控制访问。节点验证只读取 IP 地址。
  • 注意,节点验证禁止监听器级的尝试;而数据库连接尚未尝试。因此,如果已经针对失败的尝试启用了审计,则它们将不被注册。
  • 由于节点验证在监听器级别起作用,因此潜在的恶意攻击者甚至不会进入数据库,从而使拒绝服务攻击变得更困难。这对节点验证而言是一个巨大的好处。

您在考虑以上差别后应确定方法。通常情况下,如果您的目标只是禁止来自 IP 地址的连接,而不使用任何其他功能(如跟踪这些失败的尝试),则节点验证是一个快速、简单的方法。如果需要更复杂的功能,则应查看登录触发器。

如何知道要阻止哪些 IP 地址以及允许哪些 IP 地址?也许此假设太简单;实际上,客户机的列表将很长并很难攻击。在此处使用前面的调查将比较方便。注意,在第 2 阶段,您通过查看监听器日志捕获了用户连接源自的 IP 地址。在该步骤中,您一定已经生成了一个有效的客户端 IP 地址或主机名列表。该列表就是您需要知道的。

可能的影响
可能的影响可能比较严重;如果尚未执行您的操作,则可能阻止合法客户端。

操作计划

  1. 从第 2 阶段的第 1 步中,获得客户机的有效 IP 地址或主机名的列表。
  2. 确定要使用的方法 - 基于触发器或节点验证。
  3. 实施该计划。
  4. 密切监视几天,最好是整个周期(如一个月或一周),这对您的企业比较适合。
  5. 通过添加或删除过滤的节点微调该方法。

第 3 阶段的清单

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值