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

Public的特殊作用

原创 eygle 2019-09-23
1767

Public的特殊作用

在前面我们提到了用户权限与角色,而在数据库中,有一个特殊的权限集合,那就是PUBLIC。


PUBLIC是公共的含义,是数据库中一个特殊的“角色”,授予PUBLIC的权限会自动被所有用户继承,所以认真审核PUBLIC所拥有的权限是提高数据库安全的必要工作之一。


在catalog.sql脚本中,可以看到大量视图等对象在创建之后,就将权限授予了PUBLIC:


catalog.sql:grant select on tab to public with grant option;
catalog.sql:grant select on col to public with grant option;
catalog.sql:grant select on syssegobj to public with grant option;
catalog.sql:grant select on tabquotas to public with grant option;
catalog.sql:grant select on sysfiles to public with grant option;
catalog.sql:grant select on synonyms to public with grant option;
catalog.sql:grant select on publicsyn to public with grant option;
catalog.sql:grant select on GLOBAL_NAME to public with grant option


同样大量过程对象的执行权限也被授予:


catmeta.sql:grant execute on ku$_histgrm_t to public
catmeta.sql:grant execute on ku$_histgrm_list_t to public
catmeta.sql:grant execute on ku$_col_stats_t to public
catmeta.sql:grant execute on ku$_col_stats_list_t to public
catmeta.sql:grant execute on ku$_10_1_col_stats_t to public
catmeta.sql:grant execute on ku$_10_1_col_stats_list_t to public
catmeta.sql:grant execute on ku$_cached_stats_t to public
catmeta.sql:grant execute on ku$_tab_ptab_stats_t to public


在DBA_TAB_PRIVS中,PUBLIC具有的对象权限就多达2000多个:


SQL> select count(*) from dba_tab_privs where grantee='PUBLIC';
  COUNT(*)
----------
      2006


从安全角度着眼,这其中的很多权限不需授予给PUBLIC,具体的用户需要这些权限时可以进行单独授予:


SQL> SELECT table_name,grantee,privilege
2  FROM dba_tab_privs WHERE grantee='PUBLIC' AND table_name LIKE 'UTL%';
 
TABLE_NAME           GRANTEE              PRIVILEGE
-------------------- -------------------- --------------------
UTL_ALL_IND_COMPS    PUBLIC               SELECT
UTL_MATCH            PUBLIC               EXECUTE
UTL_COLL             PUBLIC               EXECUTE
UTL_REF              PUBLIC               EXECUTE
UTL_NLA              PUBLIC               EXECUTE
UTL_NLA_ARRAY_INT    PUBLIC               EXECUTE
UTL_NLA_ARRAY_FLT    PUBLIC               EXECUTE
UTL_NLA_ARRAY_DBL    PUBLIC               EXECUTE
UTL_LMS              PUBLIC               EXECUTE
UTL_I18N             PUBLIC               EXECUTE
UTL_COMPRESS         PUBLIC               EXECUTE
UTL_GDK              PUBLIC               EXECUTE
UTL_ENCODE           PUBLIC               EXECUTE
UTL_URL              PUBLIC               EXECUTE
UTL_HTTP             PUBLIC               EXECUTE
UTL_SMTP             PUBLIC               EXECUTE
UTL_INADDR           PUBLIC               EXECUTE
UTL_TCP              PUBLIC               EXECUTE
UTL_RAW              PUBLIC               EXECUTE
UTL_FILE             PUBLIC               EXECUTE


通常建议取消UTL_SMTP,UTL_TCP,UTL_HTTP,UTL_FILE等对象对于PUBLIC的授权,但是注意,取消授权之后,会导致部分系统对象失效,需要重新编译,所以建议,在进行任何权限回收时,必须经过认真的测试:

SQL> select count(*) from dba_objects where STATUS='INVALID';
  COUNT(*)
 ----------
       0
 
 SQL> REVOKE EXECUTE ON dbms_job FROM PUBLIC;
 Revoke succeeded.
 
 SQL> REVOKE EXECUTE ON utl_tcp FROM public;
 Revoke succeeded.
 
 SQL> REVOKE EXECUTE ON utl_smtp FROM public;
 Revoke succeeded.
 
 SQL> REVOKE EXECUTE ON utl_http FROM public;
 Revoke succeeded.
 
 SQL> REVOKE EXECUTE ON utl_inaddr FROM public;
 Revoke succeeded.
 
 SQL> REVOKE EXECUTE ON utl_file FROM public;
 Revoke succeeded.
 
 SQL> select count(*) from dba_objects where STATUS='INVALID';
  COUNT(*)
 ----------
        65
 
 SQL> @?/rdbms/admin/utlrp
 
 SQL> select count(*) from dba_objects where STATUS='INVALID';
 
  COUNT(*)
 ----------
         4
 
 SQL> col OBJECT_NAME for a30
 SQL> select OWNER,OBJECT_NAME from dba_objects where STATUS='INVALID';
 
 OWNER                          OBJECT_NAME
 ------------------------------ ------------------------------
 DBSNMP                           BSLN_INTERNAL
 XDB                            DBMS_XMLPARSER
 XDB                            DBMS_XSLPROCESSOR
 XDB                            DBMS_XDBT


