前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >谁在攻击我的数据库?审计功能大揭密

谁在攻击我的数据库?审计功能大揭密

作者头像
腾讯数据库技术
发布2018-06-05 17:11:47
2.7K0
发布2018-06-05 17:11:47
举报

什么是数据库审计

对于一个仓库,如果要防盗, 常见做法是出入口全装上监控,一旦有问题了,调监控查找异常情况。对数据库来说也类似,数据库也有出入口,对所有连接出入口监控,记录下所有动作,一旦有问题了,查询历史动作,找到关键信息。如果仓库中的东西价值高,损失已经造成,监控只是事后诸葛,所以往往请专业人士在巡逻防盗,防止偷盗发生。同样数据库审计也有更专业的手段,sql阻断,在动作发生前,对动作行为分析,如果判断符合预先设置的高危动作,直接中止执行,防止对数据造成破坏。 审计定义:能够实时记录网络上的数据库活动,对数据库遭受到的风险行为进行告警,对攻击行为进行阻断

常见的审计方式

应用层审计 在应用系统中直接审计,语句还没往数据库后台发就先做了审计,不影响数据库性能,对底层用的是什么数据库也不关心,但对应用系统压力比较大,并且应用系统需要解析语句,有一定复杂度。

传输层审计 往往抓包解析实现,对上下层都没什么影响,但同样要解析语句,有一定复杂度,并且如果传输层是通过加密通讯,将无法解析。

插件审计 对于开源数据库,通常都有提供插件方式增加功能。审计可以以插件直接嵌在内核上,当然会对数据库性能有一定影响,但同样因为直接嵌在内核,很多一手信息能直接拿到,比方说上面没办法回避的语法解析就不用做,而且还能直接拿更多的运行态信息,能开发功能强大又灵活的审计功能。

内核审计 直接在内核上实现,所有功能都能实现,也能将性能影响降到最低,但是对后台稳定性会有影响,对开发人员要求高,不管是开源还是非开源数据库,都会非常慎重考虑直接在内核上支持审计。

oracle审计简介

谈到数据库审计,不能不提oracle,oracle 数据库的审计功能有10多年甚至更长的历史了,对数据库sql审计功能影响深远,几乎任何数据库审计都会参考,下面我们简单了解下oracle审计。 Oracle中审计总体上可分为“标准审计”和“细粒度审计”,标准审计包含语句审计,权限审计,对象审计,细粒度审计也称为“基于政策的审计”:

审 计 类 型

说 明

语句审计

按照语句类型审计SQL语句.而不论访问何种特定的模式对象。也可以在数据库中指定一个或多个用户,针对特定的语句审计这些用户

权限审计

审计系统权限,例如GRANT。和语句审计一样,权限审计可以指定一个或多个特定的用户作为审计的目标

对象审计

审计特定模式对象上运行的特定语句(例如,DEPARTMENTS表上的UPDATE语句)。模式对象审计总是应用于数据库中的所有用户

细粒度的审计

根据访问对象的内容来审计表访问和权限。使用程序包DBMS_FGA来建立特定表上的策略

默认情况下审计是关闭的,因为开启性能影响大,需要设置一些参数打开它,审计记录结果既可以放文件也可以放系统表中。那么怎么配置需要审计的内容呢?oracle提供了一套审计配置语法来做这事,audit/noaudit,审计和取消审计,是互逆的,如下所示:

示例如下:

代码语言:javascript
复制
// 审计u1.t2这个表的update 不成功的语句
audit update on u1.t2 by  access whenever not successful;
// 审计u1.t2这个表的update 成功的语句
audit update on u1.t2 by  access whenever successful;
运算式:f+s=a  连续运行上面两个配置语句,等价审计全部
// 审计u1.t2表update全部语句,全部包括两种,成功和失败
audit update on u1.t2 by  access;
// 不审计u1.t2表update成功的语句
noaudit update on u1.t2 by  access whenever successful;
运算式:a-s=f  连续运行上面两个配置语句,等价只审计失败语句
a:all,全部
f:fail,失败
s:success,成功

这就是oracle审计配置语法用法,配置完成后就能审计到相应的语句,它的成功、失败、全部是存在运算关系的。如何查询比较简单,直接查询相关表就行,不再介绍。

mysql审计插件

