【入門編】 データベース監査ログによる不正データ抽出の検知 – インシデントレスポンス & フォレンジック(DFIR)防御ガイド

こんにちは!セキュリティの世界へようこそ。インシデントレスポンスの現場で日々泥臭い調査をしているSOCアナリストです。

今回は、開発現場でもインフラの運用でも避けて通れない「データベース(DB)のセキュリティ」についてお話ししますね。特に、システムの中身をごっそり抜き出そうとする「不正なデータ抽出」をどうやって見破るのか、一緒に一歩ずつ紐解いていきましょう。

—

データベースを守るって、どういうこと?(身近な例え話)

みなさんのお家には玄関の鍵がありますよね。では、リビングのど真ん中に、通帳や印鑑、家中の合鍵が入った「透明な金庫」が置いてあったとしたらどうでしょう?ちょっとゾッとするし、夜中に変な物音がしたら飛び起きますよね。

Webシステムにおけるデータベースは、まさにこの「透明な金庫」のようなものです。
顧客のパスワード、クレジットカード情報、購入履歴といった機密データが綺麗に整理されて入っています。

外部からのハッキングを防ぐために「外側の壁(ファイアウォール)」を頑丈にするのはもちろん大切ですが、もし「合鍵をこっそり持っている人」や「悪い人が泥棒に入ってきて、金庫ごと中身をバックパックに詰め込んでいたら」……外側の壁だけを見ていては、絶対に気づけませんよね。

だからこそ、「誰が、いつ、どの金庫を開けて、中の書類をどれくらい持ち出したのか」を記録する「データベース監査ログ」の監視が、最後の砦として絶対に必要になるんです。

—

攻撃者はどうやってデータを盗むのか?

映画のようにカッコよくシステムをハッキングする……なんてことは現実の攻撃者ほとんどしません。彼らはもっと泥臭く、そして巧妙にシステムに忍び込みます。

よくある手口の代表が、以下の3つです。

1. 深夜帯こっそりダンプ(大量のSELECT)
みんなが寝静まった真夜中に、普段は絶対に使わないような大量のデータを一度に取得するコマンド(SELECT * FROM users; など)を流し込みます。
2. 管理者権限の乗っ取り
運悪くデータベースの「マスターキー」を持っている管理者アカウントのパスワードが破られてしまい、その権限を使って堂々と中身をごっそりコピーされます。
3. アプリケーションの隙を突く(SQLインジェクション)
Webサイトの入力フォームの隙を突いて、データベースに直接変な命令を送り込み、裏側のデータを無理やり画面に吐き出させます。

これらを放置してしまうと、翌朝には会社の大切な顧客データがダークウェブ(闇のインターネット市場)に売りに出されていた……なんていう悪夢のような事態になりかねません。

—

監査ログで「泥棒の足跡」をキャッチする

では、こうした不正を見抜くために、私たちはデータベースのログをどう監視すればよいのでしょうか?
ここからは、実務でそのまま使える具体的な検知ルールと、PostgreSQLやMySQLなどのデータベースでよく使われる監査ログの考え方を見ていきましょう。

1. 深夜帯のアクセス・大量クエリをあぶり出す

まずは「時間の不自然さ」と「量の異常さ」に着目します。
例えば、「平日の昼間なら1回あたり10件程度しかデータを引かないシステムなのに、日曜日の深夜3時に、1回で10万件のレコードを取得するクエリが走っている」としたら、これはもう事件の匂いがプンプンしますよね。

監視ツール(SIEMやログ分析基盤)に入れるための、検索クエリやルールのイメージはこんな感じです。

-- 【検知ルールの例】深夜帯における大量データ取得(SELECT)の抽出
SELECT
    log_timestamp,          -- ログが記録された日時
    db_user,                -- アクセスしたデータベースユーザー名
    client_ip,              -- 接続元のIPアドレス
    executed_query          -- 実行されたSQL文
FROM
    db_audit_logs
