首页 > 数字化转型 > ERP > 这是安全性和合规性项目的第 3 阶段
在 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 脚本。该方法存在两个主要风险:
当我询问使用该方法的原因时,得到的答案几乎完全相同:因为以前的 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. 为实施挑选一种方法:
a. 在 SQL 脚本内部使用 Connect 命令
b. 在 shell 脚本内部使用 Connect 命令(无 SQL 脚本)
c. 使用口令文件
d. 使用 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 目录所有者口令的方法:
a. 在脚本内部使用 Connect 命令
b. 以 OS 验证的用户身份连接
2. 如果选择 b.,则
a. 对目录数据库启用远程 OS 验证(需要重新启动)。
b. 在目录数据库中启用节点验证,以拒绝除已知的少数几个节点之外的所有节点。
c. 创建名为 OPS$ORACLE 的用户。
d. 修改 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
您可以看到,以下作业:
现在,为将该作业转换为一个 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 而费心呢?实际上,原因是多方面的:
可能的影响无,只要作业与数据库相关。有一点可以肯定的是,即使当数据库不可用时,某些作业也必须运行 - 例如,将警报日志移动到不同的位置或检查数据库是否启动并正在运行的作业。这些作业应位于数据库的外部以及 cron 的内部。
操作计划
1. 标识 cron 中的数据库作业。
2. 确定即使在数据库关闭时仍应运行的工作(例如:每天将监听器日志移动到其他位置的作业)
3. 对于其余的作业,创建 Scheduler 作业,这些作业最初通过在 CREATE_JOB 过程中声明 ENABLED=FALSE 而被禁用。
4. 使用 dbms_scheduler.run_job() 过程测试作业的执行情况。
5. 如果成功,则关闭 cron 作业并使用 dbms_scheduler.enable() 过程启用 Scheduler 作业。
3.4 锁定对象
背景程序包、过程、函数、类型主体以及对象方法等编程对象包含企业的业务逻辑。对它们所做的任何改动都可能会影响总体处理逻辑,并且根据其配置情况,对生产系统的影响可能是灾难性的。
许多企业通过实施一个安全的更改-控制过程来解决此问题。在此过程中,更改首先经过讨论和审批(理想情况下在至少两个人之间进行),然后才能实施。所面临的难题是让系统自动运行,这实际上也是许多辖区和行业中的要求。
策略这个安全的更改-控制过程可以按照以下方式运行:
鉴于 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
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/178357/viewspace-910007/ ,如需转载,请注明出处,否则将追究法律责任。