前文提到,插件是数据库实现审计功能的常见手段,mysql上也有不少审计插件,比较有名的Macfee插件官方audit pluginmariadb audit pluginPercona audit plugin。 从功能上来说,这几个插件大同小异,只是展示的审计内容和格式略有差异。从性能上来说,除了macfee插件外,其它几个性能相差不多,宣称都是15%左右影响,macfee则可能达到50%或更多。实际上,确定一个测试性能损失的标准场景是需要商榷的,跑非常简单的语句,几十万Qps,性能影响肯定大,审计性能消耗和语句量直接关联,跑OLAP查询,几秒甚至几十秒执行一个语句,审计性能影响可以说没有,所以审计性能损失得看具体场景。 从实现方式来说,这几个插件也差不太多,从thd对象中取到所需要的属性,按一定规则过滤,按某种策略存盘,以json或xml等格式展示审计结果。

mysql审计接口详细分析

从5.5开始,mysql内核中已经增加了一套的对服务器操作的审计机制的接口,添加了额外的审计流程来对我们所关心的地方进行事件捕获,如果要对服务器进行审计,只要基于这些完善一个插件即可。 mysql审计接口官方第一次是提交到代码是2009年底,历史也比较悠久了,修改和增加的文件并不多,几个关键点介绍下。 1. 在plugin.h中增加一个新的宏 MYSQL_AUDIT_PLUGIN 用来标识一类全新的插件类型:AUDIT插件 2. 增加了一个新的头文件:plugin_audit.h,里面有审计相关的关键的结构体及一些宏定义,如下: mysql_event_general结构,query信息结构,对应非登陆相关的动作,如执行一个语句select或一个命令exit。

代码语言:javascript
复制
struct mysql_event_general
{
  unsigned int event_subclass;              //子事件类型 
  int general_error_code;                   //错误码  
  unsigned long general_thread_id;          //线程号
  const char *general_user;                 //用户名
  unsigned int general_user_length;         //长度 
  const char *general_command;              //命令,如connect,query,shutdown等,error类型存错误,其它为null 
  unsigned int general_command_length;
  const char *general_query;                //sql语句  
  unsigned int general_query_length;
  struct charset_info_st *general_charset;  //字符集
  unsigned long long general_time;          //时间戳 
  unsigned long long general_rows;          //行计数器 
  MYSQL_LEX_STRING general_host;            //来自主机,如localhost 
  MYSQL_LEX_STRING general_sql_command;     //操作类型,如select 
  MYSQL_LEX_STRING general_external_user;   // external 用户
  MYSQL_LEX_STRING general_ip;              //ip地址
};

mysql_event_connection,连接信息结构,对应登陆登出动作

代码语言:javascript
复制
struct mysql_event_connection
{
  unsigned int event_subclass;
  int status;                           //错误码 
  unsigned long thread_id;
  const char *user;
  unsigned int user_length;
  const char *priv_user;
  unsigned int priv_user_length;
  const char *external_user;
  unsigned int external_user_length;
  const char *proxy_user;
  unsigned int proxy_user_length;
  const char *host;
  unsigned int host_length;
  const char *ip;
  unsigned int ip_length;
  const char *database;                 //数据库名
  unsigned int database_length;
};

所有动作都可以用这两个结构来描述,但是并不是说就能满足全部需求,比方说,对general动作,我想知道语句是针对哪些表的,执行了多长时间,无法得到,对于connect动作,我想知道是什么时间发生的,无从得知,这肯定是不够的,仍需我们去继续丰富功能点。

几个关键的宏定义:

代码语言:javascript
复制
#define MYSQL_AUDIT_GENERAL_CLASS 0             //general动作
#define MYSQL_AUDIT_GENERAL_LOG 0               //log时,语句execute前
#define MYSQL_AUDIT_GENERAL_ERROR 1             //error时,反馈用户前       
#define MYSQL_AUDIT_GENERAL_RESULT 2            //结果集返回后
#define MYSQL_AUDIT_GENERAL_STATUS 3            //审计流程结束状态

#define MYSQL_AUDIT_CONNECTION_CLASS 1          //connect动作
#define MYSQL_AUDIT_CONNECTION_CONNECT 0        //连接
#define MYSQL_AUDIT_CONNECTION_DISCONNECT 1     //断开
#define MYSQL_AUDIT_CONNECTION_CHANGE_USER 2    //切换用户