最后几个对象,如果不使用XMLDB则可以忽略,否则可以直接向相关用户进行授权。


认真审核PUBLIC角色的权限是数据库安全管理的重要工作。


过度授权的风险


从安全角度考虑,数据库的授权应当遵循最小权限授予法,即仅授予满足用户需要的最小权限。这是因为在数据库中,如果进行了不当授权,则可能为数据库带来安全风险。


在数据库中,EXECUTE/CREATE ANY PROCEDURE都是非常重要的权限,如果被授予普通用户,则可能为数据库带来安全风险。


以下是在Oracle Database 8.1.7中的测试,首先创建了两个测试用户:


Connected to:
Oracle8i Enterprise Edition Release 8.1.7.4.0 - 64bit Production
With the Partitioning option
JServer Release 8.1.7.4.0 - 64bit Production
 
SQL> create user hacker identified by hacker default tablespace users temporary 
  2  tablespace temp;
 
User created.
 
SQL> grant create session to hacker;
 
Grant succeeded.
 
SQL> grant execute any procedure to hacker;
 
Grant succeeded.
 
SQL> create user loser identified by loser default tablespace users temporary
  2  tablespace temp;
 
User created.
 
SQL> grant connect to loser;
 
Grant succeeded.


当使用测试用户连接后,EXECUTE ANY PROCEDURE的权限使用户具有了访问和执行dbms_sys_sql包的权限,这个Package可以被用户利用来获得更高的权限:


SQL> connect hacker/hacker
Connected.
SQL> desc sys.dbms_sys_sql
PROCEDURE BIND_ARRAY
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 C                              NUMBER(38)              IN
 NAME                           VARCHAR2                IN
 N_TAB                          TABLE OF NUMBER         IN
PROCEDURE BIND_ARRAY
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 C                              NUMBER(38)              IN
 NAME                           VARCHAR2                IN
 C_TAB                          TABLE OF VARCHAR2(2000) IN
....
PROCEDURE VARIABLE_VALUE_ROWID
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 C                              NUMBER(38)              IN
 NAME                           VARCHAR2                IN
 VALUE                          ROWID                   OUT

 

通过如下一段代码,Hacker用户就可以很多DDL语句,诸如修改其他用户的口令,对自我进行授权等:


SQL> connect hacker/hacker
Connected.
 
SQL> DECLARE
  2     UID       NUMBER;
  3     sqltext   VARCHAR2 (100) := 'alter user loser identified by test';
  4     c         INTEGER;
  5  BEGIN
  6     c := SYS.DBMS_SYS_SQL.open_cursor ();
  7     SYS.DBMS_SYS_SQL.parse_as_user (c, sqltext, DBMS_SQL.native, 0);
  8     SYS.DBMS_SYS_SQL.close_cursor (c);
  9      END;
 10  /
 
PL/SQL procedure successfully completed.


通过DBMS_SYS_SQL.parse_as_user,hacker可以在数据库内任意为非作歹了。用户loser的口令已被更改:


SQL> connect loser/loser
ERROR:
ORA-01017: invalid username/password; logon denied
 
Warning: You are no longer connected to ORACLE.
SQL> connect loser/test
Connected.


在Oracle 9i中,如果用户具有EXECUTE/CREATE ANY PROCEDURE的权限,则同样用户可以做出很多跨越常规的授权:


SQL> select * from v$version where rownum <2;
 
BANNER
----------------------------------------------------------------
Oracle9i Enterprise Edition Release 9.2.0.4.0 - 64bit Production
SQL> create user eygle identified by eygle;
 
User created.
 
SQL> grant create session to eygle;
 
Grant succeeded.
 
SQL> grant execute any procedure to eygle;
 
Grant succeeded.


现在CREATE ANY PROCEDURE的权限可以使用户创建任何过程:


