暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

一篇文章带你了解Oracle 11G 中的访问控制列表 (ACL)

运维漫谈 2021-12-12
4087

本文将介绍 DBMS_NETWORK_ACL_ADMIN 包(11.x 的新特性),并提供了一些关于如何手动设置和检查权限的示例,通过 ACL,Oracle 为用户访问外部网络资源提供了更细粒度的访问控制。

UTL_MAIL、UTL_SMTP、UTL_HTTP、UTL_TCP 等包允许在数据库服务器之外与外部世界进行通信,但是当被授予访问权限时,所有主机都可以被访问。这可以解释为一个安全漏洞,因为例如使用 UTL_TCP 时不需要登录,建议 DBA 撤销 public 对这些类型的包的执行权限。

从 Oracle 11g 开始,引入了访问控制列表,您不仅可以通过授予权限来控制谁可以访问这些包,现在还可以控制他们可以调用哪些资源,我们可以根据主机和端口号来控制可访问性。

总之,这些是步骤:

  1. 创建 ACL – 设置用户所需的权限。
  2. 将 ACL 分配给网络。
  3. 测试 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;
/

文章转载自运维漫谈,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论