3. 核心功能实现代码:sql_auditc.h,sql_audit.cc,初始化,回收,以及最重要的取出thd对象有效值等一系列动作均在此完成。 在sql_auditc.h中,定义了两个内联函数和三个宏,功能是获取到thd对象中有用值,如用户名,数据库名,时间,sql内容等所需要信息,以参数的形式传给下一层接口。每个动作,都会从这里获取原始信息,会频繁调用这几个函数,所以使用了宏和内联函数来提高性能。 在sql_audit.cc中,除了审计插件初始化,回收外,最重要的功能获得操作原始信息,在这里实现了函数获得上面sql_auditc.h中通过参数形式传入的有用信息,并存入mysql_event_general和mysql_event_connection结构。 4. mysql其它一些连接、插入、解析、日志等接口也增加了审计入口函数。如mysqld.cc、sql_parse.cc等文件中函数增加了审计入口。

审计执行流程简介 登陆登出流程

代码语言:javascript
复制
#0  audit_null_notify (thd=0x7fdcc7ff6000, event_class=0, event=0x7fdd45440cb0) at /mysql56/plugin/audit_null/audit_null.c:99
#1  0x0000000000683f22 in plugins_dispatch (thd=0x7fdcc7ff6000, event_subtype=<value optimized out>, ap=<value optimized out>) at /mysql56/sql/sql_audit.cc:455
#2  event_class_dispatch (thd=0x7fdcc7ff6000, event_subtype=<value optimized out>, ap=<value optimized out>) at /mysql56/sql/sql_audit.cc:491
#3  general_class_handler(THD *, uint, typedef __va_list_tag __va_list_tag *) (thd=0x7fdcc7ff6000, event_subtype=<value optimized out>, ap=<value optimized out>)
    at /mysql56/sql/sql_audit.cc:90
#4  0x00000000006841b1 in mysql_audit_notify (thd=0x7fdcc7ff6000, event_class=0, event_subtype=0) at /mysql56/sql/sql_audit.cc:217
#5  0x000000000063e7cb in mysql_audit_general_log (thd=0x7fdcc7ff6000, cmd=0xc76b64 "Connect", cmdlen=7, query_str=<value optimized out>, query_len=<value optimized out>)
    at /mysql56/sql/sql_audit.h:125
#6  0x000000000063ea5a in log_command (thd=<value optimized out>, command=<value optimized out>, format=0xc6d27b "%s@%s on %s") at /mysql56/sql/log.cc:2094
#7  general_log_print (thd=<value optimized out>, command=<value optimized out>, format=0xc6d27b "%s@%s on %s") at /mysql56/sql/log.cc:2122
#8  0x0000000000682030 in acl_authenticate (thd=0x7fdcc7ff6000, com_change_user_pkt_len=<value optimized out>) at /mysql56/sql/sql_acl.cc:11244
#9  0x00000000006a8ad0 in check_connection (thd=0x7fdcc7ff6000) at /mysql56/sql/sql_connect.cc:685
#10 0x00000000006a8d97 in login_connection (thd=0x7fdcc7ff6000) at /mysql56/sql/sql_connect.cc:754
#11 thd_prepare_connection (thd=0x7fdcc7ff6000) at /mysql56/sql/sql_connect.cc:914
#12 0x00000000006a9119 in do_handle_one_connection (thd_arg=<value optimized out>) at /mysql56/sql/sql_connect.cc:983
#13 0x00000000006a91c2 in handle_one_connection (arg=<value optimized out>) at /mysql56/sql/sql_connect.cc:906
#14 0x0000000000939337 in pfs_spawn_thread (arg=0x7fdccb3be840) at /mysql56/storage/perfschema/pfs.cc:1860
#15 0x00007fdd46a249d1 in start_thread () from /lib64/libpthread.so.0
#16 0x00007fdd459a38fd in clone () from /lib64/libc.so.6

登陆如上所示,登陆时在do_handle_one_connection 中循环等待连接,有请求过来时再到准备连接,再到权限认证检查,最在log_command中进入审计接口,准备审计相关动作。

代码语言:javascript
复制
#0  audit_null_notify (thd=0x7fdcc7eb0000, event_class=1, event=0x7fdd46ca0b40) at /mysql56/plugin/audit_null/audit_null.c:99
#1  0x0000000000684402 in plugins_dispatch (thd=0x7fdcc7eb0000, event_subclass=<value optimized out>, ap=<value optimized out>) at /mysql56/sql/sql_audit.cc:455
#2  event_class_dispatch (thd=0x7fdcc7eb0000, event_subclass=<value optimized out>, ap=<value optimized out>) at /mysql56/sql/sql_audit.cc:491
#3  connection_class_handler(THD *, uint, typedef __va_list_tag __va_list_tag *) (thd=0x7fdcc7eb0000, event_subclass=<value optimized out>, ap=<value optimized out>)
    at /mysql56/sql/sql_audit.cc:114
