做者:王少鹏
爱可生 DBA 团队成员,负责项目数据库平常问题处理及公司 DMP 平台问题处理,对数据库有强烈的兴趣。认为不会游泳的厨师毫不是一个好数据库工程师。
本文来源:原创投稿
*爱可生开源社区出品,原创内容未经受权不得随意使用,转载请联系小编并注明来源。mysql
某日某公司的测试数据库突发告警!sql
故障初步定位极可能是新来的几位实习生没有遵照运维规范,误操做(没加 where 条件)删表致使服务异常,目前还没确认操做用户身份。数据库
DELETE TABLE XXXXX;( 环境 autocommit=1 ,没有手动开启事务 )
尽管测试环境不影响线上应用,但影响了新功能开发进度,暴露出运维管理上的漏洞。app
经过以上案例思考,MySQL 自己并无操做审计的功能,又如何根据现有的功能进行行为分析,避免悲剧再次发生?运维
文章整理了运维时经常使用的定位 MySQL 操做用户方法,帮你快速查看用户行为记录。测试
init_connect 参数的功能:当用户在客户端链接 MySQL 时,隐式执行的一条自定义的 SQL 语句(参数值)。线程
注意:3d
mysql> show variables like 'init_connect'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | init_connect | | +---------------+-------+ 1 row in set (0.00 sec) mysql> set global init_connect='insert into auditdb.accesslog(connectionID,ConnUser,MatchUser,LoginTime) values(connection_id(),user(),current_user(),now());'; Query OK, 0 rows affected (0.00 sec) mysql> show variables like 'init_connect'; +---------------+-------------------------------------------------------------------------------------------------------------------------------+ | Variable_name | Value | +---------------+-------------------------------------------------------------------------------------------------------------------------------+ | init_connect | insert into auditd.accesslog(connectionID,ConnUser,MatchUser,LoginTime) values(connection_id(),user(),current_user(),now()); | +---------------+-------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)
既然是要 insert 一条数据,那是否是这个普通用户要对这张表拥有 insert 权限呢?日志
答案是确定的。code
mysql> create database auditdb charset utf8mb4; Query OK, 1 row affected (0.01 sec) mysql> create table auditdb.accesslog (id int (10) unsigned not null primary key auto_increment, Connectionid int(10) unsigned,ConnUser varchar (30) not null default '', MatchUser varchar (30) not null default '', Logintime datetime); Query OK, 0 rows affected (0.02 sec)
对全部用户都赋予 insert 权限
mysql> grant insert on auditdb.accesslog to mindoc@'%'; Query OK, 0 rows affected (0.00 sec)
注意:
此方法须要给数据库全部用户都对 auditdb.accesslog 授写权限,不然插入用户信息会失败;
不要受权 update 、delete 等权限,不然普通用户登陆 MySQL 能够手动删除他链接的信息。
[root@db ~]# mysql -u mindoc -p -h 172.18.1.76 Enter password: mysql> create table temp(id int,name varchar(32)); Query OK, 0 rows affected (0.03 sec) mysql> insert into temp values(1,'aa'); Query OK, 1 row affected (0.01 sec) mysql> insert into temp values(2,'aa'); Query OK, 1 row affected (0.01 sec) mysql> insert into temp values(3,'aa'); Query OK, 1 row affected (0.01 sec) mysql> delete from temp; Query OK, 3 rows affected (0.01 sec)
此时数据已经被删除了,你的应用程序应该会报错或开始告警。经过检查应用日志,可大体推断时间范围。
[root@db ~]# mysqlbinlog -v --base64-output=decode-rows /usr/local/mysql-5.7.20/binlog/mysql-bin.000002 > audit.log
查看危险语句的进程 ID 号( 在解析后的 binlog 文件搜索危险命令关键字 )
经过执行的 delete 语句与大概执行时间,肯定是哪一个用户链接( thread_id=130 )
[root@db ~]# tail -35 audit.log # at 49003 #191120 13:02:18 server id 76 end_log_pos 49080 CRC32 0x73dc1dda Query thread_id=130 exec_time=0 error_code=0 SET TIMESTAMP=1574226138/*!*/; BEGIN /*!*/; # at 49080 #191120 13:02:18 server id 76 end_log_pos 49135 CRC32 0x360e7fe4 Table_map: `mindoc_db`.`temp` mapped to number 249 # at 49135 #191120 13:02:18 server id 76 end_log_pos 49194 CRC32 0xbbf0d78f Delete_rows: table id 249 flags: STMT_END_F BINLOG ' 2sjUXRNMAAAANwAAAO+/AAAAAPkAAAAAAAEACW1pbmRvY19kYgAEdGVtcAACAw8CgAAD5H8ONg== 2sjUXSBMAAAAOwAAACrAAAAAAPkAAAAAAAEAAgAC//wBAAAAAmFh/AIAAAACYWH8AwAAAAJhYY/X 8Ls= '/*!*/; ### DELETE FROM `mindoc_db`.`temp` ### WHERE ### @1=1 ### @2='aa' ### DELETE FROM `mindoc_db`.`temp` ### WHERE ### @1=2 ### @2='aa' ### DELETE FROM `mindoc_db`.`temp` ### WHERE ### @1=3 ### @2='aa' # at 49194 #191120 13:02:18 server id 76 end_log_pos 49225 CRC32 0x277ece0b Xid = 23721 COMMIT/*!*/; SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/; DELIMITER ; # End of log file /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
能够看到线程 threadid=130,而且时间也是 2019-11-20 中午一点左右。能够肯定就是 mindoc@’%’ 用户操做的 delete 语句。
经过 ConnUser 字段能够看到是 172.18.1.99 这个地址使用 mindoc@’%’ 用户链接的 MySQL 数据库。
mysql> select * from auditdb.accesslog where Connectionid=130; +----+--------------+--------------------+-----------+---------------------+ | id | Connectionid | ConnUser | MatchUser | Logintime | +----+--------------+--------------------+-----------+---------------------+ | 1 | 130 | mindoc@172.18.1.99 | mindoc@% | 2019-11-20 12:59:21 | +----+--------------+--------------------+-----------+---------------------+ 1 row in set (0.00 sec)
而后你就能够去找谁使用的 mindoc@% 用户了,还有定位下 172.18.1.99 这个 IP 地址谁在使用。
完成了经过行为定位用户的操做。