WHERE
    -- 深夜0時〜朝5時までのアクセスを対象にする
    (EXTRACT(HOUR FROM log_timestamp) >= 0 AND EXTRACT(HOUR FROM log_timestamp) <= 5)
    -- 大量のデータを一度にごっそり抜き出す構文(全件取得や大量結合など)が含まれている
    AND (executed_query LIKE '%SELECT *%' OR row_count_returned > 1000)
    -- メンテナンスバッチなどの「正当な理由がある深夜処理」を除外する
    AND client_ip NOT IN ('192.168.10.50'); -- 社内バッチサーバーのIP

このように、「いつ」「誰が」「何を」したのかを条件で絞り込むことで、怪しい動きをピタッとあぶり出すことができます。

2. 管理者権限による「テーブルダンプ」の監視

データベースの管理者(rootやpostgresユーザーなど)は、いわば「何でもできる神様」です。だからこそ、管理者が行う操作は厳しく監視しなければなりません。
特に、テーブル構造やデータを丸ごとファイルとして書き出すコマンド(MySQLの mysqldump や、PostgreSQLの pg_dump に相当する操作)の痕跡は、最優先でアラートを上げるべきです。

設定ファイル(例: PostgreSQLの postgresql.conf など)では、以下のように「ログに記録する対象(audit_log)」を細かく設定します。

# PostgreSQLの監査・ログ出力設定のサンプル
# すべての接続と、データ変更・大量取得の試行をログに残す設定にします

# ログに出力する対象(connection, disconn, command, ddl など)
log_connections = on
log_disconnections = on

# 実行されたSQL文をすべてログに記録する(※パフォーマンスと要相談ですがセキュリティ上は推奨)
log_statement = 'all'

# 処理時間が「1000ミリ秒(1秒)」を超えた重いクエリは強制的にログに残す
# (攻撃者が雑に組んだ重いSELECTクエリを見つけるため)
log_min_duration_statement = 1000

もし、本番環境のデータベースで log_statement = 'all' を有効にするのがパフォーマンス的に厳しい場合は、データ抽出を司る SELECT 文だけでも別枠で監査ログプラットフォームへ流す工夫をしましょう。

—

現場のアナリストからのアドバイス:アラートに埋もれないために

「じゃあ、怪しい動きを全部アラートにすればいいんだね!」と意気込んで、すべての SELECT 文を監視しようとすると、今度はアラートの嵐(アラート疲れ)でSOCの担当者がパンクしてしまいます。

現場で本当に使える仕組みを作るためのポイントを3つだけお伝えしますね。

1. 「白(ホワイトリスト)」をしっかり定義する
毎日定時に動くバックアップスクリプトや、日次レポートを自動生成するバッチ処理などは、必ず「安全なアクセス」として除外設定(ホワイトリスト化)しておきましょう。ここをサボると、毎日深夜に偽アラートが鳴り響いて誰も見なくなります。
2. 「普段との違い(ベースライン)」を知る
「普段、このテーブルは何時に、誰が、何件アクセスしているか」という日常の姿を把握しておくことが、異常を見つける一番の近道です。
3. インシデントが起きたときの「初動」をシュミレーションしておく
もし深夜に「大量データ抽出のアラート」が鳴ったらどうするか? 「すぐに該当するDBユーザーのパスワードを無効化する」「セッションを強制切断する」といった手順(プレイブック)を、あらかじめチームで共有しておきましょう。

—

まとめ

データベースの監査ログ分析は、最初は難しく感じるかもしれません。でも、「家の防犯カメラと、リビングの監視カメラ」なのだと考えれば、やるべきことはとてもシンプルです。

「誰がいつ金庫を開けたか」を記録し、普段と違う怪しい動きがないかを優しく見守る。この地道な積み重ねが、あなたの大切なシステムとデータを守り抜く最強の盾になります。

一歩ずつ、できるところから環境や設定を見直していきましょう!

コメント

タイトルとURLをコピーしました