SQL>  eygle/eygle
SQL> CREATE OR REPLACE PROCEDURE SYSTEM.DO(P_TEXT VARCHAR2)
  2    IS
  3  BEGIN
  4    EXECUTE IMMEDIATE P_TEXT;
  5  END;
  6  /
 
Procedure created.


现在EXECUTE ANY PROCEDURE的权限,可以使用户执行创建的过程,进行跨越职权的授权:


SQL> execute system.do('grant dba to eygle');
 
PL/SQL procedure successfully completed.


检查一下当前用户具有的权限:


SQL> SELECT * FROM SESSION_PRIVS;
PRIVILEGE
----------------------------------------
CREATE SESSION
UNLIMITED TABLESPACE
CREATE ANY PROCEDURE
EXECUTE ANY PROCEDURE
 
SQL> SELECT * FROM SESSION_ROLES;
ROLE
------------------------------
PLUSTRACE


重新连接会激活角色授权,可以注意到用户已经具备了DBA的职权:


SQL> connect eygle/eygle
Connected.
SQL> SELECT * FROM SESSION_ROLES;
 
ROLE
------------------------------
PLUSTRACE
DBA
SELECT_CATALOG_ROLE
HS_ADMIN_ROLE
EXECUTE_CATALOG_ROLE
DELETE_CATALOG_ROLE
EXP_FULL_DATABASE
IMP_FULL_DATABASE
GATHER_SYSTEM_STATISTICS
WM_ADMIN_ROLE
JAVA_ADMIN
JAVA_DEPLOY
 
12 rows selected.
 
SQL> SELECT * FROM SESSION_PRIVS;
 
PRIVILEGE
----------------------------------------
ALTER SYSTEM
AUDIT SYSTEM
CREATE SESSION
ALTER SESSION
RESTRICTED SESSION
CREATE TABLESPACE
ALTER TABLESPACE
MANAGE TABLESPACE
。。。。。。。。


虽然在不同的版本中,Oracle一直在强化其安全管理,但是仍然需要我们小心谨慎的管理数据库权限,确保数据库安全。


数据字典的访问


很多时候由于应用的需要,数据库用户需要访问数据字典对象,而这些数据字典对象对于数据库的稳定运行非常重要,所以Oracle需要通过权限设置来限制这些对象的访问。


在现实的很多系统中,通常具有这一类访问需求的用户被授予了DBA的权限,这是非常危险的,给予适当的用户以适当的权限是权限管理的基本原则。


本节我们就数据字典的访问权限进行探讨。

 

访问数据字典需要对用户授予系统权限,而Oracle的大部分系统权限都具有很大的权力,因此在给非DBA用户授予系统权限时一定要非常谨慎。例如,具有UPDATE ANY TABLE系统权限的用户,就拥有更改SYS用户数据字典基表的权限(例如obj$,ts$等)。

 

在数据字典的访问权限上,Oracle权限管理的发展经历了几个过程,这几个发展过程积累了如下一些参数和权限:


image.png


缺省的数据字典基础表仅限具有SYSOPER或SYSDBA权限的用户,通过授予相应的权限,其他用户可以获得数据字典表的访问权限。为了控制普通用户对于字典表的访问,Oracle引入了O7_DICTIONARY_ACCESSIBILITY初始化参数。

 

在Oracle9i之前,这个参数缺省值为TRUE。在Oracle8中,通过这个参数的机制可以控制用户对于字典对象的访问。我们看一下Oracle8i环境中这一参数的作用:


也许你想不到,SQL*Plus在Oracle 8.1.5中,show parameter的功能是区分大小写的,有时候回顾一下Oracle的不同版本是很有意思的一件事(注意该参数的缺省值为TRUE):


SQL> select * from v$version where rownum <2;
BANNER
----------------------------------------------------------------
Oracle8i Enterprise Edition Release 8.1.5.0.0 - Production
SQL> show parameter o7
SQL> show parameter O
NAME                           TYPE    VALUE
------------------------------ ------- ----------------------------------------
O7_DICTIONARY_ACCESSIBILITY    boolean TRUE


我们创建一个全新的用户,并且授予create session的权限:


SQL> select username from dba_users where username='EYGLE';
no rows selected
 
SQL> create user eygle identified by eygle default tablespace users temporary tablespace temp;
User created.
 
SQL> grant create session to eygle;
Grant succeeded.


使用新的用户登录之后,我们可以看到这个用户仅具备CREATE SESSION的权限,不能访问数据字典对象


