审计 MySQL 数据库上的登录

sta*_*ppo 12 mysql authentication audit

有没有办法审核 MySQL 的登录?我希望能够为每个员工创建一个用户名,从而创建登录的审计跟踪。然而,谷歌搜索没有出现好的结果。

我们可以审计的越多越好。至少,知道谁何时登录会很好。最好看看谁在什么时候执行了什么查询。日志主要是为了告诉客户我们有它们,因为数据库中有潜在的敏感信息。

显然,能够审计每个用户(以及何时)执行的查询也将使我们能够更好地查明安全问题的原因,如果出现安全问题。

Gai*_*ius 6

您可能希望使用一般查询日志

一般查询日志是对mysqld正在做什么的一般记录。当客户端连接或断开连接时,服务器将信息写入此日志,并记录从客户端收到的每个 SQL 语句。

安全日志记录的一件重要事情是攻击者无法访问日志以擦除其存在的痕迹,因此请考虑仅附加文件

Oracle 中的 FWIW 我们可以自动将日志发送到远程 syslog,但我不相信 MySQL 有这个功能。也许你可以用 SNMP 伪造它,但我没有尝试过。

  • [在 5.1.20 中添加了通过 syslog 进行日志记录](http://dev.mysql.com/doc/refman/5.1/en/mysqld-safe.html#option_mysqld_safe_syslog) (4认同)

Rol*_*DBA 6

@Gauis 的回答非常好。要进一步添加,您可以执行以下操作:

MySQL 5.1 现在允许将一般日志和慢查询日志存储为 SQL 表。

将此添加到/etc/my.cnf:

[mysqld]
log-output=TABLE
log
Run Code Online (Sandbox Code Playgroud)

重启mysql

然后,当 mysqld 创建通用日志时,它会在 /var/lib/mysql/mysql 文件夹(mysql 模式数据库)中将表创建为 CSV 表,而不是文本文件。

只需这样做即可查看它:

SHOW CREATE TABLE mysql.general_log\G
Run Code Online (Sandbox Code Playgroud)

所有的连接都会堆积在里面。

对您来说,这在查询时不是很有用。每次都只是全表扫描。

该怎么办 ???将其转换为 MyISAM 并为表格编制索引!!!!

SET @old_log_state = @@global.general_log;
SET GLOBAL general_log = 'OFF';
ALTER TABLE mysql.general_log ENGINE = MyISAM;
ALTER TABLE mysql.general_log ADD INDEX (event_time);
SET GLOBAL general_log = @old_log_state;
Run Code Online (Sandbox Code Playgroud)

或者,您可能希望在参数字段上放置全文索引。

我刚刚在服务器上设置了 MySQL 5.5.9 并进行了尝试。结果如下:

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.5.9-log MySQL Community Server (GPL)

Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

iml-db10:3306 (DB (none)) :: show create table mysql.general_log\G
*************************** 1. row ***************************
       Table: general_log
Create Table: CREATE TABLE `general_log` (
  `event_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `user_host` mediumtext NOT NULL,
  `thread_id` int(11) NOT NULL,
  `server_id` int(10) unsigned NOT NULL,
  `command_type` varchar(64) NOT NULL,
  `argument` mediumtext NOT NULL
) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='General log'
1 row in set (0.01 sec)

iml-db10:3306 (DB (none)) :: SET @old_log_state = @@global.general_log;
Query OK, 0 rows affected (0.00 sec)

iml-db10:3306 (DB (none)) :: SET GLOBAL general_log = 'OFF';
Query OK, 0 rows affected (0.00 sec)

iml-db10:3306 (DB (none)) :: ALTER TABLE mysql.general_log ENGINE = MyISAM;
Query OK, 9 rows affected (0.02 sec)
Records: 9  Duplicates: 0  Warnings: 0

iml-db10:3306 (DB (none)) :: ALTER TABLE mysql.general_log ADD INDEX (event_time);
Query OK, 9 rows affected (0.00 sec)
Records: 9  Duplicates: 0  Warnings: 0

iml-db10:3306 (DB (none)) :: SET GLOBAL slow_query_log = @old_log_state;
Query OK, 0 rows affected (0.00 sec)

iml-db10:3306 (DB (none)) :: select * from mysql.general_log;
+---------------------+-----------------------------+-----------+-----------+--------------+-------------------------------------------+
| event_time          | user_host                   | thread_id | server_id | command_type | argument                                  |
+---------------------+-----------------------------+-----------+-----------+--------------+-------------------------------------------+
| 2011-02-24 14:42:18 | [lwdba] @  [127.0.0.1]      |         3 | 106451130 | Connect      | lwdba@127.0.0.1 on                        |
| 2011-02-24 14:42:18 | lwdba[lwdba] @  [127.0.0.1] |         3 | 106451130 | Query        | select @@version_comment limit 1          |
| 2011-02-24 14:42:18 | lwdba[lwdba] @  [127.0.0.1] |         3 | 106451130 | Query        | SHOW VARIABLES LIKE 'hostname'            |
| 2011-02-24 14:42:18 | lwdba[lwdba] @  [127.0.0.1] |         3 | 106451130 | Quit         |                                           |
| 2011-02-24 14:42:18 | [lwdba] @  [127.0.0.1]      |         4 | 106451130 | Connect      | lwdba@127.0.0.1 on                        |
| 2011-02-24 14:42:18 | lwdba[lwdba] @  [127.0.0.1] |         4 | 106451130 | Query        | select @@version_comment limit 1          |
| 2011-02-24 14:42:30 | lwdba[lwdba] @  [127.0.0.1] |         4 | 106451130 | Query        | show create table mysql.general_log       |
| 2011-02-24 14:43:54 | lwdba[lwdba] @  [127.0.0.1] |         4 | 106451130 | Query        | SET @old_log_state = @@global.general_log |
| 2011-02-24 14:44:00 | lwdba[lwdba] @  [127.0.0.1] |         4 | 106451130 | Query        | SET GLOBAL general_log = 'OFF'            |
+---------------------+-----------------------------+-----------+-----------+--------------+-------------------------------------------+
9 rows in set (0.00 sec)

iml-db10:3306 (DB (none)) :: show create table mysql.general_log\G
*************************** 1. row ***************************
       Table: general_log
Create Table: CREATE TABLE `general_log` (
  `event_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `user_host` mediumtext NOT NULL,
  `thread_id` int(11) NOT NULL,
  `server_id` int(10) unsigned NOT NULL,
  `command_type` varchar(64) NOT NULL,
  `argument` mediumtext NOT NULL,
  KEY `event_time` (`event_time`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='General log'
1 row in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

现在,您可以按时间戳查询并在参数字段中查找特定标记。

例如,请注意我所做的 SELECT 的第 4 行。我的登录在参数字段中记录为lwdba@127.0.0.1 on. 您可以跟踪这些。

如果将军变得太大怎么办(相信我它会变得太大很快)

该怎么办 ???

  1. 关闭mysql
  2. 将general_log.frm、general_log.MYD 和general_log.MYI 移动到不同的(希望更大的)磁盘安装。
  3. 从 /var/lib/mysql/mysql 创建指向 general_log.frm、general_log.MYD 和 general_log.MYI 的三个符号链接
  4. chown mysql:mysql general_log.frm general_log.MYD general_log.MYI 新盘挂载
  5. chown mysql:mysql general_log.frm general_log.MYD general_log.MYI 符号链接在/var/lib/mysql/mysql
  6. 启动mysql备份

顺便说一句,一旦您将一般日志脱机,您就可以运行这些日志来收集在 mysqld 中执行某些操作的不同登录名:

SET SQL_LOG_BIN=0;
use mysql
DROP TABLE IF EXISTS audit_user_host;
CREATE TABLE audit_user_host
(
    user_host VARCHAR(32),
    PRIMARY KEY (user_host)
) ENGINE=MyISAM;
SHOW CREATE TABLE audit_user_host\G
INSERT IGNORE INTO mysql.audit_user_host SELECT user_host FROM mysql.general_log;
SELECT COUNT(1) FROM mysql.audit_user_host;
Run Code Online (Sandbox Code Playgroud)

我有一个带有 3 个数据库服务器的客户端。每个带有 DB Server 的行都包含超过 1,000,000,000(10 亿 [千百万])行。完成上述脚本大约需要 2.5 小时。audit_user_host 表最终有 27 个不同的登录名。

你应该很高兴去。

祝大家玩得开心!!!