数据库安全和最小权限原则


一、PUBLIC权限

 PUBLIC角色隐式授予每位用户。只要为PUBLIC授予任何权限,相应的权限实际上就会授予可以连接到数据库的每个人,创建的每个账户都有权访问这些权限。默认方式下,PUBLIC用户拥有大量权限。


gyj@OCM> select count(*) from dba_tab_privs where grantee='PUBLIC';

COUNT(*)
----------
     28164


gyj@OCM> select table_name from dba_tab_privs where grantee='PUBLIC' and privilege='EXECUTE' and table_name like 'UTL%';


TABLE_NAME
------------------------------
UTL_RAW
UTL_IDENT
UTL_TCP
UTL_HTTP
UTL_FILE
UTL_INADDR
UTL_SMTP
UTL_URL
UTL_ENCODE
UTL_GDK
UTL_COMPRESS
UTL_I18N
UTL_LMS
UTL_NLA_ARRAY_DBL
UTL_NLA_ARRAY_FLT
UTL_NLA_ARRAY_INT
UTL_NLA
UTL_REF
UTL_COLL
UTL_MATCH
UTL_BINARYINPUTSTREAM
UTL_BINARYOUTPUTSTREAM
UTL_CHARACTERINPUTSTREAM
UTL_CHARACTEROUTPUTSTREAM

24 rows selected.


虽然应用软件可以为PUBLIC用户授予执行UTL包的权限,但是我们应当取消PUBLIC用户的这个权限。执行如下操作就可以取消该权限:


gyj@OCM> conn / as sysdba

Connected.


sys@OCM> revoke execute on utl_file from public;


Revoke succeeded.


UTL_FILE:这个包允许用户读写操作系统,Oracle所有者都可以访问的任何文件和目录,这些文件与目录包括所有的数据库文件以及ORACLE_HOME目录。


二、对安全性至关重要的实例参数

 对于数据库的安全性来说,某些实例参数至关重要。这些参数的默认值通常都是合适的,但在某些情况下可能需要修改。


1、UTL_FILE_DIR


gyj1@OCM> show parameter utl_file   


NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
utl_file_dir                         string      


utl_file_dir默认为空值,设置这个参数需要小心,utl_file_dir参数允许PL/SQL通过UTL_FILE包来访问服务器计算机文件系统。而UTL_FILE包具有打开并读写文件的过程,唯一的限制是Oracle拥有者必须能访问所列出的目录。

utl_file_dir参数接受一个用逗号分隔的目录列表,并且是静态的,如下操作:


sys@OCM> alter system set utl_file_dir='/oracle/ocp','/oracle/ocm/' scope=spfile;


System altered.


2、OS_AUTHENT_PREFIX

 这个参数控制某个用户是否参够在不需要给出口令的情况下从远程计算机上连接数据库。


sys@OCM> show parameter os_authent


NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
os_authent_prefix                    string      ops$
remote_os_authent                    boolean     FALSE


(1)修改参数


sys@OCM> alter system set os_authent_prefix='' scope=spfile;


System altered.


sys@OCM> startup force;


(2)建操作系统用户及设置密码


[root@ocm ~]# useradd joe
[root@ocm ~]# passwd joe
Changing password for user joe.
New UNIX password: 
BAD PASSWORD: it is WAY too short
Retype new UNIX password: 
passwd: all authentication tokens updated successfully.

(3)建数据库用户及授权


sys@OCM> create user joe identified externally;



User created.


sys@OCM> grant dba to joe;


Grant succeeded.


(4)操作系统认证


[root@ocm ~]# su - joe
[joe@ocm ~]$ export ORACLE_BASE=/u01/app/oracle
[joe@ocm ~]$ export ORACLE_HOME=$ORACLE_BASE/product/11.2.0
[joe@ocm ~]$ export ORACLE_SID=ocm
[joe@ocm ~]$ export PATH=$ORACLE_HOME/bin:$PATH
[joe@ocm ~]$ sqlplus /


SQL*Plus: Release 11.2.0.1.0 Production on Mon Mar 11 21:25:13 2013


Copyright (c) 1982, 2009, Oracle.  All rights reserved.

Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options


只要服务器操作系统安全,那么上面的操作也是安全的。


3、REMOTE_OS_AUTHENT


 gyj1@OCM> show parameter remote_os_authent


NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------

remote_os_authent                    boolean     FALSE


默认是 FALSE,把它改成TRUE


gyj1@OCM> conn /  as sysdba
Connected.
sys@OCM> alter system set remote_os_authent=TRUE scope=spfile;


System altered.


sys@OCM> startup force;


[joe@ocm ~]$ sqlplus /@ocm


SQL*Plus: Release 11.2.0.1.0 Production on Tue Mar 12 19:41:59 2013


Copyright (c) 1982, 2009, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

joe@OCM> 


注意这里要想成功操作系统登录,必须把sqlnet.ora给干掉(mv sqlnet.ora sqlnet.ora.bak)
remote_os_authent这个参数开启后, 存在很大的安全隐患, 远端服务器只要根据数据库中存在的外部用户来创建用户, 就可以登陆到数据库中, 因此除非必要, 否则不建议开启这个参数。



4、O7_DICTIONARY_ACCESSIBILITY
O7_DICTIONARY_ACCESSIBILITY实例参数控制使用ANY关键字授予对象权限的效果。这个参数默认为FALSE。

如下操作为用户gyj1授予查看数据库中所有表的权限:


sys@OCM> grant select any table to gyj1;


Grant succeeded.


 但是,怎么样才能使gyj1能查看所有的数据字典与用户表呢?因为某些表包含了敏感数据据,所以这似乎是不可能的。

 O7_DICTIONARY_ACCESSIBILITY参数默认是FALSE,这意味着ANY权限不被授予SYS拥有的对象,从而保护了数据字典,此时gyj1能够查看所有的用护数据。但是无法查看SYS拥有的对象。如果将这个参数改为TRUE,那么意味着所有对象都被授予了ANY权限,此时gyj1能够查看数据字典以及所有用户的数据。


sys@OCM> show parameter O7


NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
O7_DICTIONARY_ACCESSIBILITY          boolean     FALSE


当O7_DICTIONARY_ACCESSIBILITY为FALSE,想要访问数据字典如下授权操作:


sys@OCM> grant select any dictionary to gyj1;


Grant succeeded.


sys@OCM> conn gyj1/gyj1

Connected.


gyj1@OCM> select count(*) from sys.tab$;


  COUNT(*)
----------
      2907


gyj1@OCM> conn /as sysdba

Connected.


sys@OCM> revoke select any dictionary from gyj1;


Revoke succeeded.


sys@OCM> grant select any table to gyj1;


Grant succeeded.


sys@OCM> conn gyj1/gyj1

Connected.


gyj1@OCM> select count(*) from sys.tab$;
select count(*) from sys.tab$
                         *
ERROR at line 1:
ORA-00942: table or view does not exist


当O7_DICTIONARY_ACCESSIBILITY为FALSE,想要访问数据字典可以把O7_DICTIONARY_ACCESSIBILITY改为TRUE。


gyj1@OCM> conn / as sysdba

Connected.


sys@OCM> alter system set O7_DICTIONARY_ACCESSIBILITY=true scope=spfile;


System altered.


sys@OCM> startup force;

ORACLE instance started.


Total System Global Area  836976640 bytes
Fixed Size                  1339740 bytes
Variable Size             419434148 bytes
Database Buffers          411041792 bytes
Redo Buffers                5160960 bytes
Database mounted.
Database opened.
sys@OCM> conn gyj1/gyj1
Connected.
gyj1@OCM> select count(*) from sys.tab$;


  COUNT(*)
----------
      2907



5、REMOTE_LOGIN_PASSWORFILE


sys@OCM> show parameter remote_login_passwordfile


NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------

remote_login_passwordfile            string      EXCLUSIVE


 远程的REMOTE_LOGIN_PASWORFILE实例参数控制具有sysdba或sysoper权限的用户否通过网络连接实例。当这个参数被赋予默认值NONE时,得到SYSDBA连接的唯一方法是作为拥有Oracle软件的操作系统的成员登录服务器的操作系统。只要服务器的操作系统是安全的,这种操作就是绝对安全的。
将remote_login_passwordfile设为EXCLUSIVE或SHARED时,用户可以通过列不同的方法得到SYSDBA连接:
SHARED:在同一个Oracle主目录内运行的所有实例共享一个公有的口令文件,对于所有实例公有的SYS用户来说,这个主目录只有一个口令。

EXCLUSIVE:实例会寻找一个其名称包含实例名的文件(在windows中为:PWD<SID>.ora,在UNIX中为orapwd<SID>),这个文件具有实例特有的口令。


sys@OCM> select * from v$pwfile_users;


USERNAME                       SYSDB SYSOP SYSAS
------------------------------ ----- ----- -----
SYS                            TRUE  TRUE  FALSE
GYJ1                           TRUE  FALSE FALSE


sys@OCM> grant sysoper to hr;


Grant succeeded.


sys@OCM> grant sysdba to gyj;


Grant succeeded.


sys@OCM> select * from v$pwfile_users;


USERNAME                       SYSDB SYSOP SYSAS
------------------------------ ----- ----- -----
SYS                            TRUE  TRUE  FALSE
GYJ1                           TRUE  FALSE FALSE
HR                             FALSE TRUE  FALSE
GYJ                            TRUE  FALSE FALSE


三、使用标准数据库审核
 无论安全策略多么完善,总是存在策略显得不足的情况。

 除了SYSDBA审核之外,Oracle还提供了三种审核技术:数据库审核、基于值的审核、细粒度审核。


1、SYSDBA审核:具有SYSDBA的权限的任何人可以在数据库内进行任何操作。为了使雇主相信数据库管理员不会滥用权利,有必要审核所有的SYSDBA活动。对于普通用户,数据库管理员也可能希望跟踪他们所进行的操作。

 实例参数AUDIT_SYS_OPERATIONS设置为TRUE(默认FALSE)


sys@OCM> show parameter AUDIT_SYS_OPERATIONS


NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
audit_sys_operations                 boolean     FALSE


2、数据库审核:能够跟踪特定权限的使用、特定命令的执行、对于特定表的访问能及登录尝试。
(1)设置数据库审核之前,必须设置audit_trail实例参数。这个参数具体有以下值:
 NONE(或者FALSE):无论试图配置哪一种审核,这个参数值会禁用数据库审核。
 OS:审核记录会被写至操作系统的审核跟踪(也就是Windows系统中的Windows Application Log文件夹或者Unix系统中的AUDIT_FILE_DEST目录)
 DB:审核记录会被写入数据字典表SYS.AUD$。我们可以通过某些视图来查看这个表的内容。
 DB_EXTENDED:与DB的作用大体相同,不过包含生成审核记录的、具有绑定变量的SQL语句。
 XML:与OS的作用大体相同,但使用XML标记设置生成。
 XML_EXTENDED:与XML的作用大体相同,但使用SQL语句和绑定变量。


(2)查看audit_trail参数的值,默认值为:DB


sys@OCM> show parameter trail


NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
audit_trail                          string      DB


(3)使用AUDIT命令配置数据库审核。

  使用如下命令可以审核对表的查询


sys@OCM> audit select table;


Audit succeeded.


gyj@OCM> SELECT * FROM HR.DEPARTMENTS;


DEPARTMENT_ID DEPARTMENT_NAME                MANAGER_ID LOCATION_ID
------------- ------------------------------ ---------- -----------
          300 DBA1                                   100        1000
          400 DBA2                                              1000
          500 DBA3                                             1000
                
3 rows selected.


gyj@OCM> select timestamp, USERNAME,owner,obj_name,SES_ACTIONS from dba_audit_trail where OBJ_NAME='DEPARTMENTS';


TIMESTAMP      USERNAME                       OWNER                          OBJ_NAME                                  SES_ACTIONS
-------------- ------------------------------ ------------------------------ -------------------------------------------------------------------------------------------------------------------------------- -------------------
10-03 -13     GYJ                            HR                             DEPARTMENTS                               ---------S------


 使用如下命令可以审核权限的命用


 sys@OCM> audit create any trigger;


Audit succeeded.


sys@OCM> audit select any table by session;


Audit succeeded.


默认方式下,审核会为违返审核条件的每个会话生成一个审核记录,而不考虑违反条件的次数。这相当于为AUDIT命令追加了关键字BY SESSION。
为AUDIT命令追加关键字BY ACCESS时,会为每次违反条件的情况生成一条记录。


 使用如下命令可以审核对象


 sys@OCM> audit insert on gyj.t10 whenever successful;


  Audit succeeded.


   只要会话在指定表中插入一行就会生成审核记录。WHENEVER SUCCESSFUL关键字将审核记录限制为操作成功的记录,WHENEVER NOT SUCCESSFUL是替换语法。默认方式下,会审核所有操作。


 sys@OCM> audit all on gyj.t20;


 Audit succeeded.


  审核针对指定表执行SELECT、DML及DDL语名的每个会话。
  
 DBA_AUDIT_TRAIL视图是一个很重要的视图,其它审核视图(DBA_AUDIT_OBJECT、DBA_AUDIT_STATEMENT、DBA_AUDIT_SESSION)都是DBA_AUDIT_TRAIL视图的一个子集,仅显示与相关的某些审核记录和列。




3、基于值的审核:使用了数据库触发器。在插入、更新或删除记录时,就会运行一个包括记录事件全部细节的pl/sql代码块。
 前面所描述的数据库审核可以捕获到针对某个表执行一条命令的事实,但是没有跟踪受影响的行。例如,如果执行AUDIT INSERT ON GYJ.T10命令,只要在指定表中插入一行就会生成一条审核记录,但是该审核记录不会包含插入行的实际值。有些时侯,我们希望捕获这些实际值地,此时就需要使用数据库触发器。


  gyj@OCM> create table t1 (id int,name varchar2(100));


  Table created.
  
   gyj@OCM> insert into t1 values(1,'Joe');


1 row created.


gyj@OCM> insert into t1 values(2,'Tom');


1 row created.


gyj@OCM> insert into t1 values(3,'Rose');


1 row created.


gyj@OCM> insert into t1 values(4,'Jack');


1 row created.


gyj@OCM> insert into t1 values(5,'jemmy');


1 row created.


gyj@OCM> commit;


Commit complete.


gyj@OCM> create table t_audit (os_user varchar2(20),ip_address varchar2(20),change varchar2(100));


Table created.


 创建触发器语句,操作如下:
 gyj@OCM> CREATE OR REPLACE TRIGGER gyj.name_audit
  2    AFTER UPDATE OF name
  3    ON gyj.t1
  4    REFERENCING NEW AS NEW OLD AS OLD
  5    FOR EACH ROW
  6    BEGIN
  7    IF :old.name != :new.name THEN
  8    INSERT INTO gyj.t_audit
  9    VALUES(sys_context('userenv','os_user'),sys_context('userenv','ip_address'),:new.id||' name  changed from   '||:old.name||' to '||:new.name);
 10    END IF;
 11    END;
 12    /


 gyj@OCM> update t1 set name='guoyJoe'  where name='Joe';


1 row updated.
gyj@OCM> update t1 set name='Tony'  where id=2;


1 row updated.
gyj@OCM> update t1 set name='coco'  where id=3;


1 row updated.
gyj@OCM> select * from t_audit;


OS_USER    IP_ADDRESS           CHANGE
---------- ------------------ ---------------------------------------
oracle                          1  name  changed from   Joe to guoyJoe
oracle                          2  name  changed from   Tom to Tony
oracle                          3  name  changed from   Rose to coco


 


4、细粒度审核:允计根据所访问的记录(或该记录的列)来跟踪对表的访问。与数据库审核或基于值的审核相比,细粒度审核更为精确,并且可以将生成的审核记录的范围限制为感兴趣的审核记录。
 (1)创建GYJ_EMP1,此策略将捕获读取的条件是:SELECT中出现SALARY, COMMISSION_PCT或WHERE条件中出现SALARY 列不为空和 COMMISSION_PCT 列不为空的所有SELECT的语句。(注只要SALARY, COMMISSION_PCT两列出现在SELECT或WHERE中就审计)
 操作如下:
 sys@OCM> conn hr/hr
Connected.
hr@OCM> BEGIN
  2  DBMS_FGA.ADD_POLICY(
  3     object_schema      =>  'HR', 
  4     object_name        =>  'EMPLOYEES', 
  5     policy_name        =>  'GYJ_EMP1', 
  6     audit_condition    =>  'SALARY IS NOT NULL AND COMMISSION_PCT IS NOT NULL', 
  7     audit_column       =>  'SALARY,COMMISSION_PCT', 
  8     enable             =>   TRUE, 
  9     statement_types    =>  'SELECT', 
 10     audit_trail        =>   DBMS_FGA.DB_EXTENDED, 
 11     audit_column_opts  =>   DBMS_FGA.ALL_COLUMNS); 
 12  END ;
 13  /


PL/SQL procedure successfully completed.


hr@OCM> col AUDIT_TYPE  for a20
hr@OCM> col DB_USER  for a10
hr@OCM> col OS_USER  for a10
hr@OCM> col USERHOST  for a10
hr@OCM> col OBJECT_SCHEMA  for a10
hr@OCM> col OBJECT_NAME  for a10
hr@OCM> col ACTION for a10
hr@OCM> col SQL_TEXT for a100
hr@OCM> select AUDIT_TYPE ,SESSION_ID,DB_USER,OS_USER,USERHOST,OBJECT_SCHEMA,OBJECT_NAME,ACTION,sql_text from  DBA_COMMON_AUDIT_TRAIL where sql_text like '%EMP%';


AUDIT_TYPE           SESSION_ID DB_USER    OS_USER    USERHOST   OBJECT_SCH OBJECT_NAM     ACTION SQL_TEXT
-------------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------------------------------------------------------------------------------------------------
Fine Grained Audit       470672 HR         oracle     ocm        HR         EMPLOYEES             select * from EMPLOYEES where SALARY IS NOT NULL AND COMMISSION_PCT IS NOT NULL
Fine Grained Audit       470672 HR         oracle     ocm        HR         EMPLOYEES             select * from EMPLOYEES
Fine Grained Audit       470672 HR         oracle     ocm        HR         EMPLOYEES             select * from EMPLOYEES WHERE SALARY IS NOT NULL
Fine Grained Audit       470672 HR         oracle     ocm        HR         EMPLOYEES             select * from EMPLOYEES WHERE SALARY >5000
Fine Grained Audit       470672 HR         oracle     ocm        HR         EMPLOYEES             select employee_id from EMPLOYEES WHERE SALARY IS NOT NULL AND COMMISSION_PCT IS NOT NULL


hr@OCM> SELECT SQL_TEXT FROM DBA_FGA_AUDIT_TRAIL WHERE sql_text like '%EMP%';


SQL_TEXT
----------------------------------------------------------------------------------------------------
select * from EMPLOYEES where SALARY IS NOT NULL AND COMMISSION_PCT IS NOT NULL
select * from EMPLOYEES
select * from EMPLOYEES
select * from EMPLOYEES WHERE SALARY IS NOT NULL
select * from EMPLOYEES WHERE SALARY >5000
select employee_id from EMPLOYEES WHERE SALARY IS NOT NULL AND COMMISSION_PCT IS NOT NULL
select COMMISSION_PCT from EMPLOYEES WHERE SALARY IS NOT NULL


(2)审计EMP1表中EMPNO,MGRNO,SALARY这三列的DML操作,不审计列EMPNAME
于是我创建了个审计如下:
hr@OCM>  create table EMP1 AS SELECT EMPLOYEE_ID EMPNO,LAST_NAME EMPNAME,MANAGER_ID MGRNO,SALARY FROM EMPLOYEES;


Table created.


hr@OCM> begin
  2    dbms_fga.add_policy(object_schema => 'HR',
  3                                 object_name => 'EMP1',
  4                                 policy_name => 'FGA_EMP',
  5                                 audit_column => 'EMPNO,MGRNO,SALARY',
  6                                 statement_types =>'insert,update,delete');
  7  end;
  8  /


PL/SQL procedure successfully completed.


hr@OCM> SELECT SQL_TEXT FROM DBA_FGA_AUDIT_TRAIL WHERE sql_text like '%emp1%';


SQL_TEXT
----------------------------------------------------------------------------------------------------
update emp1 set EMPNAME='Joe' where empno=100


可是,对于下面这个update也作了审计:update emp1 set EMPNAME='Joe' where empno=100;
像这样的update有很多,如果都审计了sys.fga_log$表扩展太快,请问大家有什么办法能让审计对于EMPNAME的DML操作都不审计呢?


解决办法:分别建两个策略
A)策略一对insert和delete操作的列是:EMPNO,MGRNO,SALARY。
hr@OCM> begin
  2    dbms_fga.add_policy(object_schema => 'HR',
  3                                 object_name => 'EMP1',
  4                                 policy_name => 'FGA_EMP1',
  5                                 audit_column => 'EMPNO,MGRNO,SALARY',
  6                                 statement_types =>'insert,delete');
  7  end;
  8  /


PL/SQL procedure successfully completed.


B)策略二对update操作的列是:MGRNO,SALARY,不包括了EMPNO。
hr@OCM> begin
  2    dbms_fga.add_policy(object_schema => 'HR',
  3                                 object_name => 'EMP1',
  4                                 policy_name => 'FGA_EMP2',
  5                                 audit_column => 'MGRNO,SALARY',
  6                                 statement_types =>'update');
  7  end;
  8  /


PL/SQL procedure successfully completed.




先drop掉原来的FGA_EMP策略:
hr@OCM> BEGIN
  2  DBMS_FGA.DROP_POLICY(
  3     object_schema      =>  'HR', 
  4     object_name        =>  'EMP1', 
  5     policy_name        =>  'FGA_EMP');
  6  END ;
  7  /


PL/SQL procedure successfully completed.


再对雇员名称做update测试:
hr@OCM> update emp1 set EMPNAME='gyj1' where empno=130;


1 row updated.


查审计记录:
hr@OCM> SELECT SQL_TEXT FROM DBA_FGA_AUDIT_TRAIL WHERE sql_text like '%emp1%';


SQL_TEXT
----------------------------------------------------------------------------------------------------
update emp1 set EMPNAME='Joe' where empno=100


没有发现update emp1 set EMPNAME='gyj1' where empno=130;的语句被审计了!!!





**********本博客所有内容均为原创,如有转载请注明作者和出处!!!**********
Name:    guoyJoe

QQ:        252803295

Email:    oracledba_cn@hotmail.com

Blog:      http://blog.csdn.net/guoyJoe

ITPUB:   http://www.itpub.net/space-uid-28460966.html

OCM:    http://education.oracle.com/education/otn/YGuo.HTM
_____________________________________________________________
加群验证问题:哪些SGA结构是必需的,哪些是可选的?否则拒绝申请!!!

答案在:http://blog.csdn.net/guoyjoe/article/details/8624392

Oracle@Paradise  总群:127149411

Oracle@Paradise No.1群:177089463(已满)

Oracle@Paradise No.2群:121341761

Oracle@Paradise No.3群:140856036