#4  0x00000000006841b1 in mysql_audit_notify (thd=0x7fdcc7eb0000, event_class=1, event_subtype=1) at /mysql56/sql/sql_audit.cc:217
#5  0x000000000057bb53 in close_connection (thd=0x7fdcc7eb0000, sql_errno=0) at /mysql56/sql/mysqld.cc:2634
#6  0x00000000006a90b2 in do_handle_one_connection (thd_arg=<value optimized out>) at /mysql56/sql/sql_connect.cc:996
#7  0x00000000006a91c2 in handle_one_connection (arg=<value optimized out>) at /mysql56/sql/sql_connect.cc:906
#8  0x0000000000939337 in pfs_spawn_thread (arg=0x7fdccb3be7a0) at /mysql56/storage/perfschema/pfs.cc:1860
#9  0x00007fdd46a249d1 in start_thread () from /lib64/libpthread.so.0
#10 0x00007fdd459a38fd in clone () from /lib64/libc.so.6

登出时相对简单,在close_connection中增加了审计动作。

query审计流程 执行前

代码语言:javascript
复制
#0  audit_null_notify (thd=0x7fdcc7ff6000, event_class=0, event=0x7fdd45440da0) at /mysql56/plugin/audit_null/audit_null.c:99
#1  0x0000000000683f22 in plugins_dispatch (thd=0x7fdcc7ff6000, event_subtype=<value optimized out>, ap=<value optimized out>) at /mysql56/sql/sql_audit.cc:455
#2  event_class_dispatch (thd=0x7fdcc7ff6000, event_subtype=<value optimized out>, ap=<value optimized out>) at /mysql56/sql/sql_audit.cc:491
#3  general_class_handler(THD *, uint, typedef __va_list_tag __va_list_tag *) (thd=0x7fdcc7ff6000, event_subtype=<value optimized out>, ap=<value optimized out>)
    at /mysql56/sql/sql_audit.cc:90
#4  0x00000000006841b1 in mysql_audit_notify (thd=0x7fdcc7ff6000, event_class=0, event_subtype=0) at /mysql56/sql/sql_audit.cc:217
#5  0x000000000063e7cb in mysql_audit_general_log (thd=0x7fdcc7ff6000, cmd=0xc76b19 "Query", cmdlen=5, query_str=<value optimized out>, query_len=<value optimized out>)
    at /mysql56/sql/sql_audit.h:125
#6  0x000000000063e93e in log_command (thd=0x7fdcc7ff6000, command=<value optimized out>, query=0x7fdcc201c010 "SELECT DATABASE()", query_length=17) at /mysql56/sql/log.cc:2094
#7  general_log_write (thd=0x7fdcc7ff6000, command=<value optimized out>, query=0x7fdcc201c010 "SELECT DATABASE()", query_length=17) at /mysql56/sql/log.cc:2136
#8  0x00000000006e0b37 in mysql_parse (thd=0x7fdcc7ff6000, rawbuf=<value optimized out>, length=<value optimized out>, parser_state=<value optimized out>)
    at /mysql56/sql/sql_parse.cc:6578
#9  0x00000000006e1e78 in dispatch_command (command=COM_QUERY, thd=0x7fdcc7ff6000, packet=0x7fdcc7ffa001 "SELECT DATABASE()", packet_length=3254894625)
    at /mysql56/sql/sql_parse.cc:1359
#10 0x00000000006a908d in do_handle_one_connection (thd_arg=<value optimized out>) at /mysql56/sql/sql_connect.cc:990
#11 0x00000000006a91c2 in handle_one_connection (arg=<value optimized out>) at /mysql56/sql/sql_connect.cc:906
#12 0x0000000000939337 in pfs_spawn_thread (arg=0x7fdccb3be840) at /mysql56/storage/perfschema/pfs.cc:1860
#13 0x00007fdd46a249d1 in start_thread () from /lib64/libpthread.so.0
#14 0x00007fdd459a38fd in clone () from /lib64/libc.so.6

执行后:

代码语言:javascript
复制
#0  audit_null_notify (thd=0x7fdcc7ff6000, event_class=0, event=0x7fdd45441180) at /mysql56/plugin/audit_null/audit_null.c:99
#1  0x0000000000683f22 in plugins_dispatch (thd=0x7fdcc7ff6000, event_subtype=<value optimized out>, ap=<value optimized out>) at /mysql56/sql/sql_audit.cc:455
#2  event_class_dispatch (thd=0x7fdcc7ff6000, event_subtype=<value optimized out>, ap=<value optimized out>) at /mysql56/sql/sql_audit.cc:491
#3  general_class_handler(THD *, uint, typedef __va_list_tag __va_list_tag *) (thd=0x7fdcc7ff6000, event_subtype=<value optimized out>, ap=<value optimized out>)
    at /mysql56/sql/sql_audit.cc:90
#4  0x00000000006841b1 in mysql_audit_notify (thd=0x7fdcc7ff6000, event_class=0, event_subtype=3) at /mysql56/sql/sql_audit.cc:217
#5  0x00000000006e1543 in mysql_audit_general (command=<value optimized out>, thd=0x7fdcc7ff6000, packet=<value optimized out>, packet_length=1) at /mysql56/sql/sql_audit.h:196
#6  dispatch_command (command=<value optimized out>, thd=0x7fdcc7ff6000, packet=<value optimized out>, packet_length=1) at /mysql56/sql/sql_parse.cc:1793
#7  0x00000000006a908d in do_handle_one_connection (thd_arg=<value optimized out>) at /mysql56/sql/sql_connect.cc:990
#8  0x00000000006a91c2 in handle_one_connection (arg=<value optimized out>) at /mysql56/sql/sql_connect.cc:906
#9  0x0000000000939337 in pfs_spawn_thread (arg=0x7fdccb3be840) at /mysql56/storage/perfschema/pfs.cc:1860
#10 0x00007fdd46a249d1 in start_thread () from /lib64/libpthread.so.0
#11 0x00007fdd459a38fd in clone () from /lib64/libc.so.6

Query动作审计工作流程如上图,需要留意的是在语句执行前和执行后都有审计,通过上面的宏MYSQL_AUDIT_GENERAL_LOG和MYSQL_AUDIT_GENERAL_RESULT告诉Audit是执行前后进入的审计模块,基于此可以做一些更细分的功能。当执行结果有错时,通过MYSQL_AUDIT_GENERAL_ERROR来告知审计模块。

实例流程演示: 文字描述抽象,下面以一个select 语句实例演示下审计流程。 执行语句: select from t2; 当语法解析重写完成后,*在execute执行前,会在LOGGER::log_command()中进入审计流程,代码中增加了处理审计逻辑代码:

代码语言:javascript
复制
mysql_audit_general_log(thd, command_name[(uint) command].str,
                          command_name[(uint) command].length,
                           query_str, query_length);

不论审计插件有没有安装都会进入这个函数,进入这个函数第一件事就会判断是否有审计插件,没有安装审计会直接跳过所有审计逻辑,这个函数就是上面第3点介绍的获取有用值两个内联函数之一 : mysql_audit_general_log

代码语言:javascript
复制
static inline
void mysql_audit_general_log(THD *thd, const char *cmd, uint cmdlen,
                             const char *query_str, size_t query_len)
{
if (mysql_global_audit_mask[0] & MYSQL_AUDIT_GENERAL_CLASSMASK)     //没装插件则跳过
  {
    //取得有用的各种值
    .....
    ....
    ....
      mysql_audit_notify(thd, MYSQL_AUDIT_GENERAL_CLASS, MYSQL_AUDIT_GENERAL_LOG,
                       error_code, time, user, userlen, cmd, cmdlen, query.str,
                       query.length, clientcs, rows, sql_command, host,
                       external_user, ip);  //把有用的值往下传
  }
}

在mysql_audit_notify会判断下是连接语句还是通用语句,然后调用对应的函数,如本例中会调通用语句处理接口general_class_handler

代码语言:javascript
复制
static void general_class_handler(THD *thd, uint event_subtype, void *tb, va_list ap)
{
  mysql_event_general event;
    ....
  event.general_query= va_arg(ap, const char *);
  event.general_query_length= va_arg(ap, unsigned int);
  event.general_charset= va_arg(ap, struct charset_info_st *);
  event.general_rows= (unsigned long long) va_arg(ap, ha_rows);
  event.general_host= va_arg(ap, MYSQL_LEX_STRING);
  event_class_dispatch(thd, MYSQL_AUDIT_GENERAL_CLASS, &event);
}

