数据的安全

按层面划分:

  • 网络层

    • 防火墙
    • vpn
  • 系统层

    • 操作系统漏洞
    • 病毒、木马
  • 应用层

    • 数据加密
    • 认证
    • SQL注入
  • 数据库层

Oracle的安全方案:

  • 用户管理(相关产品:Advanced Security)

    • 安全密码
    • 用户管理
    • 强认证
    • 代理认证
    • 基本的安全配置
  • 访问控制(相关产品:VPD、Database Vault)

    • 控制用户的权限
    • 控制who、when、where访问what数据
    • 数据权限
    • 行级安全性
    • 数据分类
    • 多级安全管理
  • 数据保护(相关产品:Advanced Security、TDE、Secure Backup)

    • 数据加密
    • 网络加密
    • 数据隐藏
    • 导出加密
    • 备份加密
  • 监控(相关产品:Database vault、Audit Vault)

    • 数据库审计
    • 细粒度审计
    • 审计报告和预警
    • 安全配置扫描

Oracle的认证

Oracle的认证方式:

  • 数据库认证(普通用户)

    密码保存在数据库中,需要数据库处于open状态。

  • 密码文件认证(具有SYSDBA角色的用户)

    密码保存在密码文件中

  • 操作系统认证

    操作系统级别的认证,只要用户登录进了操作系统,就可以不用密码直接登录。

数据库认证:

  1. # 需要输入用户名/密码,oracle把密码和数据库中的进行比对
  2. sqlplus test/test

密码文件认证:

  1. # 在数据库实例没有启动的情况下,使用以下命令
  2. # 数据库实例没有启动,而且登录的是sysdba身份的用户,oracle会和密码文件中的密码进行比对
  3. sqlplus test/test as sysdba

操作系统认证:

  1. # 当前操作系统登录的用户具有dba权限,直接登录
  2. sqlplus / as sysdba

密码文件认证时,密码文件保存位置:$ORACLE_HOME/database/PWD实例名.ora,例如:

  1. D:\PC_Software\Program_Software\DataBase_Software\Database_Server\oracle\app\Administrator\product\11.2.0\dbhome_1\database\PWDorcl.ora

创建密码文件:

# orapwd是oracle安装的系统命令
# orapwd file=<密码文件名> entries=<该密码文件中最多可以放多少个用户密码>
# 命令参数的等号两边不可以有空格
orapwd file=OraPwdOrcl entries=30

操作系统认证的设置:

在sqlnet.ora文件中设置,$ORACLE_HOME/network/admin/sqlnet.ora

SQLNET.AUTHENTICATION_SERVICES=(NTS)

该配置有三个选项:

  • ALL:对于Linux设置为all或者默认,可以进行操作系统认证。
  • NTS:对于Windows,设置为NTS可以进行操作系统认证
  • NULL:windows下不能进行操作系统认证

设置为all时,windwos 下使用sqlplus / as sysdba登录会报错:

ORA-12641:验证服务无法初始化

设置为null时,windows下使用sqlplus / as sysdba登录会报错:

ORA-01031: insufficient privileges

Oracle的权限管理

查看Oralce的权限(privilege):

select * from dba_sys_privs;

查看oracle的角色(role):

select * from dba_roles;

角色和权限对应关系:

select * from role_sys_privs;

给用户赋予单一的权限:

-- 将查看sys.tab$表的权限赋给test用户
grant select on sys.tab$ to test;

给用户赋予角色:

grant connect to test;  -- 给用户resource角色
grant resource to test;  -- 给用户resource角色

oraclce Advanced Security产品

功能:

  • 数据加密(Data Encryption)
  • 强验证机制(Strong Authentication)

Oracle透明加密技术(TDE)

TDE(Tranparent Data Encryption)

  • 基于列的加密
  • 基于表空间的加密(oracle 11g)

优势:

  • 数据列进行加密,列依然可以建索引
  • 对应用透明
  • 管理简便,无需应用设置

限制:

  • 只能使用 B-Tree 索引
  • 加密的列无法对索引进行 range scan 操作
  • 不能对外部对象加密
  • 不能对可传输表空间加密
  • 不能进行exp/imp操作

基于列的加密的机制

