数据库原理——第四章:数据库安全性

参考书目《数据库系统概论(第5版)》

数据库安全性概述

数据库安全标准:TCSECCC
TCSEC/TDI安全级别划分(从上到下安全级别逐渐降低)

安全级别 定义
A1 验证设计
B3 安全域
B2 结构化保护
B1 标记安全保护
C2 受控的存取保护
C1 自主安全保护
D 最小保护

C1级:只提供了非常初级的自主安全保护,能够实现对用户和数据的分离,进行自助存取控制(DAC)
B1级:对系统的数据加以标记,并对标记的主体和客体实施强制存取控制(MAC)以及审计等安全机制。B1级别的产品才被认为是真正意义上的安全产品


数据库安全性控制

用户身份鉴别

这是数据库管理系统提供的最外层安全保护机制

  1. 静态口令鉴别
  2. 动态口令鉴别
  3. 生物特征鉴别
  4. 智能卡鉴别

存取控制

存取控制机制主要包括定义用户权限合法权限检查,二者一起组成了数据库管理系统的存取控制子系统

  • 自主存取控制:用户对于不同的数据库对象拥有不同的存取权限,不同用户对同一对象也有不同权限,而且用户可以将其拥有的权限转授给其他用户。因此自主存取控制非常灵活
  • 强制存取控制:每个数据库对象被标以一定的密级,每一个用户也被授予某一个级别的许可证。对于任意一个对象,只有具有合法许可证的用户才可以存取。因此强制存取控制相对比较严格

自主存取控制方法

用户权限由两个要素组成:数据库对象操作类型
定义用户的存取权限称为授权

———后续语句实现基于MySQL———

创建用户

1
2
CREATE USER <用户名>@<用户登陆主机> [IDENTIFIED BY <密码>];
CREATE USER <用户名>; /*可以在本地无密码登录的账户*/
  • 用户登录主机若不填写则默认为localhost,若要允许远程登陆,则localhost可以替换为相应的主机ip,或者直接替换为:%(表示任何一台主机都可以远程登陆)
  • 新用户的密码可以选择不创建

修改用户密码

1
2
ALTER USER <用户名>@<用户登陆主机> IDENTIFIED BY <新密码>
SET PASSWORD FOR <用户名>@<用户登陆主机> = PASSWORD('新密码') /*创建新密码*/

删除用户

1
DROP USER [IF EXIST] <用户名>@<用户登陆主机>

给用户授权

1
GRANT <权限>(属性名),... ON <数据库名>.<数据库表名>,... TO <用户名>@<用户登陆主机>,... [WITH GRANT OPTION]
  • 如果指定了WITH GRANT OPTION子句,则获得某种权限的用户还可以把这种权限再授予其他用户(传播权限)
  • 对于<权限>(属性名),如UPDATE(Sno)表示对于Sno这个属性具有更新的权限,若不填则默认为所有属性
  • 如果想给新用户所有的权限,可以直接使用ALL PRIVILEGES

收回授权

1
REVOKE <权限>(属性名),... ON <数据库名>.<数据库表名>,... FROM <用户名>@<用户登陆主机>,...

数据库角色

MySQL 8.0 为了用户权限管理更容易,提供了一个角色管理的新功能
数据库角色是被命名的一组与数据库操作相关的权限,角色是权限的集合。如果用户被授予角色权限,则该用户拥有该角色的权限,从而简化授权过程
MySQL 8.0 提供的角色管理功能如下:

1
2
3
4
5
6
7
8
CREATE ROLE 角色创建
DROP ROLE 角色删除
GRANT 为用户和角色分配权限
REVOKE 为用户和角色撤销权限
SHOW GRANTS 显示用户和角色的权限
SET DEFAULT ROLE 指定哪些帐户角色默认处于活动状态
SET ROLE 更改当前会话中的活动角色
CURRENT_ROLE() 显示当前会话中的活动角色
  1. 创建用户、分配权限、回收权限、验证

    • 创建用户

      1
      CREATE USER wsy@'%' IDENTIFIED BY '111111';
    • 分配权限

      1
      GRANT INSERT,UPDATE,ALTER ON test.* TO wsy@'%';
    • 回收权限

      1
      REVOKE UPDATE ON test.* FROM wsy@'%';
    • 验证

      1
      2
      3
      4
      5
      6
      7
      /*使用用户wsy登录Mysql之后*/
      SELECT user();
      USE test;
      DESC P;
      INSERT INTO P VALUES ('P7', '螺母', '绿', 32);
      SELECT * FROM P WHERE PNO='P1'
      UPDATE P SET P=P+10 WHERE COLOR='红';

      结果如下

  2. 创建角色、分配权限、回收权限、验证

    • 创建角色

      1
      CREATE ROLE visitor;
    • 分配权限

      1
      GRANT SELECT ON test.* TO visitor;
    • 回收权限

      1
      REVOKE SELECT ON test.* FROM visitor;
    • 验证

      1
      2
      3
      4
      5
      /*root账户下,分配visitor角色给wsy*/
      GRANT visitor TO wsy;

      /*使用用户wsy登录Mysql之后*/
      USE test;

强制存取控制方法

自助存取控制可能不安全的根本原因在于:仅仅通过对数据的存取控制权限来进行安全控制,而数据本身并无安全性标记
在强制存取控制中,全部实体被分为主体客体两大类。主体是系统中的活动实体,客体是系统中的被动实体,受主体操控
数据库管理系统为每个实例指派一个敏感度标记,敏感度标记可被分为:TS >= S >= C >= P
主体的敏感度标记称为许可证级别,客体的敏感度标记称为密级
判定规则:

  • 仅当主体的许可证级别大于或等于客体的密级是,该主体才能读取相应的客体
  • 仅当主体的许可证级别小于或等于客体的密级是,该主体才能相应的客体

视图

通过视图机制把要保密的数据对无权存取的用户隐藏起来


审计

审计功能把用户对数据库的所有操作自动记录下来放入审计日志中。管理人员可利用审计日志监控数据库的各种行为,重现操作过程,找出非法存取数据的人、时间和内容等

———后续语句实现基于MySQL8.0———

  1. 开启审计功能

    • 设置变量

      1
      2
      3
      4
      5
      6
      7
      8
      /*打开审计开关*/
      set global general_log = on;
      set global general_log_file = '/var/lib/mysql/operation.log';
      set global log_timestamps = SYSTEM;

      /*查看审计状态*/
      show global variables like 'log_timestamps';
      show global variables like '%general%';
  2. 设置审计权限

    • 创建用于存放连接日志的数据库和表

      1
      2
      3
      4
      5
      6
      7
      8
      9
      create database auditlog;
      create table auditlog.t_audit(
      id int not null auto_increment,
      thread_id int not null,
      login_time timestamp,
      localname varchar(50) default null,
      matchname varchar(50) default null,
      primary key (id)
      )ENGINE=InnoDB default charset=utf8 comment '审计用户登录信息';
    • 授权某个用户拥有对审计表的select和insert权限

      1
      2
      3
      4
      5
      /*给出对所有用户授权的语句(拼结授权语句)*/
      SELECT concat("GRANT SELECT,INSERT ON auditlog.t_audit to '",user,"'@'",host,"';") FROM mysql.user;

      /*授权用户wsy*/
      GRANT SELECT,INSERT ON auditlog.* to wsy@'%';
    • 设置init_connect参数

      1
      SET GLOBAL init_connect='INSERT INTO auditlog.t_audit(id,thread_id,login_time,localname,matchname) VALUES(null,connection_id(),now(),user(),current_user());';
  3. 普通用户登录,执行操作

    • 查看登录记录

      1
      SELECT * FROM t_audit WHERE matchname='wsy@%';
    • 执行插入操作

      1
      INSERT INTO P VALUES ('P8', '丝轴', '银', 12);

      之后查看日志记录cat /var/lib/mysql/operation.log

      可以看到insert操作已经被记录下来

    • 查照操作者

      1
      2
      /*使用root用户*/
      SELECT * FROM t_audit;

      可以看到用户wsy在2019-05-07 19:10:56登录,并在2019-05-07 19:11:11进行了insert操作。