web-dev-qa-db-ja.com

MySQLデータベースのログインを監査する

MySQLへのログインを監査する方法はありますか?各従業員のユーザー名を作成して、ログインの監査証跡を作成できるようにしたいと考えています。しかし、ググリングは良い結果をもたらしていません。

私たちが監査できるほど、優れています。少なくとも、いつ誰がログインしたかを知っておくといいでしょう。だれがどのクエリをいつ実行したかを確認したほうがよいでしょう。データベースには機密情報が含まれている可能性があるため、ログは主にクライアントにログを提供するためのものです。

明らかに、各ユーザーが(いつ)実行したクエリを監査できることで、セキュリティ上の問題が発生した場合に、その原因を正確に特定できるようになります。

11
statichippo

おそらく 一般クエリログ を使用することになります。

一般クエリログは、mysqldが実行していることの一般的な記録です。サーバーは、クライアントが接続または切断するときにこのログに情報を書き込み、クライアントから受信した各SQLステートメントをログに記録します。

セキュリティのためにログを記録する際の重要な点の1つは、攻撃者がログにアクセスしてその存在の痕跡を消去できないことです。そのため、 append-only files を検討してください。

OracleのFWIWでは、ログを自動的に リモートSyslog に送信できますが、MySQLにはまだこの機能がないと思います。たぶん、あなたはSNMPでそれを偽造することができましたが、私はそれを試していません。

6
Gaius

@Gauisの回答は素晴らしいです。さらにそれに追加するには、次のことができます。

MySQL 5.1では、一般ログとスロークエリログをSQLテーブルとして保存できるようになりました。

これを/etc/my.cnfに追加します。

[mysqld]
log-output=TABLE
log

Mysqlを再起動します

次に、mysqldがテキストファイルではなく一般的なログを作成すると、テーブルが/ var/lib/mysql/mysqlフォルダー(mysqlスキーマデータベース)にCSVテーブルとして作成されます。

これを表示するには、次のようにします。

SHOW CREATE TABLE mysql.general_log\G

すべての接続がその中に積み上げられます。

あなたにとっては、それはそれを照会することになるとあまり役に立ちません。毎回全テーブルスキャンになります。

何をすべきか ??? 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;

オプションで、引数フィールドにフルテキストインデックスを配置することもできます。

サーバーに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      | [email protected] 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      | [email protected] 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)

これで、タイムスタンプでクエリを実行し、引数フィールドで特定のトークンを探すことができます。

たとえば、私が選択したSELECTの4行目に注目してください。ログインは、引数フィールドに[email protected] 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への3つのシンボリックリンクを作成します。
  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;

3つのDBサーバーを持つクライアントがあります。 Each with DB Serverには、1,000,000,000(10億[千億])を超える行があります。上記のスクリプトの完了には、約2.5時間かかりました。 audit_user_Hostテーブルは、27の異なるログインで終わりました。

あなたは行ってもいいはずです。

みんな、これを楽しんでね!!!

5
RolandoMySQLDBA

多くのことを手動で行う代わりに、ユーザーレベルでより多くの洞察を提供する監査プラグインをインストールするだけです

http://www.mysql.com/products/enterprise/audit.html

一部の商用MySQLエディションでも利用できますが、MySQLフォークがコミュニティエディションにも追加されていれば、ほとんどの人がこの機能のメリットを享受できればすばらしいでしょう。

1
Mahesh Patil

@statichippo
MySQLに監査ログをインストールする方法。
+監査ログはMySQL Enterpriseのみをサポート
+ MySQLコミュニティに監査ログをインストールできます。
1。 MySQL Enterprise Trialをインストールしてから、ファイルaudit_log.soをMySQLコミュニティにコピーできます。
2。 audit_log.soをplugin_dirに/ usr/lib64/mysql/pluginとしてコピーするか、次のようにしてプラグインdirを表示できます。
mysqlコンソールに移動します。mysql> '%plugin%'などのグローバル変数を表示します。
3。次のように監査ログをインストールします。
mysql> INSTALL PLUGIN audit_log SONAME 'audit_log.so';
mysql> SHOW VARIABLES LIKE 'audit_log%';
4。出力監査ログ:
tail -f /var/lib/mysql/audit.log

どうもありがとう。

0
Binh Nguyen