您可能熟悉 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 数据库 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 数据库 11 g 最好的新安全特性之一。