oracle有一个外部安全模块(External Security Module),可以产生一个Wallet钱包(Master Key),外部模块通过Wallet进行加密后传给Oracle内部。

Oracle内部 Data Dictionary 有列的密钥(Column Keys),对外部模块传入的内容再做一次加密。

配置步骤

使用TDE进行基于列的加密:

  • 需要保证数据库版本高于10g R2

  • 需要设置wallet钱包的位置
    $ORACLE_HOME/network/admin/sqlnet.ora中添加配置:

    ENCRYPTION_WALLET_LOCATION = (SOURCE = 
                                          (METHOD = FILE)
                                          (METHOD_DATA = 
                                              # 指定钱包路径
                                              (DIRECTORY=D:\app\xxxx\wallet)
                                          )
                              )
    

TDE支持的加密算法:

  • 3DES168
  • AES128
  • AES192(default)
  • AES256

加密配置步骤:

  • 在wallet里面创建key
    -- 授权访问。
    -- myPassword不是key的值,而是要访问这个key时需要输入的密码
    alter system set encryption key authenticated by "myPassword";
    
  • oracle会自动在sqlnet.ora配置的钱包文件夹中创建wallet文件

  • 创建表时,对指定列加密

    create table tde_test(
      id number(10) primary key,
      info varchar2(50) encrypt using 'AES192'
    );
    
  • 查看系统表中加密的列
    select * from dba_encrypted_columns;
    

对加密表查询

如果要查询加密表,需要打开wallet:

-- 打开wallet
alter system set wallet open identified by 'myPassword';

此时使用sql查询时感觉不到加密的存在(对应用透明):

select * from tde_test;

对索引的影响

关闭wallet后无法查看表信息:

-- 关闭wallet
alter system set wallet close identified by 'myPassword';

此时查询tde_test表时,会报错:

ORA-28365:Wallet未打开

只有将加密列的属性设置为 no salt 时,才可以创建索引,否则会报错:

ORA-28338:不能同时使用 salt 值索引和加密列

设置加密列为 no salt

alter table tde_test modify info encrypt no salt;

此时可以为加密列正常创建索引:

-- 为加密列创建索引
create index idx_td on tde_test(info);

可以使用加密列索引进行等值查询:

-- 使用索引列进行等值查询
select * from tde_test where info='test'

但是对加密列建索引后,该索引不能走 range scan:

-- tde_test2表对数值型的id设置为加密列,然后添加索引
-- 此时对id进行范围扫描时,可以正常查出数据,但是没有走索引范围扫描,而是走的全表扫描
select * from tde_test2 where id < 2;

使用in进行查询时依然可以走索引:

-- oracle 会将in语句转换成or语句:select * from t where id=1 or id=2 or id=3
-- 此时会走索引
select * from t where id in (1, 2, 3);

加密表空间

创建加密表空间,该表空间上的表都会被加密,不再是对某张表的某个字段进行加密。

语句:

-- 创建加密表空间
create tablespace tde_tablespace
encryption using 'AES256'
default storage(encrypt);

查看表空间是否为加密表空间:

select tablespace_name, encrypted from dba_tablespaces;

和加密字段的区别:

表空间加密是发生在数据存储的时候,也就是存储在文件上的数据已经被加密。字段加密发生在SQL层,由SQL调用一个算法对数据进行加密处理。

表空间加密的数据,不会再受到字段加密的限制,例如:

  • 字段类型
  • 索引类型
  • 需要 no salt 创建索引
-- 在加密表空间上可以正常的创建表
create table t tablespace tde_tablespace as select * from dba_objects;
-- 可以创建索引,不再受no salt限制
create index idx_t on t(object_id);
-- 可以正常走索引范围扫描
select * from t where object_id < 10;

加密表空间的限制:

  • 外部大对象(bfiles)不可以
  • 不可以使用exp/imp,需要使用 expdp/impdp

当wallet关闭时,加密表空间上的数据全部无法访问:

-- 关闭wallet
alter system set encryption wallet close identified by 'myPassword2';

此时查询表空间上的表时,会报错:

ORA-28365:Wallet未打开

此时在该表空间上创建表时,也会报一样的错。

总结

