Oracle允許使用幾個PL/SQL API(UTL_TCP UTL_SMTP UTL_MAIL UTL_HTTP和 UTL_INADDR)訪問外部網絡服務這些API都使用TCP協議在上一個數據庫版本中(g)是通過一個基於用戶是否被授予執行某個包的許可的on/off開關來實現的Oracle g引入了細粒度訪問網絡服務
通過在XML DB 數據庫中使用訪問控制列表(ACL)來實現允許控制哪個用戶能夠訪問哪個網絡資源而不關心包的授權
使用FTP或WebDav可以直接在XML DB 數據庫中創建修改和刪除訪問控制列表Oracle提供了DBMS_NETWORK_ACL_ADMIN和DBMS_NETWORK_ACL_UTILITY程序包允許從PL/SQL管理訪問控制列表這些API就是本文的主角
創建一個訪問控制列表(ACL)
訪問控制列表是使用DBMS_NETWORK_ACL_ADMIN程序包來操作的CREATE_ACL存儲過程使用下面的參數來創建一個新的訪問控制列表
? acl 訪問控制列表XML文件的名字產生在XML DB 數據庫中的/sys/acls目錄下? description 訪問控制列表的描述信息? principal 第一個被授予或拒絕的用戶賬號大小寫敏感? is_grant TRUE意味著授予了權限FALSE意味著權限被拒絕? privilege 給UTL_TCP UTL_SMTP UTL_MAIL和UTL_HTTP授予connect權限給UTL_INADDR名稱/ip解析授予resolve權限大小寫敏感? start_date 默認值是NULL當指定了一個值後訪問控制列表只有在指定的日期到達時或到達後才被激活? en_date 訪問控制列表結束日期(可選的)
下面的代碼創建了兩個測試用戶充當委托人然後又創建了一個新的訪問控制列表
CONN sys/password@dbg AS SYSDBA
CREATE USER test IDENTIFIED BY test;
GRANT CONNECT TO test;
CREATE USER test IDENTIFIED BY test;
GRANT CONNECT TO test;
BEGIN
DBMS_NETWORK_ACL_ADMINcreate_acl (
acl => test_acl_filexml
description => A test of the ACL functionality
principal => TEST
is_grant => TRUE
privilege => connect
start_date => SYSTIMESTAMP
end_date => NULL);
COMMIT;
END;
/
一旦創建完畢訪問控制列表就能夠//host:port/sys/acls目錄下看到
使用ADD_PRIVILEGE存儲過程將其他的用戶或角色添加到訪問控制列表中它的參數與CREATE_ACL存儲過程的參數類似省略了DESCRIPTION參數同時增加了POSITION參數它用於設置優先順序
BEGIN
DBMS_NETWORK_ACL_ADMINadd_privilege (
acl => test_acl_filexml
principal => TEST
is_grant => FALSE
privilege => connect
position => NULL
start_date => NULL
end_date => NULL);
COMMIT;
END;
/
每個委托人在訪問控制列表中都被作為一個獨立的訪問控制單元(ACE)進行定義當定義了多條原則時他們按照從上到下的順序被評估直到最後一條定義權限的原則這就意味著一個拒絕訪問某個資源的角色可以被授予一個用戶但是如果這個用戶又作為一個委托人定義在文件中時這個定義將覆蓋角色的定義使用POSITION參數保證權限是按順序進行評估的
使用DELETE_PRIVILEGE存儲過程移除權限如果IS_GRANT或PRIVILEGE參數的值是NULL將移除所有授予的權限
BEGIN
DBMS_NETWORK_ACL_ADMINdelete_privilege (
acl => test_acl_filexml
principal => TEST
is_grant => FALSE
privilege => connect);
COMMIT;
END;
/
使用DROP_ACL刪除訪問控制列表
BEGIN
DBMS_NETWORK_ACL_ADMINdrop_acl (
acl => test_acl_filexml);
COMMIT;
END;
/
給網絡分配一個訪問控制列表
使用ASSIGN_ACL存儲過程給網絡分配訪問控制列表它有下面一些參數
? acl 訪問控制列表XML文件的名字? host 主機名域名ip地址或分配的子網主機名大小寫敏感ip地址和域名允許使用通配符? lower_port 默認值是NULL為connect權限指定低端口范圍? upper_port 默認值是NULL如果指定了lower_port同時upper_port的值為 NULL它就認為upper_port等同於lower_port
下面的代碼展示了前面創建的訪問控制列表被分配一個特定的ip地址和一個子網
BEGIN
DBMS_NETWORK_ACL_ADMINassign_acl (
acl => test_acl_filexml
host =>
lower_port =>
upper_port => NULL);
DBMS_NETWORK_ACL_ADMINassign_acl (
acl => test_acl_filexml
host => *
lower_port => NULL
upper_port => NULL);
COMMIT;
END;
/
只有一個訪問控制列表可以分配給一個特殊的主機+端口范圍的組合給主機+端口范圍分配一個新的訪問控制列表將導致前面分配的訪問控制列表被刪除在你開始一個新的分配操作時要特別留意前一個訪問控制列表關閉的端口現在又被你打開了因此分配給:的訪問控制列表的優先級比分配給*的訪問控制列表要高
UNASSIGN_ACL存儲過程允許你手動刪除訪問控制列表它使用的參數與ASSIGN_ACL存儲過程相同使用NULL參數作為通配符
BEGIN
DBMS_NETWORK_ACL_ADMINunassign_acl (
acl => test_acl_filexml
host =>
lower_port =>
upper_port => NULL);
COMMIT;
END;
/
訪問控制列表視圖
DBA_NETWORK_ACLS DBA_NETWORK_ACL_PRIVILEGES和USER_NETWORK_ACL_PRIVILEGES視圖顯示當前的訪問控制列表設置下面預期的輸出認為沒有執行過delete/drop/unassign操作
DBA_NETWORK_ACLS視圖顯示關於網絡和訪問控制列表分配的信息
COLUMN host FORMAT A
COLUMN acl FORMAT A
SELECT host lower_port upper_port acl
FROM dba_network_acls;
HOST
*
LOWER_PORT UPPER_PORT ACL
/sys/acls/test_acl_filexml
/sys/acls/test_acl_filexml
rows selected
SQL>
DBA_NETWORK_ACL_PRIVILEGES視圖顯示關於與訪問控制列表聯合的權限信息
COLUMN acl FORMAT A
COLUMN principal FORMAT A
SELECT acl
principal
privilege
is_grant
TO_CHAR(start_date DDMONYYYY) AS start_date
TO_CHAR(end_date DDMONYYYY) AS end_date
FROM dba_network_acl_privileges;
ACL PRINCIPAL
/sys/acls/test_acl_filexml TEST
/sys/acls/test_acl_filexml TEST
PRIVILE IS_GR START_DATE END_DATE
connect true APR
connect false
rows selected
SQL>
USER_NETWORK_ACL_PRIVILEGES視圖顯示當前用戶網絡訪問控制列表設置
CONN test/test@dbg
COLUMN host FORMAT A
SELECT host lower_port upper_port privilege status
FROM user_network_acl_privileges;
HOST LOWER_PORT UPPER_PORT PRIVILE STATUS
* connect GRANTED
connect GRANTED
rows selected
SQL>
CONN test/test@dbg
COLUMN host FORMAT A
SELECT host lower_port upper_port privilege status
FROM user_network_acl_privileges;
HOST LOWER_PORT UPPER_PORT PRIVILE STATUS
* connect DENIED
connect DENIED
rows selected
SQL>
權限檢查
處理訪問控制列表視圖外還可以使用DBMS_NETWORK_ACL_ADMIN包中的CHECK_PRIVILEGE和CHECK_PRIVILEGE_ACLID函數來檢查權限
CONN sys/password@dbg AS SYSDBA
SELECT DECODE(
DBMS_NETWORK_ACL_ADMINcheck_privilege(test_acl_filexml TEST connect)
GRANTED DENIED NULL) privilege
FROM dual;
PRIVILE
GRANTED
row selected
SQL>
COLUMN acl FORMAT A
COLUMN host FORMAT A
SELECT acl
host
DECODE(
DBMS_NETWORK_ACL_ADMINcheck_privilege_aclid(aclid TEST connect)
GRANTED DENIED NULL) privilege
FROM dba_network_acls;
PRIVILE
DENIED
row selected
SQL>
DBMS_NETWORK_ACL_UTILITY包包括了幫助判斷可能匹配的域的函數DOMAINS表函數按順序返回所有可能受影響的主機域ip地址或子網的集合
SELECT *
FROM TABLE(DBMS_NETWORK_ACL_UTILITYdomains(oelglocaldomain));
COLUMN_VALUE
oelglocaldomain
*localdomain
*
rows selected
SQL>
SELECT *
FROM TABLE(DBMS_NETWORK_ACL_UTILITYdomains());
COLUMN_VALUE
*
*
*
*
rows selected
SQL>
DOMAIN_LEVEL函數返回主機域ip地址或子網的級數
SELECT DBMS_NETWORK_ACL_UTILITYdomain_level(oelglocaldomain)
FROM dual;
DBMS_NETWORK_ACL_UTILITYDOMAIN_LEVEL(OELGLOCALDOMAIN)
row selected
SQL>
SELECT DBMS_NETWORK_ACL_UTILITYdomain_level()
FROM dual;
DBMS_NETWORK_ACL_UTILITYDOMAIN_LEVEL()
row selected
SQL>
在為可能匹配的主機域ip地址或子網查詢訪問控制列表視圖是這些函數可能非常有用
SELECT host
lower_port
upper_port
acl
DECODE(
DBMS_NETWORK_ACL_ADMINcheck_privilege_aclid(aclid TEST connect)
GRANTED DENIED null) PRIVILEGE
FROM dba_network_acls
WHERE host IN (SELECT *
FROM TABLE(DBMS_NETWORK_ACL_UTILITYdomains()))
ORDER BY
DBMS_NETWORK_ACL_UTILITYdomain_level(host) desc lower_port upper_port;
HOST LOWER_PORT UPPER_PORT ACL PRIVILE
* /sys/acls/test_acl_filexml GRANTED
row selected
SQL>
測試訪問控制列表
用戶TEST和TEST分別擁有了允許的和拒絕的訪問控制列表這就意味著我們可以開始通過對比對訪問外部網絡服務時它們的響應來測試訪問控制列表的功能下面的代碼授予了這兩個用戶都可以執行UTL_HTTP包的權限然後嘗試從每個用戶訪問一個web頁面
CONN sys/password@dbg AS SYSDBA
GRANT EXECUTE ON UTL_HTTP TO test test;
CONN test/test@dbg
DECLARE
l_url VARCHAR() := ;
l_;
l_;
BEGIN
Make a HTTP request and get the response
l_(l_url);
l_(l_http_request);
UTL_HTTPend_response(l_http_response);
END;
/
PL/SQL procedure successfully completed
SQL>
CONN test/test@dbg
DECLARE
l_url VARCHAR() := ;
l_;
l_;
BEGIN
Make a HTTP request and get the response
l_(l_url);
l_(l_http_request);
UTL_HTTPend_response(l_http_response);
END;
/
DECLARE
*
ERROR at line :
ORA: HTTP request failed
ORA: at SYSUTL_HTTP line
ORA: network access denied by access control list (ACL)
ORA: at line
SQL>
從返回的信息我們不難看出用戶TEST能夠訪問web頁面而用戶TEST被訪問控制列表拒絕了服務器的默認行為是拒絕訪問外部網絡服務下面顯示了一個新用戶的測試情況
CONN sys/password@dbg AS SYSDBA
CREATE USER test IDENTIFIED BY test;
GRANT CONNECT TO test;
GRANT EXECUTE ON UTL_HTTP TO test;
CONN test/test@dbg
DECLARE
l_url VARCHAR() := ;
l_;
l_;
BEGIN
Make a HTTP request and get the response
l_(l_url);
l_(l_http_request);
UTL_HTTPend_response(l_http_response);
END;
/
DECLARE
*
ERROR at line :
ORA: HTTP request failed
ORA: at SYSUTL_HTTP line
ORA: network access denied by access control list (ACL)
ORA: at line
SQL>
在從g升級到g時訪問外部網絡服務時可能會產生一些混亂在那種情況下你需要實現合理的訪問控制列表
其他安全因素
Pete Finnigan在它的博客上和關於訪問控制列表的安全陳述只沒有附上具體的程序包這就意味著通過UTL_TCP UTL_SMTP UTL_MAIL和UTL_HTTP加上connect權限就能在服務器上打開一個端口牢記這一點並考慮以下事項
◆細粒度訪問網絡服務的使用不能作為忽略基本的安全評估的借口如收回與網絡服務有關程序包的不必要的權限
◆通過限制對特定端口的訪問控制你的服務是可用的如果你僅僅需要訪問http 端口指定這個端口比在服務器上開放所有端口的訪問要好得多
◆授權時使用通配符比不使用通配符安全性更差也更危險
◆你必須保護你的訪問控制列表如果有人能夠修改它們因為保護機制問題它們變得毫無用處阻止直接訪問存儲在XML DB 數據庫中的訪問控制列表確保用戶不能訪問管理API
From:http://tw.wingwit.com/Article/program/Oracle/201311/18300.html