您的位置:首页 > 其它

记一次ORA-24247: network access denied by access control list (ACL)

2012-10-02 17:21 976 查看
这两天在测试使用UTL_SMTP发送邮件时,遇到了ORA-24247的错误:

Error report:

ORA-24247: network access denied by access control list (ACL)

ORA-06512: at "SYS.UTL_TCP", line 17

ORA-06512: at "SYS.UTL_TCP", line 267

ORA-06512: at "SYS.UTL_SMTP", line 161

ORA-06512: at "SYS.UTL_SMTP", line 197

ORA-06512: at line 9

我使用的数据库是11gR2,在11g的安全控制得到了进一步的提升,在使用工具包进行tcp连接时,Oracle数据库11g做了较为严格的控制。

Oracle 数据库 11g有一个新的解决方案:您可以将执行权限程序包授予任何人,但要控制他们可以调用的资源。例如,utl_tcp 可限制为仅调用几个 IP地址,这种机制称为访问控制列表 (ACL)。如果主机在 ACL 中,用户可以在 utl_tcp 中使用;但是仅仅拥有对 utl_tcp的执行权限是不够的。因此,恶意进程不可能取代 utl_tcp 程序包和建立非法连接。

那些所熟悉的 工具包有UTL_TCP、UTL_HTTP 和 UTL_SMTP等,它们支持数据库领域外的服务器之间的通信。例如,utl_tcp 用于在两台主机间建立 TCP/IP通信,而不是通过数据库链接。类似地,utl_http 用于从 Web 服务器发出 http 请求,utl_smtp 用于在主机间进行 SMTP邮件呼叫。

先看看两个使用acl控制tcp访问的例子:

普通用户,暂时未授予acl访问权限的用户,使用utl_http进行web请求时会出现ORA-24247的错误:

11:29:03 osdbso@SRCB> select utl_http.request('http://www.baidu.com') from dual;

select utl_http.request('http://www.baidu.com') from dual

*

ERROR at line 1:

ORA-29273: HTTP request failed

ORA-06512: at "SYS.UTL_HTTP", line 1722

ORA-24247: network access denied by access control list (ACL)

ORA-06512: at line 1

超级用户,或者是已授予了acl的用户,则可以使用utl_http进行web请求:

11:29:10 osdbso@SYS> select utl_http.request('http://www.baidu.com') from dual;

UTL_HTTP.REQUEST('HTTP://WWW.BAIDU.COM')

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

<!doctype html><html><head><meta http-equiv="Content-Type" content="text/html;charset=gb2312"><title>鐧惧害涓�涓嬶紝浣犲氨鐭ラ亾 </title><style>html{overflow-y:auto}body{font:12px arial;text-align:center;

background:#fff}body,p,form,ul,li{margin:0;padding:0;list-style:none}body,form,#fm{position:relative}td{text-align:left}img{border:0}a{color:#00c}a:active{color:#f60}#u{color:#999;padding:4px 10px 5px

0;text-align:right}#u a{margin:0 5px}#u .reg{margin:0}#m{width:720px;margin:0 auto;}#nv a,#nv b,.btn,#lk{font-size:14px}#fm{padding-left:110px;text-align:left}input{border:0;padding:0}#nv{height:19px