TDE的用途:

  • 保护敏感的数据,禁止未授权的人访问
  • 防止数据的丢失。别人即使导出拿到数据文件,也会因为没有wallet而无法查看真实数据
  • 防止数据在传递过程中被截获

数据访问安全

Oracle数据访问安全的相关产品:

  • VPD(Virtual Private Database)
  • OLS(Oracle Label Security)

优势:

  • 更精细的访问控制
  • 对业务透明

VPD

VPD(Virtual Private Database):Oracle自带的细粒度权限产品,通过指定策略,对用户的SQL添加过滤的谓词,来达到过滤数据的目的。

例如:

A部门的用户发出一条SQL:select * from t时,只能查看到deptNo='A'的数据。B部门的用户发出同样的SQL,只能看到deptNo='B'的数据。

操作:

创建函数:

-- 指定一个函数,返回要添加的where条件
create or replace function hide_sal_comm(v_schema varchar2, v_object varchar2)
return varchar2 as 
    con varchar2(200);
begin
    con:='deptNo=30';
    return(con);
end hid_sal_comm;

添加策略:

begin
    dbms_rls.add_policy(
        object_schema => 'scott',  -- 用户
        object_name => 'emp',     -- 表名
        policy_name => 'hide_sal_policy',  -- 策略名
        policy_function => 'hide_sal_comm',  -- 生成where条件的函数
        sec_relevant_cols => 'sal,comm'  -- 只有用户查询字段带有sal或者comm字段时才启用规则
    );
end;

此时发出查询emp:

-- 只能查看到 deptNo=30 的数据
select * from emp;

-- 没有查询sal或者comm字段,所以会显示所有数据
select deptNo from emp;

-- 只能看到 dept=30 的数据
select deptNo,sal from emp;

也可以实现隐藏敏感列的数据:

begin
    dbms_rls.add_policy(
        object_schema => 'scott',  
        object_name => 'emp',   
        policy_name => 'hide_sal_policy',
        policy_function => 'hide_sal_comm',
        sec_relevant_cols => 'sal,comm',
        sec_relevant_cols_opt => dbms_rls.all_rows  -- 显示所有行,但是敏感列的内容置空
    );
end;

此时查询emp表:

-- 此时会返回表中所有的行。但是只有deptNo=30的行中字段sal、comm有值,其他行的sal、comm为空,其他字段可以正常显示。
select * from emp;

删除策略:

exec dbms_rls.drop_policy('scott', 'emp', 'hide_sal_policy');

OLS

OLS(Oracle Label Security):在Oracle 10g时默认没有安装OLS,需要在安装Oracle时勾选Oracle Label Security。在Oracle 11g时,已经默认集成到了Oracle产品中,只需启用即可。

Oracle 11g 启用OLS:

chopt enable lbac

使用该命令后,oracle会将$ORACLE_HOME/bin/下的oralbac.dll.dbl重命名成oralbac.dll

所以直接将该文件重命名也可以启用该服务。

启用OLS后,需要重启Oracle服务。

启用OLS之后,使用sqlplus连接数据库时,输出的信息中,在oracle版本号下面,会出现Oracle Label Security

启用OLS之后,还需要对数据库进行一些配置才能使用:

  1. 使用命令进入Database Configuration Assistant:
    dbca
    
  1. 选择 配置数据库选件

  2. 数据库组件中勾选 Oracle Label Security

  3. 后面一直下一步即可

这个过程,oracle会在数据库中创建OLS需要用到的用户、用户视图等相关内容。

Oracle的SQL权限工作机制:

OLS会在对应的表上增加一个伪列(称为标签label),通过这个标签上的策略控制数据访问权限。

例如,创建如下的安全策略:

姓名 标签等级 权限
Tom SENSITIVE ‘BEIJING’,’TOKYO’,’SIINGAPORE’
Peter CONFIDENTIAL ‘MUNICH’,’OXFORD’,’ROME’
Rose PUBLIC 其他

创建策略:

-- 配置了OLS后,数据库中就会自动加入lbacsys用户,需要先将该用户解锁、设置密码
-- 使用lbacsys用户连入数据库
conn lbacsys/lbacsys

-- 创建策略
exec sa_sysdba.create_policy(
    policy_name => 'ACCESS_LOCATIONS',  -- 策略名称
    column_name => 'OLS_COLUMN' -- 字段名(要访问的表会增加一个伪列,这个是指定伪列的列名)
);

-- 查看所有策略
select policy_name, status from DBA_SA_POLICIES

创建等级:

-- 创建PUBLIC标签等级
exec sa_components.create_level(
    policy_name => 'ACCESS_LOCATIONS',  -- 策略名
    level_num => 1000,      -- 数字越大级别越高,高等级可以访问低等级的数据
    short_name => 'PUB',    -- 缩写名称
    long_name => 'PUBLIC CITY'  -- 完整名称
);

-- 创建CONFIDENTIAL标签等级
exec sa_components.create_level(
    policy_name => 'ACCESS_LOCATIONS',
    level_num => 2000,
    short_name => 'CONF',
    long_name => 'CONFIDENTIAL CITY'
);

-- 创建SENSITIVE标签等级
exec sa_components.create_level(
    policy_name => 'ACCESS_LOCATIONS',
    level_num => 2000,
    short_name => 'SENS',
    long_name => 'SENSITIVE CITY' 
);

查看创建的等级:

select * from dba_sa_levels order by level_num;

创建标签:

-- 创建1000标签,级别对应到PUB
exec sa_label_admin.create_label(
    policy_name => 'ACCESS_LOCATIONS',  -- 策略名
    LABEL_TAG => '1000',  -- 标签名
    LABEL_VALUE => 'PUB',   -- 对应到level
    DATA_LABEL => TRUE
);

-- 创建2000标签,级别对应到CONF
exec sa_label_admin.create_label(
    policy_name => 'ACCESS_LOCATIONS',
    LABEL_TAG => '2000',
    LABEL_VALUE => 'CONF',
    DATA_LABEL => TRUE
);

-- 创建3000标签,等级对应到SENS
exec sa_label_admin.create_label(
    policy_name => 'ACCESS_LOCATIONS',
    LABEL_TAG => '3000',
    LABEL_VALUE => 'SENS',
    DATA_LABEL => TRUE
);
-- 将策略应用到表上
exec sa_policy_admin.apply_table_policy(
    policy_name => 'ACCESS_LOCATION',  -- 策略名
    schema_name => 'HR',  -- 用户名
    table_name => 'T_LOCATIONS',  -- 表名
    table_options => 'LABEL_DEFAULT'  -- 表的选项
)

给用户设置策略和标签级别:

exec sa_user_admin.set_user_labels(
    policy_name => 'ACCESS_LOCATIONS',  -- 策略名称
    user_name => 'TOM',  -- 用户名
     max_read_label => 'SENS'  -- 用户可以读取的该策略下的标签level
);
exec sa_user_admin.set_user_labels(
    policy_name => 'ACCESS_LOCATIONS',  
    user_name => 'PETER',  
     max_read_label => 'CONF'  
);
exec sa_user_admin.set_user_labels(
    policy_name => 'ACCESS_LOCATIONS',  
    user_name => 'ROSE',  
     max_read_label => 'PUB' 
);

给表中的每行数据设置标签值:

exec sa_user_admin.set_user_labels(
    policy_name => 'ACCESS_LOCATIONS',  
    user_name => 'HR',  
    privileges => 'FULL' 
);

update t_locations set ols_column = char_to_label('ACCESS_LOCATIONS', 'SENS')
where city in ('BeiJing', 'Tokyo','Singapore');

update t_locations set ols_column = char_to_label('ACCESS_LOCATIONS', 'CONF')
where city in ('Munich', 'Oxford', 'Rome');

update t_locations set ols_column = char_to_label('ACCESS_LOCATIONS', 'PUB')
where city is null;

后续该表如果插入了新的数据,也需要接着为新插入的数据也设置标签值。

查看标签:

select * from hr.t_locations order by city;

可以看到,表中多了一个伪列OLS_COLUMN,该字段的值是Label_Tag

使用不同用户查询该表时,只会显示该用户有权限的标签的数据行。

删除相关信息:

exec sa_label_admin.drop_label(
    policy_name => 'ACCESS_LOCATIONS',
    label_tag => 1000
);
exec sa_label_admin.drop_label(
    policy_name => 'ACCESS_LOCATIONS',
    label_tag => 2000
);
exec sa_label_admin.drop_label(
    policy_name => 'ACCESS_LOCATIONS',
    label_tag => 3000
);

exec sa_policy_admin.remove_table_policy(
    policy_name => 'ACCESS_LOCATIONS',
    schema_name => 'HR',
    table_name => 'T_LOCATIONS'
);

exec sa_sysdba.drop_policy(
    policy_name => 'ACCESS_LOCATIONS'
);

Database Vault

oracle 10g需要另外下载 database vault安装包。11g 已经整合到数据库安装包中,直接配置使用即可。

Database Vault:通过将权限限定在特定范围内(Realms域方式、命令集方式),来达到安全的目的。最重要的是解决了对sysdba角色的用户管理。

Realms域方式:将数据划分成不同的域,不同域的DBA用户不能访问没有权限的域数据。

Command Rule Flexibility(命令集)方式:给用户设置具体的命令权限。

11g配置启用Database Vault:

# 启用Database Vault
chopt enable dv
# 重启数据库服务
net stop oracleserviceorcl
net start oracleserviceorcl

windows下,使用chopt启用database vault后,会将$ORACLE_HOME/bin/下的oradv.dll.dbl重命名为oradv.dll文件。

重启数据库服务后,使用sqlplus连接数据库时,可以看到服务中多了Oracle Database Vault服务。

使用dbca命令打开 Database Configuration Assistant,配置 Database Vault:

  1. 选择配置数据库选件
  2. 勾选Oracle Database Vault
  3. 创建一个Database Vault的用户,并设置密码
  4. 等待安装完成即可

oracle建议使用OEM网页对Database Vault进行配置。也可以使用oci中的包、存储过程进行配置。使用OEM配置比较简单。

Database Vault管理页面的地址、端口和OEM一样,假如OEM地址为:https://localhost:1158/em/,那么Database Vault管理页面为:https://localhost:1158/dva/

审计

审计层面:

  • Trigger:based Auditing(触发器)
  • Auditing the sys User:Sys用户审计
  • Standard Auditing:标准审计
  • Managing the Audit Trail:审计日志管理

触发器审计:

create trigger tra_a_idu_r_emp_sal
after insert or delete or update of sal on emp
for each row
begin
    if(:NEW.sal > :OLD.sal * 1.10)
        then insert into emp_sal_audit value(:OLD.empno, :OLD.sal, :NEW.sal, user, sysdate);
    end if;
end;

sys用户的审计:

alter system set audit_sys_operations=true,scope=spfile;

sys用户审计日志会写到系统日志中,且该路径不是oracle自带路径,而是操作系统的日志路径。

标准审计:(普通数据库用户的审计)

alter system set audit_trail=DB, extended_scope=spfile

会保存在数据库的aud$视图中,也可以配置成写到操作系统中。放在操作系统会存在$ORACLE_BASE/admin/sid/adump路径下。

可以审计的内容:

  • 审计会话
  • 审计对象
  • 审计操作
  • 审计授权

对表审计:

-- 对test用户的t表审计
audit select,insert,update,delete on test.t;

查看审计日志:

select * from sys.aud$;

管理审计数据:

  • sys.aud$
  • 操作系统文件:$ORACLE_BASE/admin/sid/adump
  • audit vault审计保险柜
  • sys用户放在syslog中

Audit Vault

Aduit Vault: 集中管理审计数据

  • 统一保管审计数据
  • 告警机制
  • 提供报告
  • 审计策略统一管理

可以在OEM企业管理器中管理Audit Vault,例如:https://localhost:1158/av/

Audit Vault是Oracle的审计数据统一管理的产品,但是它也可以对 Sql Server、ASE、DB2等数据库,以及Text文本文件的审计信息进行抽取管理。

Audit Vault支持的数据库版本:

  • Oracle 9iR2、10g、11g
  • Sql Server 2000、2005、2008
  • DB2 8.2、9.1、9.5,(Linux、Unix、Windows)
  • Sybase ASE 12.5.4 - 15.0.x