
本文将介绍 DBMS_NETWORK_ACL_ADMIN 包(11.x 的新特性),并提供了一些关于如何手动设置和检查权限的示例,通过 ACL,Oracle 为用户访问外部网络资源提供了更细粒度的访问控制。
UTL_MAIL、UTL_SMTP、UTL_HTTP、UTL_TCP 等包允许在数据库服务器之外与外部世界进行通信,但是当被授予访问权限时,所有主机都可以被访问。这可以解释为一个安全漏洞,因为例如使用 UTL_TCP 时不需要登录,建议 DBA 撤销 public 对这些类型的包的执行权限。
从 Oracle 11g 开始,引入了访问控制列表,您不仅可以通过授予权限来控制谁可以访问这些包,现在还可以控制他们可以调用哪些资源,我们可以根据主机和端口号来控制可访问性。
总之,这些是步骤:
创建 ACL – 设置用户所需的权限。 将 ACL 分配给网络。 测试 UTL_ 包。
创建 ACL
ACL 是一个 XML 文件,其中列出了授予用户的权限,此 XML 存储在 Oracle XML DB 中。确保已安装。以“SYS AS SYSDBA”身份登录,首先创建一个测试用户
CREATE USER [USER] IDENTIFIED BY [PWD];
GRANT CONNECT TO [USER];
创建一个 ACL – 并为 [USER] 授予“连接”权限(有关以下权限的更多信息),注意 COMMIT 需要保存更改。
BEGIN
DBMS_NETWORK_ACL_ADMIN.CREATE_ACL(acl => 'ACL_TEST.xml',
description => 'ACL FOR TEST PURPOSES',
principal => [USER],
is_grant => true,
privilege => 'connect',
start_date => null,
end_date => null );
COMMIT;
END;
/
acl – ACL 文件的名称(它作为 XML 文件存储在 XDB 中定义的“/sys/acls”中)。重要的是,这是区分大小写的。 主体– 要授予/拒绝特权的数据库用户或角色。 is_grant – true(授予)或 false(拒绝)。 特权– “连接”或“解决”(这是区分大小写的),Connect用于外部网络,在使用 UTL_TCP、UTL_HTTP、UTL_SMTP 和 UTL_MAIL 时需要,解决用于将主机名解析为 IP 地址的 UTL_INADDR(反之亦然),还有其他值,例如在使用钱包时,“use-passwords”授予用户在钱包中使用密码的权限。“use-client-certificates”使用钱包中的客户端证书对用户进行身份验证。 start_date和end_date是可选的。
验证是否使用正确的权限创建了 ACL
检查是否已创建 ACL 并使用“CHECK_PRIVILEGE”为您的用户授予连接权限。
SELECT DECODE(
DBMS_NETWORK_ACL_ADMIN.check_privilege('ACL_TEST.xml', [USER], 'connect'),1, 'GRANTED', 0, 'DENIED', NULL) privilege
FROM dual
/
PRIVILE
-------
GRANTED
使用 ADD_PRIVILEGE 添加额外权限(可选)
ADD_PRIVILEGE 可用于为其他用户添加权限,它还可以用于为同一用户添加相同的权限。例如:
为我们的用户 [USER] 添加“连接”权限但拒绝访问,您将首先添加另一个 ACE(访问控制实体)。请注意,可选的“位置”参数允许您为用户定义额外的权限。
BEGIN
DBMS_NETWORK_ACL_ADMIN.ADD_PRIVILEGE(acl => 'ACL_TEST.xml',
principal => [USER],
is_grant => false,
privilege => 'connect',
position => 1);
COMMIT;
END;
/
--use check_privilege as show above.
PRIVILE
-------
DENIED
这是正确的,因为添加了第二个 ACE。位置“空”是默认值,位置 1 覆盖相同的权限,但值为“假”。特权是从最高值中选择的(例如,在本例中为 1)。
请务必删除刚刚添加的最后一个 ACE – 以恢复我们在“连接”上的初始权限 (true)。
BEGIN
DBMS_NETWORK_ACL_ADMIN.DELETE_PRIVILEGE(acl => 'ACL_TEST.xml',
principal => ,
is_grant => false,
privilege => 'connect');
COMMIT;
END;
/
注意:使用带有“is_grant” = null 的 DELETE_PRIVILEGE 删除该权限的所有 ACE(只要这不留下空的 ACL –ora-24246)。
可选:要继续此演示,请不要删除 ACL,这仅显示需要时的语法
BEGIN
DBMS_NETWORK_ACL_ADMIN.DROP_ACL (
acl => 'ACL_TEST.xml' );
COMMIT;
END;
/
将 ACL 分配给网络
ACL 需要分配给网络主机。下面的示例使用主机 www.abc.com,对于 UTL_SMTP,这将是您的邮件服务器主机。
BEGIN
DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL (
acl => 'ACL_TEST.xml',
host => 'www.abc.com',
lower_port => null,
upper_port => null);
COMMIT;
END;
/
主机——任何主机只能分配一个 ACL——但通配符可用于域或 IP 地址。尝试将另一个 ACL 分配给同一主机将替换现有的 ACL。如果您定义“www.abc.com”的主机,则使用的 ACL 将优先于分配给“.abc.com”的任何主机,后者又优先于“”,同样适用于IP 地址。例如“1.2.3.4”的ACL将在“1.”或“”之前使用
可选– 要继续此演示,请不要取消分配 ACL。这仅显示需要时的语法
BEGIN
DBMS_NETWORK_ACL_ADMIN.UNASSIGN_ACL (
acl => 'ACL_TEST.xml',
host => 'www.abc.com',
lower_port => null,
upper_port => null);
COMMIT;
END;
/
检查是否已分配 ACL:
col host format a30
col acl format a30
set pagesize 999
SELECT host, acl, lower_port, upper_port
FROM DBA_NETWORK_ACLS
/
HOST ACL LOWER_PORT
------------------------------ ------------------------------ ----------
UPPER_PORT
----------
www.abc.com /sys/acls/ACL_TEST.xml
myproxy.abc.com /sys/acls/ACL_TEST.xml
此外,您可以使用视图“DBA_NETWORK_ACL_PRIVILEGES”或使用“USER_NETWORK_ACL_PRIVILEGES”为用户检查与 ACL 关联的权限:
column acl format a30
column principal format a20
SELECT acl,
principal,
privilege,
is_grant,
to_char(start_date) ,
to_char(end_date)
FROM dba_network_acl_privileges
/
ACL PRINCIPAL PRIVILE IS_GRANT
------------------------------ -------------------- ------- --------------------
TO_CHAR(START_DATE)
----------------------------------------------------------------------
TO_CHAR(END_DATE)
----------------------------------------------------------------------
/sys/acls/ACL_TEST.xml USER connect true
最后,这是通过 ACLID 检查您的权限的替代选择:
col acl format a30
col host format a30
SELECT acl,
host,
DECODE(
DBMS_NETWORK_ACL_ADMIN.check_privilege_aclid(aclid, , 'connect'),
1, 'GRANTED', 0, 'DENIED', NULL) privilege
FROM dba_network_acls
/
ACL HOST PRIVILE
------------------------------ -------------------- -------
/sys/acls/ACL_TEST.xml www.abc.com GRANTED
/sys/acls/ACL_TEST.xml myproxy.abc.com GRANTED
测试 ACL
使用 UTL_HTTP 的简单测试。注意:更改代理服务器以反映正确的值。
DECLARE
req UTL_HTTP.REQ;
resp UTL_HTTP.RESP;
value VARCHAR2(32200);
BEGIN
UTL_HTTP.SET_PROXY('myproxy.abc.com','uk.abc.com');
req := UTL_HTTP.BEGIN_REQUEST('http://www.abc.com');
resp := UTL_HTTP.GET_RESPONSE(req);
LOOP
UTL_HTTP.READ_LINE(resp, value, TRUE);
DBMS_OUTPUT.PUT_LINE(value);
END LOOP;
--
UTL_HTTP.END_RESPONSE(resp);
EXCEPTION
WHEN UTL_HTTP.END_OF_BODY THEN
begin
DBMS_OUTPUT.PUT_LINE('Finished');
UTL_HTTP.END_RESPONSE(resp);
end;
END;
/