;font-size:16px;margin:0 0 4px;text-align:left;text-indent:137px;}.s_ipt_wr{width:418px;height:30px;display:inline-block;margin-right:5px;background:url(http://s1.bdstatic.com/r/www/img/i-1.0.0.png) n

o-repeat -304px 0;border:1px solid #b6b6b6;border-color:#9a9a9a #cdcdcd #cdcdcd #9a9a9a;vertical-align:top}.s_ipt{width:405px;height:22px;font:16px/22px arial;margin:5px 0 0 7px;background:#fff;outlin

e:none;-webkit-appearance:none}.s_btn{width:95px;height:32px;padding-top:2px\9;font-size:14px;background:#ddd url(http://s1.bdstatic.com/r/www/img/i-1.0.0.png);cursor:pointer}.s_btn_h{background-posit

ion:-100px 0}.s_btn_wr{width:97px;height:34px;display:inline-block;background:url(http://s1.bdstatic.com/r/www/img/i-1.0.0.png) no-repeat -202px 0;*position:relative;z-index:0;vertical-align:top}#lg i

mg{vertical-align:top;margin-bottom:3px}#lk{margin:33px 0}#lk span{font:14px "瀹嬩綋"}#lm{height:60px}#lh{margin:16px 0 5px;word-spacing:3px}.tools{position:absolute;top:-4px;*top:10px;right:7px;}#mHold

er{width:62px;position:relative;z-index:296;display:none}#mCon{height:18px;line-height:18px;position:absolute;cursor:pointer;padding:0 18px 0 0;background:url(http://s1.bdstatic.com/r/www/img/bg-1.0.0

.gif) no-repeat right -134px;background-position:right -136px\9}#mCon span{color:#00c;cursor:default;display:block}#mCon .hw{text-decoration:underline;cursor:pointer}#mMenu a{width:100%;h

接下来看看acl访问控制的工作原理,以及实现步骤:

1、使用dbms_network_acl_admin包创建一个ACL:

11:38:18 osdbso@SYS> begin

dbms_network_acl_admin.create_acl (

acl => 'myutltcpacl.xml',

description => 'Normal Access',

principal => 'CONNECT',

is_grant => TRUE,

privilege => 'connect',

start_date => null,

end_date => null

);

end;

PL/SQL procedure successfully completed.

注明此处,参数 principal => 'CONNECT' 表示该 ACL 适用于 CONNECT 角色。您可以在此处定义一个用户或角色。该 ACL 是作为一个 myutltcpacl.xml 文件创建的。还可以指定start_date和end_data两个参数来限定acl的有效期。

创建完毕后,您可以进行检查以确保该 ACL 已增加:

11:39:58 osdbso@SYS> SELECT any_path FROM resource_view WHERE any_path like '/sys/acls/%myutltcpacl.xml';

ANY_PATH

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

/sys/acls/myutltcpacl.xml

2、把acl权限授予需要的用户:

11:45:16 osdbso@SYS> begin

dbms_network_acl_admin.add_privilege (

acl => 'myutltcpacl.xml',

principal => 'SRCB',

is_grant => TRUE,

privilege => 'connect',

start_date => null,

end_date => null);

end;

/

PL/SQL procedure successfully completed.

其中,acl对应的参数myutltcpac.xml即为上一步中创建的acl权限文件,授予用户为SRCB,同样可以使用start_data和end_date来现在用户的acl访问期限。

3、设定acl限制的主机及其他信息:

11:50:36 osdbso@SYS> begin

dbms_network_acl_admin.assign_acl (

acl => 'myutltcpacl.xml',

host => 'www.baidu.com',

lower_port => 22,

upper_port => 55);

end;

/

PL/SQL procedure successfully completed.

本实例中表示,限定用户SRCB只能访问主机www.baidu.com,且只能访问www.baidu.com的22到55端口。如果此时想访问www.baidu.com的80端口则依然会出现ORA-24247的错误:

11:54:29 osdbso@SRCB> select utl_http.request('http://www.baidu.com') from dual;

select utl_http.request('http://www.baidu.com') from dual

*

ERROR at line 1:

ORA-29273: HTTP request failed

ORA-06512: at "SYS.UTL_HTTP", line 1722

ORA-24247: network access denied by access control list (ACL)

ORA-06512: at line 1

因此,我们要根据实际中的需要限定正确的范围,如:

11:56:17 osdbso@SYS> begin

dbms_network_acl_admin.assign_acl (

acl => 'myutltcpacl.xml',

host => 'www.baidu.com',

lower_port => 20,

upper_port => 128);

end;

/

PL/SQL procedure successfully completed.

现在我们使用SRCB用户就可以正常访问www.baidu.com的80端口了:

12:00:02 osdbso@SRCB> select utl_http.request('www.baidu.com') from dual;

UTL_HTTP.REQUEST('WWW.BAIDU.COM')

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

<!doctype html><html><head><meta http-equiv="Content-Type" content="text/html;charset=gb2312"><title>鐧惧害涓�涓嬶紝浣犲氨鐭ラ亾 </title><style>html{overflow-y:auto}body{font:12px arial;text-align:center;

background:#fff}body,p,form,ul,li{margin:0;padding:0;list-style:none}body,form,#fm{position:relative}td{text-align:left}img{border:0}a{color:#00c}a:active{color:#f60}#u{color:#999;padding:4px 10px 5px

0;text-align:right}#u a{margin:0 5px}#u .reg{margin:0}#m{width:720px;margin:0 auto;}#nv a,#nv b,.btn,#lk{font-size:14px}#fm{padding-left:110px;text-align:left}input{border:0;padding:0}#nv{height:19px

;font-size:16px;margin:0 0 4px;text-align:left;text-indent:137px;}.s_ipt_wr{width:418px;height:30px;display:inline-block;margin-right:5px;background:url(http://s1.bdstatic.com/r/www/img/i-1.0.0.png) n

o-repeat -304px 0;border:1px solid #b6b6b6;border-color:#9a9a9a #cdcdcd #cdcdcd #9a9a9a;vertical-align:top}.s_ipt{width:405px;height:22px;font:16px/22px arial;margin:5px 0 0 7px;background:#fff;outlin

e:none;-webkit-appearance:none}.s_btn{width:95px;height:32px;padding-top:2px\9;font-size:14px;background:#ddd url(http://s1.bdstatic.com/r/www/img/i-1.0.0.png);cursor:pointer}.s_btn_h{background-posit

ion:-100px 0}.s_btn_wr{width:97px;height:34px;display:inline-block;background:url(http://s1.bdstatic.com/r/www/img/i-1.0.0.png) no-repeat -202px 0;*position:relative;z-index:0;vertical-align:top}#lg i

mg{vertical-align:top;margin-bottom:3px}#lk{margin:33px 0}#lk span{font:14px "瀹嬩綋"}#lm{height:60px}#lh{margin:16px 0 5px;word-spacing:3px}.tools{position:absolute;top:-4px;*top:10px;right:7px;}#mHold

er{width:62px;position:relative;z-index:296;display:none}#mCon{height:18px;line-height:18px;position:absolute;cursor:pointer;padding:0 18px 0 0;background:url(http://s1.bdstatic.com/r/www/img/bg-1.0.0

.gif) no-repeat right -134px;background-position:right -136px\9}#mCon span{color:#00c;cursor:default;display:block}#mCon .hw{text-decoration:underline;cursor:pointer}#mMenu a{width:100%;h

该规则仅适用于 www.baidu.com。如果您调用其他 Web 站点,调用将失败,错误原因仍为ORA-24247。这是最细粒度水平上的安全性。如果您的企业需要连接到主机www.baidu.com,您可以在允许该连接的同时阻止对任何其他主机的访问,从而防止恶意用户使用该功能来访问所有其他的主机。

要了解 ACL 的详细信息,请查询 DBA_NETWORK_ACLS 视图:

17:25:41 osdbso@SYS> select host, lower_port, upper_port, acl, aclid from dba_network_acls where ACL='/sys/acls/myutltcpacl.xml';

HOST

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

LOWER_PORT UPPER_PORT

---------- ----------

ACL

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

ACLID

--------------------------------

www.baidu.com

22 55

/sys/acls/myutltcpacl.xml

CB11F58530D41CDCE0430164A8C07839

www.baidu.com

20 128

/sys/acls/myutltcpacl.xml

CB11F58530D41CDCE0430164A8C07839

最后附上dbms_network_acl_admin包的说明:

create or replace
package dbms_network_acl_admin is

/*
* DBMS_NETWORK_ACL_ADMIN is the PL/SQL package that provides the interface
* to administer the network ACL. The EXECUTE privilege on the package will
* be granted only to the DBA role by default.
*/

----------------
-- Exceptions --
----------------
ace_already_exists          EXCEPTION;
empty_acl                   EXCEPTION;
acl_not_found               EXCEPTION;
invalid_acl_path            EXCEPTION;
invalid_host                EXCEPTION;
invalid_privilege           EXCEPTION;
invalid_wallet_path         EXCEPTION;
bad_argument                EXCEPTION;
PRAGMA EXCEPTION_INIT(ace_already_exists,          -24243);
PRAGMA EXCEPTION_INIT(empty_acl,                   -24246);
PRAGMA EXCEPTION_INIT(acl_not_found,               -31001);
PRAGMA EXCEPTION_INIT(invalid_acl_path,            -46059);
PRAGMA EXCEPTION_INIT(invalid_host,                -24244);
PRAGMA EXCEPTION_INIT(invalid_privilege,           -24245);
PRAGMA EXCEPTION_INIT(invalid_wallet_path,         -29248);
PRAGMA EXCEPTION_INIT(bad_argument,                -29261);
ace_already_exists_num      constant PLS_INTEGER := -24243;
empty_acl_num               constant PLS_INTEGER := -24246;
acl_not_found_num           constant PLS_INTEGER := -31001;
invalid_acl_path_num        constant PLS_INTEGER := -46059;
invalid_host_num            constant PLS_INTEGER := -24244;
invalid_privilege_num       constant PLS_INTEGER := -24245;
invalid_wallet_path_num     constant PLS_INTEGER := -29248;
bad_argument_num            constant PLS_INTEGER := -29261;

-- IP address mask: xxx.xxx.xxx.xxx
IP_ADDR_MASK    constant VARCHAR2(80) := '([[:digit:]]+\.){3}[[:digit:]]+';
-- IP submet mask:  xxx.xxx...*
IP_SUBNET_MASK  constant VARCHAR2(80) := '([[:digit:]]+\.){0,3}\*';
-- Hostname mask:   ???.???.???...???
HOSTNAME_MASK   constant VARCHAR2(80) := '[^\.\:\/\*]+(\.[^\.\:\/\*]+)*';
-- Hostname mask:   *.???.???...???
DOMAIN_MASK     constant VARCHAR2(80) := '\*(\.[^\.\:\/\*]+)*';

/*--------------- API for ACL and privilege administration ---------------*/

/*
* Creates an access control list (ACL) with an initial privilege setting.
* An ACL must have at least one privilege setting. The ACL has no access
* control effect unless it is assigned to a network host.
*
* PARAMETERS
*   acl          the name of the ACL. Relative path will be relative to
*                "/sys/acls".
*   description  the description attribute in the ACL
*   principal    the principal (database user or role) whom the privilege
*                is granted to or denied from
*   is_grant     is the privilege is granted or denied
*   privilege    the network privilege to be granted or denied
*   start_date   the start date of the access control entry (ACE). When
*                specified, the ACE will be valid only on and after the
*                specified date.
*   end_date     the end date of the access control entry (ACE). When
*                specified, the ACE will expire after the specified date.
*                The end_date must be greater than or equal to the
*                start_date.
* RETURN
*   None
* EXCEPTIONS
*
* NOTES
*   To remove the ACL, use DROP_ACL. To assign the ACL to a network host,
*   use ASSIGN_ACL.
*/
procedure create_acl(acl          in varchar2,
description  in varchar2,
principal    in varchar2,
is_grant     in boolean,
privilege    in varchar2,
start_date   in timestamp with time zone default null,
end_date     in timestamp with time zone default null);

/*
* Adds a privilege to grant or deny the network access to the user. The
* access control entry (ACE) will be created if it does not exist.
*
* PARAMETERS
*   acl          the name of the ACL. Relative path will be relative to
*                "/sys/acls".
*   principal    the principal (database user or role) whom the privilege
*                is granted to or denied from
*   is_grant     is the privilege is granted or denied
*   privilege    the network privilege to be granted or denied
*   position     the position of the ACE. If a non-null value is given,
*                the privilege will be added in a new ACE at the given
*                position and there should not be another ACE for the
*                principal with the same is_grant (grant or deny). If a null
*                value is given, the privilege will be added to the ACE
*                matching the principal and the is_grant if one exists, or
*                to the end of the ACL if the matching ACE does not exist.
*   start_date   the start date of the access control entry (ACE). When
*                specified, the ACE will be valid only on and after the
*                specified date. The start_date will be ignored if the
*                privilege is added to an existing ACE.
*   end_date     the end date of the access control entry (ACE). When
*                specified, the ACE will expire after the specified date.
*                The end_date must be greater than or equal to the
*                start_date. The end_date will be ignored if the
*                privilege is added to an existing ACE.
* RETURN
*   None
* EXCEPTIONS
*
* NOTES
*   To remove the privilege, use DELETE_privilege.
*/
procedure add_privilege(acl        in varchar2,
principal  in varchar2,
is_grant   in boolean,
privilege  in varchar2,
position   in pls_integer default null,
start_date in timestamp with time zone default null,
end_date   in timestamp with time zone default null);

/*
* Delete a privilege.
*
* PARAMETERS
*   acl          the name of the ACL. Relative path will be relative to
*                "/sys/acls".
*   principal    the principal (database user or role) for whom the
*                privileges will be deleted
*   is_grant     is the privilege is granted or denied. If a null
*                value is given, the deletion is applicable to both
*                granted or denied privileges.
*   privilege    the privilege to be deleted. If a null value is given,
*                the deletion is applicable to all privileges.
* RETURN
*   None
* EXCEPTIONS
*
* NOTES
*   Any ACE that does not contain any privilege after the deletion will
*   be removed also.
*/
procedure delete_privilege(acl          in varchar2,
principal    in varchar2,
is_grant     in boolean  default null,
privilege    in varchar2 default null);

/*
* Drops an access control list (ACL).
*
* PARAMETERS
*   acl          the name of the ACL. Relative path will be relative to
*                "/sys/acls".
* RETURN
*   None
* EXCEPTIONS
*
*/
procedure drop_acl(acl in varchar2);

/*--------- API for ACL assignment to network hosts and wallets ---------*/

/*
* Assigns an access control list (ACL) to a network host, and optionally
* specific to a TCP port range.
*
* PARAMETERS
*   acl        the name of the ACL. Relative path will be relative to
*              "/sys/acls".
*   host       the host to which the ACL will be assigned. The host can be
*              the name or the IP address of the host. A wildcard can be
*              used to specify a domain or a IP subnet. The host or
*              domain name is case-insensitive.
*   lower_port the lower bound of a TCP port range if not NULL.
*   upper_port the upper bound of a TCP port range. If NULL,
*              lower_port is assumed.
* RETURN
*   None
* EXCEPTIONS
*
* NOTES
* 1. The ACL assigned to a domain takes a lower precedence than the other
*    ACLs assigned sub-domains, which take a lower precedence than the ACLs
*    assigned to the individual hosts. So for a given host say
*    "www.us.mycompany.com", the following domains are listed in decreasing
*    precedences:
*      - www.us.mycompany.com
*      - *.us.mycompany.com
*      - *.mycompany.com
*      - *.com
*      - *
*    In the same way, the ACL assigned to an subnet takes a lower
*    precedence than the other ACLs assigned smaller subnets, which take a
*    lower precedence than the ACLs assigned to the individual IP addresses.
*    So for a given IP address say "192.168.0.100", the following subnets
*    are listed in decreasing precedences:
*      - 192.168.0.100
*      - 192.168.0.*
*      - 192.168.*
*      - 192.*
*      - *
* 2. The port range is applicable only to the "connect" privilege
*    assignments in the ACL. The "resolve" privilege assignments in an ACL
*    have effects only when the ACL is assigned to a host without a port
*    range.
* 3. For the "connect" privilege assignments, an ACL assigned to the host
*    without a port range takes a lower precedence than other ACLs assigned
*    to the same host with a port range.
* 4. When specifying a TCP port range, both lower_port and upper_port must
*    not be NULL and upper_port must be greater than or equal to lower_port.
*    The port range must not overlap with any other port ranges for the same
*    host assigned already.
* 5. To remove the assignment, use UNASSIGN_ACL.
*/
procedure assign_acl(acl        in varchar2,
host       in varchar2,
lower_port in pls_integer default null,
upper_port in pls_integer default null);

/*
* Unassign the access control list (ACL) currently assigned to a network
* host.
*
* PARAMETERS
*   acl        the name of the ACL. Relative path will be relative to
*              "/sys/acls". If acl is NULL, any ACL assigned to the host
*              will be unassigned.
*   host       the host remove the ACL assignment from. The host can be
*              the name or the IP address of the host. A wildcard can be
*              used to specify a domain or a IP subnet. The host or
*              domain name is case-insensitive. If host is null, the ACL
*              will be unassigned from any host. If both host and acl are
*              NULL, all ACLs assigned to any hosts will be unassigned.
*   lower_port if not NULL, the lower bound of a TCP port range for the
*              host.
*   upper_port the upper bound of a TCP port range. If NULL,
*              lower_port is assumed.
* RETURN
*   None
* EXCEPTIONS
*
*/
procedure unassign_acl(acl        in varchar2 default null,
host       in varchar2 default null,
lower_port in pls_integer default null,
upper_port in pls_integer default null);

/*
* Assigns an access control list (ACL) to a wallet.
*
* PARAMETERS
*   acl         the name of the ACL. Relative path will be relative to
*               "/sys/acls".
*   wallet_path the directory path of the wallet to which the ACL will be
*               assigned. The path is case-sensitive and of the format
*               "file:<directory-path>".
* RETURN
*   None
* EXCEPTIONS
*
* NOTES
*   To remove the assignment, use UNASSIGN_WALLET_ACL.
*/
procedure assign_wallet_acl(acl         in varchar2,
wallet_path in varchar2);

/*
* Unassign the access control list (ACL) currently assigned to a wallet.
*
* PARAMETERS
*   acl         the name of the ACL. Relative path will be relative to
*               "/sys/acls". If acl is NULL, any ACL assigned to the wallet
*               will be unassigned.
*   wallet_path the directory path of the wallet to which the ACL will be
*               assigned. The path is case-sensitive and of the format
*               "file:<directory-path>". If wallet_path is null, the ACL
*               will be unassigned from any wallet.
* RETURN
*   None
* EXCEPTIONS
*
*/
procedure unassign_wallet_acl(acl         in varchar2 default null,
wallet_path in varchar2 default null);

/*
* Check if a privilege is granted to or denied from the user in an
* access control list.
*
* PARAMETERS
*   acl        the name of the ACL. Relative path will be relative to
*              "/sys/acls".
*   aclid      the object ID of the ACL.
*   user       the user to check against. If the user is NULL, the invoker
*              is assumed. The username is case-sensitive as in the
*              USERNAME column of the ALL_USERS view.
*   privilege  the network privilege to check
* RETURN
*   1 when the privilege is granted; 0 when the privilege is denied;
*   NULL when the privilege is neither granted or denied.
* EXCEPTIONS
*
*/
function check_privilege(acl       in varchar2,
user      in varchar2,
privilege in varchar2) return number;
function check_privilege_aclid(aclid     in raw,
user      in varchar2,
privilege in varchar2) return number;

/*
* This procedure is for internal use. It is the pre-delete XDB event
* handler to remove the ACL assignments when the ACL is dropped.
*/
procedure handlePreDelete(event in DBMS_XEvent.XDBRepositoryEvent);

end;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: