ITPub博客

首页 > 数据库 > 数据库开发技术 > 一文搞懂MySQL开源审计功能

一文搞懂MySQL开源审计功能

原创 数据库开发技术 作者:小安 时间:2021-10-09 20:44:58 0 删除 编辑


首先,为什么需要数据库审计?


因为数据是一个企业的核心资产,更是企业的命脉所在,而数据库审计是数据库安全技术之一。

说白了,没了数据,企业危矣;有了数据,企业活矣;数据有了审计,企业长久矣。(瞎编)


其次,以企业安全和等保测评这两方面体现审计的重要性。


1. 企业安全

企业的发展壮大和可持续发展离不开审计的保驾护航。


2. 等保测评

金融及政府等有严格法律法规要求的行业。数据安全审计能够按照标准要求提供完全对应条例的审计信息,确保网络合规性。

再次,本文主要以MySQL数据库作为分析对象,那MySQL有哪些审计工具呢?

详见图文,已经简要说明工具的来源、类型、基本原理等信息。


由于环境和经费问题,笔者主要选择三个适用性比较好的工具进行演示,分别是init-connect+binlog、McAfee插件和MariaDB插件,通过三者比较以下事件类型能否被记录作为审计的功能点评估。



本文大纲

1.  测试案例

2.  init-connect + binlog

3.  McAfee 插件

4.  MariaDB 插件


01

测试案例


各工具使用测试案例基本不变,除了init-connect比较特别,因为不能审计root用户或其他超级用户。
### 1. 创建数据库
create database test_aud;
use test_aud;

### 2. 创建用户
create user 'xixi'@'%' identified by "123456";
create user 'haha'@'%' identified by "123456";

### 3. 授予权限
GRANT ALL PRIVILEGES ON test_aud.* TO 'xixi'@'%';
grant select,insert,update,delete on test_aud.* to 'haha'@'%';
revoke select,insert,update,delete on test_aud.* from 'haha'@'%';

### init-connect使用xixi用户进行后续操作。
### 4. 创建测试表
CREATE TABLE `t_audit` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `item_name` varchar(30) NOT NULL COMMENT '商品名称',
  `price` int(11) NOT NULL COMMENT '价格',
  `comment` varchar(30) NOT NULL COMMENT '评价',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

### 5. DML操作
insert into t_audit values (1,'Apple',300,'非常棒');
insert into t_audit values (2,'Banana',400,'好吃');
insert into t_audit values (3,'Orange',500,'不错');

show table status like '%t_audit%';
select * from t_audit;
update t_audit set comment='质量好' where id =2 ;
select * from t_audit;
delete from t_audit where id = 3;

### 6. Alter操作
ALTER TABLE `test_aud`.`t_audit` MODIFY COLUMN `comment` varchar(50) CHARACTER SET utf8mb4  NOT NULL COMMENT '评价' AFTER `price`;

ALTER TABLE `test_aud`.`t_audit` ADD COLUMN `user` varchar(30) NOT NULL COMMENT '用户' AFTER `comment`;

desc `test_aud`.`t_audit`;
show create table `test_aud`.`t_audit`;

### 7. 还原环境
truncate table t_audit;
drop table t_audit;
drop database test_aud;

drop user 'xixi'@'%';
drop user 'haha'@'%';


理论上,测试案例的每一行SQL都应该被记录,少一行都意味着审计功能的缺陷。接下来要开始测试了,过程还是挺花时间的。


02

init-connect + binlog

1. 介绍链接

https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_init_connect

官网说明:为什么init-connect不能审计超级用户呢?

对于具有SUPER权限的用户,不会执行init_connect的内容。这样做是为了让init_connect的错误不会阻止所有客户端连接。

例如,该值可能包含有语法错误的语句,从而导致客户端连接失败。对于超级特用户,不执行init_connect,可以使他们打开连接并修复init_connect值。

设计MySQL的哥哥姐姐果然是智慧的!


2. 创建存放连接信息的审计表
create database test_audlog;
use test_audlog;
create table test_audlog.access_log ( id int(11) primary key auto_increment, Conn_id int, ConnUserName varchar(50), PrivMatchName varchar(50), LoginTime timestamp);


root@localhost:mysql.sock [test_audlog]>desc test_audlog.access_log;
+---------------+-------------+------+-----+---------+----------------+
| Field         | Type       | Null | Key | Default | Extra         |
+---------------+-------------+------+-----+---------+----------------+
| id           | int(11)     | NO   | PRI | NULL   | auto_increment |
| Conn_id       | int(11)     | YES |     | NULL   |               |
| ConnUserName | varchar(32) | YES |     | NULL   |               |
| PrivMatchName | varchar(32) | YES |     | NULL   |               |
| LoginTime     | timestamp   | YES |     | NULL   |               |
+---------------+-------------+------+-----+---------+----------------+


3. 配置权限

保证所有的用户对此表有insert权限

insert into mysql.db(host,db,user,Insert_priv) values('%','test_audlog','','Y'); 
flush privileges;


或者,通过命令查询用户需要授予的权限。

mysql> select concat("grant insert on test_audlog.access_log to '",user,"'@'",host,"';") from mysql.user;
grant insert on test_audlog.access_log to 'haha'@'%';
grant insert on test_audlog.access_log to 'xixi'@'%';


4. 配置init-connect

binlog必须配置。

### 配置文件添加以下配置
init-connect='insert into test_audlog.access_log (Conn_id,ConnUserName,PrivMatchName,LoginTime) values (connection_id(),user(),current_user(),now());'

log_bin=/mysql/log/3306/binlog/mysql-bin
log_bin_index=/mysql/log/3306/binlog/mysql-bin.index


### 重启MySQL数据库
service mysql restart


5. 测试结果

审计表信息。

root@localhost:mysql.sock [test_aud]>select * from test_audlog.access_log;
+----+---------+----------------------+---------------+---------------------+
| id | Conn_id | ConnUserName         | PrivMatchName | LoginTime           |
+----+---------+----------------------+---------------+---------------------+
|  4 |      11 | xixi@localhost       | xixi@%        | 2021-10-03 22:05:17 |
|  5 |      12 | haha@localhost       | haha@%        | 2021-10-03 22:05:27 |
|  6 |      13 | xixi@localhost       | xixi@%        | 2021-10-03 22:05:47 |
|  7 |      22 | xixi@192.168.117.133 | xixi@%        | 2021-10-03 22:41:17 |
+----+---------+----------------------+---------------+---------------------+


binlog的日志信息。

mysqlbinlog --start-datetime='2021-10-03 22:00:00' --stop-datetime='2021-10-03 22:08:00' /mysql/log/3306/binlog/mysql-bin.000008 |grep -Ei 'create|alter|truncate|drop|show|select|insert|update|delete|grant|revoke' -B 2




6. 小结

init-connect + binlog从审计的类型来看,基本上该有的都有。

不足之处有以下几点:

  1. 无法将连接信息与binlog的记录一一对应,需要手工关联。

  2. 无法审计超级用户。不排除有些应用使用root用户或者超级用户,针对此点,云平台数据库不开放root用户是明智的选择。

  3. 挖掘少量日志可行,但是海量信息就够呛了。而且挖掘出来的信息也需要进行存储,既然如此,为何不一开始就选择能够额外存放的插件呢?

  4. 审计表的连接信息可以被有权限的用户进行篡改,若清空审计表后,仅靠binlog日志无法承担审计的角色。

  5. binlog日志没有查询记录,哪些敏感信息被读取无从考察。


03

McAfee 插件

1. 下载插件

https://github.com/mcafee/mysql-audit


2. 解压文件
[root@MYS-DB01 Package]# ls
audit-plugin-mysql-5.7-1.1.9-974-linux-x86_64.zip
[root@MYS-DB01 Package]# unzip audit-plugin-mysql-5.7-1.1.9-974-linux-x86_64.zip


3. 拷贝插件
[root@MYS-DB01 lib]# cp libaudit_plugin.so /usr/local/mysql/lib/plugin/
[root@MYS-DB01 plugin]# chmod 755 libaudit_plugin.so
[root@MYS-DB01 ~]# chown -R mysql:mysql /mysql/log/3308/audit
[root@MYS-DB01 ~]# chmod -R 755 /mysql/log/3308/audit

4. 安装插件

mysql> INSTALL PLUGIN AUDIT SONAME 'libaudit_plugin.so';

5. 查看插件版本
mysql> show global status like 'AUDIT_version';
+---------------+-----------+
| Variable_name | Value     |
+---------------+-----------+
| Audit_version | 1.1.9-974 |
+---------------+-----------+

6. 查看插件信息
mysql> select * from information_schema.plugins where plugin_name='AUDIT'\G
*************************** 1. row ***************************
          PLUGIN_NAME: AUDIT
      PLUGIN_VERSION: 1.0
        PLUGIN_STATUS: ACTIVE
          PLUGIN_TYPE: AUDIT
  PLUGIN_TYPE_VERSION: 4.1
      PLUGIN_LIBRARY: libaudit_plugin.so
PLUGIN_LIBRARY_VERSION: 1.6
        PLUGIN_AUTHOR: McAfee Inc
  PLUGIN_DESCRIPTION: AUDIT plugin, creates a file mysql-audit.log to log activity
      PLUGIN_LICENSE: GPL
          LOAD_OPTION: ON

7. 参数设置

先通过动态加载插件的方式,再在配置文件添加数据库能够识别的参数。

### 1. McAfee 插件
plugin-load=AUDIT=libaudit_plugin.so

### McAfee 参数配置
audit_json_file=on
audit_json_log_file=/mysql/log/3308/audit/mysql-audit.json
audit_record_cmds='create,drop,alter,truncate,grant,insert,delete,update,show,select,connect,quit'


8. 检查DB参数

以Json的形式记录文件。

root@localhost:mysql.sock [(none)]>show variables like 'audit_json%';
+---------------------------------+-----------------------------------------------------+
| Variable_name                   | Value                                               |
+---------------------------------+-----------------------------------------------------+
| audit_json_file                 | ON                                                 |
| audit_json_file_bufsize         | 1                                                   |
| audit_json_file_flush           | OFF                                                 |
| audit_json_file_retry           | 60                                                 |
| audit_json_file_sync           | 0                                                   |
| audit_json_log_file             | /mysql/log/3308/audit/mysql-audit.json             |
| audit_json_socket               | OFF                                                 |
| audit_json_socket_name         | /var/run/db-audit/mysql.audit__mysql_data_3308_3308 |
| audit_json_socket_retry         | 10                                                 |
| audit_json_socket_write_timeout | 1000                                               |
+---------------------------------+-----------------------------------------------------+


9. 审计类型
root@localhost:mysql.sock [(none)]>show variables like 'audit_re%';
+-------------------+----------------------------------------------------------------------------------+
| Variable_name     | Value                                                                            |
+-------------------+----------------------------------------------------------------------------------+
| audit_record_cmds | connect,create,alter,truncate,drop,select,show,insert,update,delete,grant,revoke |
| audit_record_objs |                                                                                  |
+-------------------+----------------------------------------------------------------------------------+


10. 审计用户

这个是白名单,以逗号隔开用户名写入配置,该用户就不会被审计。

root@localhost:mysql.sock [(none)]>show variables like '%audit_whitelist_users%';
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| audit_whitelist_users |       |
+-----------------------+-------+


11. 卸载插件

在 my.cnf 中 [mysqld] 下添加 audit_uninstall_plugin=1,重启mysql。执行两次 "uninstall plugin audit" 即可卸载。

mysql> uninstall plugin audit;
ERROR 1620 (HY000): Uninstall AUDIT plugin must be called again to complete
mysql> uninstall plugin audit;
Query OK, 0 rows affected, 1 warning (0.01 sec)


12. 测试结果

没有密集恐惧症的亲可以点开看看。


13. 小结
  1. 信息量大,即日志体积相对来说会比较大,需要更多的存储空间。

  2. 记录了一些无关要紧的信息,而且缺少了一些重要的信息,比如,create、drop、alter操作等等。表若被drop了,也不知道是谁干的,这能忍?


04

MariaDB 插件

1. 下载插件

链接1:https://mirrors.tuna.tsinghua.edu.cn/mariadb/

链接2:https://mariadb.com/kb/en/mariadb-server-10-5-12/

参数说明:https://mariadb.com/kb/en/mariadb-audit-plugin-options-and-system-variables


2. 解压文件
[root@MYS-DB01 MySQL]# tar -zxvf mariadb-10.5.12-linux-x86_64.tar.gz

3. 拷贝插件
[root@MYS-DB01 plugin]# cp server_audit.so /mysql/software/mysql-5.7.30/lib/plugin/


4. 安装插件
root@localhost:mysql.sock [(none)]>install plugin server_audit soname 'server_audit.so';

5. 查看插件版本

跟随MariaDB数据库版本信息,查看审计类型。


6. 查看插件信息
root@localhost:mysql.sock [(none)]>select * from information_schema.plugins where plugin_name='SERVER_AUDIT'\G
*************************** 1. row ***************************
          PLUGIN_NAME: SERVER_AUDIT
      PLUGIN_VERSION: 1.4
        PLUGIN_STATUS: ACTIVE
          PLUGIN_TYPE: AUDIT
  PLUGIN_TYPE_VERSION: 4.1
      PLUGIN_LIBRARY: server_audit.so
PLUGIN_LIBRARY_VERSION: 1.4
        PLUGIN_AUTHOR: Alexey Botchkov (MariaDB Corporation)
  PLUGIN_DESCRIPTION: Audit the server activity
      PLUGIN_LICENSE: GPL
          LOAD_OPTION: ON

7. 参数配置

先通过动态加载插件的方式,再在配置文件添加数据库能够识别的参数。参数相关介绍见注释。笔者开启了轮询,每个审计日志大小1GB,防止单个文件无限扩展。

server_audit_logging                                       = ON                             # 开启日志记录,默认是关闭
server_audit                                               = FORCE_PLUS_PERMANENT           # 防止插件被卸载
server_audit_file_rotate_now                               = ON                             # 是否强制切割审计日志
server_audit_file_rotate_size                              = 1G                             # 定义切割审计日志的文件大小1073741824=1GB
server_audit_file_rotations                                = 999                            # 定义审计日志的轮询个数,0=不轮询,MAX=999
server_audit_events                                        = CONNECT,QUERY,QUERY_DDL,QUERY_DML,QUERY_DCL # 参考官网配置
server_audit_file_path                                     = /mysql/log/3308/audit/server_audit.log      # 审计日志路径
#server_audit_incl_users                                   = root                           # 只审计某个用户

8. 检查DB参数

server_audit_logging=ON才能开启审计,仅靠安装插件是不能开启审计的。

root@localhost:mysql.sock [(none)]>show variables like 'server_audit%';
+-------------------------------+---------------------------------------------+
| Variable_name                 | Value                                       |
+-------------------------------+---------------------------------------------+
| server_audit_events           | CONNECT,QUERY,QUERY_DDL,QUERY_DML,QUERY_DCL |
| server_audit_excl_users       |                                             |
| server_audit_file_path       | /mysql/log/3308/audit/server_audit.log     |
| server_audit_file_rotate_now | ON                                         |
| server_audit_file_rotate_size | 1073741824                                 |
| server_audit_file_rotations   | 999                                         |
| server_audit_incl_users       |                                             |
| server_audit_loc_info         |                                             |
| server_audit_logging         | ON                                         |
| server_audit_mode             | 1                                           |
| server_audit_output_type     | file                                       |
| server_audit_query_log_limit | 1024                                       |
| server_audit_syslog_facility | LOG_USER                                   |
| server_audit_syslog_ident     | mysql-server_auditing                       |
| server_audit_syslog_info     |                                             |
| server_audit_syslog_priority | LOG_INFO                                   |
+-------------------------------+---------------------------------------------+
16 rows in set (0.00 sec)


9. 审计类型


参考MariaDB官网信息,什么版本可以开启哪些对应的审计事件。



通过MariaDB版本了解插件可以开启的审计事件类型。

root@localhost:mysql.sock [(none)]>show variables like 'server_audit_events';
+---------------------+---------------------------------------------+
| Variable_name       | Value                                       |
+---------------------+---------------------------------------------+
| server_audit_events | CONNECT,QUERY,QUERY_DDL,QUERY_DML,QUERY_DCL |
+---------------------+---------------------------------------------+


10. 审计用户

把需要审计的用户以逗号的形式隔开写入配置。这里与McAfee是相反的。

root@localhost:mysql.sock [(none)]>show variables like 'server_audit_incl_users';
+-------------------------+-------+
| Variable_name           | Value |
+-------------------------+-------+
| server_audit_incl_users |       |
+-------------------------+-------+


11. 卸载插件

在数据库层面执行server_audit,并且删除配置文件相关信息。

mysql> UNINSTALL PLUGIN server_audit;


12. 测试结果

信息量不是很多,比较直观。


13. 小结
  1. 审计的操作类型较为全面,简洁明了。

  2. 若硬要鸡蛋里挑骨头,那就得看看性能方面。


06

总结

综上对比,MariaDB的审计功能比较全面,无论是登入登出,还是DML、DDL、DCL都能够记录。

本文还有些地方还可以继续完善,这里就交给有兴趣的同学了,比如,调度存储过程、触发器等。

从功能方面比较,笔者更加倾向于MariaDB插件。但除了功能外,还要考虑性能方面!


那么下文将分享有关审计的性能测试,主要根据等保要求进行,其中涉及sysbench、Python制图等。有兴趣的同学们,可以关注下喔!



此外,由于笔者的技术水平有限,本文的总结和测试结果难免考虑不周,如有侵权或者不妥之处,请联系,谢谢!


参考资料

阿里云 | 企业上云等保三级合规

腾讯云 | 腾讯云数据安全审计(Data Security Audit,DSAudit)

葫芦娃集团 | 为什么一定要做数据库审计

书籍 |《MySQL DBA工作笔记》

其他 | 见本文链接




 · Python系列 | 推荐 ·



如何使用Python对MySQL的误操作快速恢复数据?

Python入门必备第4课:字符串、序列

Python入门必备第3课:列表元组,看这一篇够了

Python入门必备第2课:分支与循环,助你无限可能

Python入门必备第1课:基础知识,3分钟搞懂




 · 自动化运维系列 | 推荐 ·


自动化运维实战五  | 【演示】3分钟一键部署Mysql数据库

自动化运维实战四  | 【实现】Mysql一键部署的前后端交互

自动化运维实战三  | 【规划】Mysql一键部署的数据模型

自动化运维实战二  | 【构思】Mysql一键部署的界面

自动化运维实战一  | 【模板】 套用精美模板演示登陆界面



喜欢就点个  在看  呀!

原文作者:Python自动化运维;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2018-10-07

  • 博文量
    47
  • 访问量
    17922