SQL> connect eygle/eygle
Connected.
SQL> select * from session_privs;
PRIVILEGE
----------------------------------------
CREATE SESSION
SQL> desc sys.obj$
ERROR:
ORA-04043: object sys.obj$ does not exist


我们再来看一下在O7_DICTIONARY_ACCESSIBILITY为True的设置下,SELECT ANY TABLE权限的作用:


SQL> connect / as sysdba
Connected.
SQL> grant select any table to eygle;
Grant succeeded.
 
SQL> connect eygle/eygle
Connected.
SQL> select * from session_privs;
PRIVILEGE
----------------------------------------
CREATE SESSION
SELECT ANY TABLE
 
SQL> select count(*) from sys.obj$;
  COUNT(*)
----------
     16389
SQL> select count(*) from scott.emp;
  COUNT(*)
----------
        14


我们注意到此时用户具备了查询数据字典的权限,而当该参数设置为FALSE时,SELECT ANY  TABLE的系统权限并不能使用户获得访问数据字典的权限,但是仍然可以访问其他用户的数据表:


SQL> show parameter O7
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
O7_DICTIONARY_ACCESSIBILITY          boolean     FALSE
SQL> select * from session_privs;
PRIVILEGE
----------------------------------------
CREATE SESSION
SELECT ANY TABLE
 
SQL> select count(*) from sys.obj$;
select count(*) from sys.obj$
                         *
ERROR at line 1:
ORA-00942: table or view does not exist
SQL> desc sys.v$instance
ERROR:
ORA-04043: object sys.v$instance does not exist
SQL> select count(*) from scott.emp;
  COUNT(*)
----------
        14


也就是说Oracle通过O7_DICTIONARY_ACCESSIBILITY将部分ANY权限对访问数据字典和普通用户对象的权限界定开来。


为了安全起见,从Oracle9i开始,O7_DICTIONARY_ACCESSIBILITY参数缺省值即为FALSE。也正因为如此,从Oracle9i开始,SYS用户必需以SYSDBA或SYSOPER身份登录数据库,否则将收到如下错误提示:


SQL> connect sys/oracle
ERROR:
ORA-28009: connection to sys should be as sysdba or sysoper
 
Warning: You are no longer connected to ORACLE.


而如果将O7_DICTIONARY_ACCESSIBILITY参数设置为TRUE,SYS用户登录时就不会出现该错误提示:


SQL> connect sys/oracle
Connected.
SQL> show parameter o7
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
O7_DICTIONARY_ACCESSIBILITY          boolean     TRUE


为了弥补O7_DICTIONARY_ACCESSIBILITY参数设置为FALSE带来的影响,在Oracle9i中,Oracle引入了SELECT ANY DICTIONARY的系统权限,这个权限可以使用户获得数据字典的访问权限:


SQL> connect eygle/eygle
Connected.
SQL> select * from session_privs;
PRIVILEGE
----------------------------------------
CREATE SESSION
SELECT ANY DICTIONARY
 
SQL> select count(*) from sys.obj$;
  COUNT(*)
----------
      6431
SQL> select count(*) from v$instance;
  COUNT(*)
----------
         1
SQL> select count(*) from scott.emp;
select count(*) from scott.emp
                           *
ERROR at line 1:
ORA-00942: table or view does not exist


通过测试我们注意到,如果仅有SELECT ANY DICTIONARY可以使用户具备访问数据字典的权限,但是不能使用户获得访问其他用户表的权限。


也就是说:


O7_DICTIONARY_ACCESSIBILITY=TRUE + SELECT ANY TABLE

=

O7_DICTIONARY_ACCESSIBILITY=FALSE + SELECT ANY TABLE + SELECT ANY DICTIONARY

 

SELECT_CATALOG_ROLE角色是Oracle8中引入的,用于限制用户对于SYS拥有的视图的访问:


SQL> revoke select any dictionary from eygle;
Revoke succeeded.
 
SQL> grant select_catalog_role to eygle;
Grant succeeded.
 
SQL> connect eygle/eygle
Connected.
SQL> select * from session_privs;
PRIVILEGE
----------------------------------------
CREATE SESSION
 
SQL> select * from session_roles;
ROLE
------------------------------
SELECT_CATALOG_ROLE
 
SQL> select count(*) from dba_tables;
  COUNT(*)
----------
       520
 
SQL> select count(*) from sys.tab$;
select count(*) from sys.tab$
                         *
ERROR at line 1:
ORA-00942: table or view does not exist
最后修改时间:2019-09-23 17:02:11
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论