在general_class_handler函数之后,语句的信息就已经有了,保存在event结构中,上面语句在gdb中 实际打印的结果如下:

代码语言:javascript
复制
(gdb) p (mysql_event_general )event
$2 = {event_subclass = 0, general_error_code = 0, general_thread_id = 1, general_user = 0x7fd27aa51050 “root[root] @ localhost [127.0.0.1]”,
  general_user_length = 34, general_command = 0xc76b19 “Query”, general_command_length = 5,
  general_query = 0x7fd1f5c1a010 “select from t2”, general_query_length = 15, general_charset = 0x12e27e0, general_time = 1505712354,
  general_rows = 0, general_host = {str = 0xbe4d2f “localhost”, length = 9}, general_sql_command = {str = 0xd29b04 “select”, length = 6},
  general_external_user = {str = 0xc70579 “”, length = 0}, general_ip = {str = 0x7fd1f5c12040 “127.0.0.1”, length = 9}}

可以非常清楚的看到语句内容,时间,类型等信息。 当 *execute执行后,会在 dispatch_command () 函数尾部会调用审计接口:

代码语言:javascript
复制
   if (!thd->is_error() && !thd->killed_errno())
     mysql_audit_general(thd, MYSQL_AUDIT_GENERAL_RESULT, 0, 0);

  mysql_audit_general(thd, MYSQL_AUDIT_GENERAL_STATUS,
                      thd->get_stmt_da()->is_error() ?
                      thd->get_stmt_da()->sql_errno() : 0,
                      command_name[command].str);

这里调用的是 mysql_audit_general,也是上面第3点介绍的获取有用值另一个内联函数,功能和mysql_audit_general_log相同,带log的为执行前调,不带log的为执行后调,区别在于记录的值略有差异,如执行前的值里没错误状态,执行后的值是有的,成功为0,失败为对应的错误代码。在mysql_audit_general之后流程和上面mysql_audit_general_log一样,不再介绍。 这两个内联函数处理的是Query语句,另外有三个宏MYSQL_AUDIT_NOTIFY_CONNECTION_CONNECT、MYSQL_AUDIT_NOTIFY_CONNECTION_DISCONNECT、MYSQL_AUDIT_NOTIFY_CONNECTION_CHANGE_USER是处理登陆、登出、换用户时用,功能和前两个函数大同小异,不再赘述。

审计进一步思考

审计是记录历史动作,但有些情况下,光历史记录远远不够。对于应用系统,很多语句都是都是绑定参数运行的,直观审计到的就是一条条带问号的语句,不能看到实际动作,若要还原真实语句,需要联系上下语句分析,非常不便,这就要求审计有一定的语句还原拼接功能,把参数和内容放一起展示。更进一步,假如有人非常了解审计系统,知道审计记录不会永久存放,在某时刻建一个带有破坏性的存储过程,等超期不再保留建立过存储程记录后,执行并删除,真实运行动作将无法通过审计得知,对这类操作,就有了反向追踪运行内容语句的需求,尤其在金融行业中。

另一方面,审计用户也应该是个特权用户,和超级用户互相制约。审计用户应该独立出来,有超级用户不能修改的帐号密码,专门用于审计相关操作,如开关审计,设置审计策略,查阅审计结果,超级用户不能干涉这些动作,保证审计记录的真实性和完整性。审计用户账号应该掌握在客户最核心人手中,以对超级用户活动形成制衡,更加保证数据的安全。

再深入一层,有客户需求可能希望不同用户看到的内容不一样,对敏感数据根据不同用户进行自动过滤,严格来说这已经不再属于审计范围了,属于数据安全问题,需要有更严密的处理逻辑来实现。对于数据库产品来说,基于BLP模型的强制访问控制(MAC)是实现该需求的方法之一,该模型关键在于权限标签,对主客体进行标识,每个主体客体都有自己的标签,权限高的可访问修改低的对象,低权限的不能看到高权限的内容,对每个表、列甚至行都打上标签,对内容过滤可以做到列级直至行级。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-11-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 腾讯数据库技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是数据库审计
  • 常见的审计方式
  • oracle审计简介
  • mysql审计插件
  • mysql审计接口详细分析
  • 审计进一步思考
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档