ログを読まずにルールは作れません。前回に続いて今回はDiscoverでイベントの中身を確認しながら、「ログイン失敗を検知する」最初のルールを正しい条件で作ります。ルール作成前にDiscoverで確認する習慣が、後々の誤検知を防ぐ最大のポイントです。
※本シリーズで使用するデータセットは、第1回の記事からダウンロードできます。
この記事を読むと何ができるか
event.outcome:"failure"に複数種類の失敗が混在していることを理解できるevent.action:"user-login" and event.outcome:"failure"でログイン失敗だけを正確に絞り込めるFailed Login Detection (Basic Rule)という名前の検知ルールが動いている状態になる- 過去データの確認に Rule preview と manual run を使い分けられる
Step 1:Discoverでイベントの中身を確認する
Discoverを開き、左上のData Viewが training-security-logs になっていることを確認します。時間範囲は「Last 2 years」に変更してください。

まず次のフィールドを列として追加します。フィールド名の横の「+」アイコンをクリックすると列に追加できます。
| フィールド | 何を見るか |
|---|---|
@timestamp | いつ起きたか |
event.action | 何のイベントか |
event.outcome | 成功か失敗か |
user.name | 対象ユーザー |
source.ip | 送信元IP |
host.name | 対象ホスト |
Step 2:ログイン失敗だけに絞り込む
まず次のKQLを実行します。
event.outcome:"failure"
18件ヒットします。ここで event.action 列に注目してください。event.outcome:"failure" は「失敗したイベント全般」を返します。ログイン失敗だけでなく、ポートスキャン時の接続失敗も含まれます。「Failed Login Detection」という名前のルールをこの条件で作ると、名前と実態がずれたルールになってしまいます。

| event.action | 件数 | 意味 |
| connection-attempt | 6件 | ポートへの接続試行が失敗 |
| user-login | 12件 | ログイン試行が失敗 |
次のKQLを実行します。
event.action:"user-login" and event.outcome:"failure"12件に絞られます。connection-attempt の失敗が消え、純粋にログイン失敗だけが残っているはずです。

確認ポイント:
event.actionがすべてuser-loginになっているかevent.outcomeがすべてfailureになっているかconnection-attemptのようなネットワーク失敗が混ざっていないか
混ざっていなければ、この条件がルールのKQLとして使えます。
event.categoryをルール条件に使う際の注意点event.categoryはマルチバリューフィールドです。1件のイベントが["iam", "authentication"]のように複数の値を持てる設計になっています。Elastic SecurityのCustom query ruleでこのフィールドをルール条件に使うと、「The event.category field cannot be used for…」というエラーが表示される場合があります。ルールのKQL条件ではevent.actionやevent.outcomeのようなシングルバリューフィールドを使い、event.categoryはDiscover での確認用として使うのが安全です。
※ Discoverでフィールドの統計量を確認できる。

Step 3:このサンプルデータに含まれる2つのシナリオ
絞り込んだ12件を時系列で見ると、2つの独立した攻撃シナリオが含まれています。この章では両方のシナリオを拾う「一般的なログイン失敗の監視ルール」を作ります。シナリオAの攻撃チェーンを詳しく追う調査は第3回で行います。
シナリオA:内部ネットワークからの侵害の可能性(source.ip: 192.168.1.100)
UTC 10:03台に、192.168.1.100 から PROD-SRV-01 に対して admin_root と administrator へのログイン失敗が複数回続き、その直後に成功しています。
このような「短時間の連続失敗の後に成功する」挙動は、ブルートフォース攻撃による認証突破の可能性を示す典型的なパターンです。ただし、ユーザーの入力ミスによる正常なログインの可能性もあるため、追加の調査が必要です。
シナリオB:外部からのブルートフォース(source.ip: 45.33.21.11)
UTC 10:14〜10:17台に、外部IP 45.33.21.11 から PROD-SRV-01 に対して guest・admin・root・administrator など複数のユーザー名でログイン失敗が連続して発生しています。
これは、一般的なアカウント名を順に試す典型的なブルートフォース攻撃の挙動です。
Step 4:ルールタイプを選ぶ
Elastic Securityには複数のルールタイプがあります。
| ルールタイプ | 何を見るか | 向いているケース |
|---|---|---|
| Custom query | 条件に一致する1件1件のイベント | 1件でも起きたら知らせたい |
| Threshold | 一致したイベントの件数 | 5回以上失敗したら知らせたい |
| ES|QL | 集計・加工した結果 | 合計転送量が閾値を超えたら |
| Event Correlation | イベントの順序・パターン | AのあとにBが起きたら |
今回は「1件のログイン失敗が起きたら知らせたい」ので Custom query を選びます。Threshold は「何回失敗したか」を数えるためのものであり、1件ずつ検知したい今回の目的には向きません。Threshold の使い方は第5回で扱います。
Step 5:ルールを作る
Security → Rules → Detection rules (SIEM) → Create new rule を開きます。


ルールタイプの選択画面で「Custom query」を選んで「Selected」にします。

Define rule の設定:
データソースとして「Data View」タブを選び、training-security-logs を指定します。Custom query 欄に次を入力します。
event.action:"user-login" and event.outcome:"failure"
保存前に必ずDiscoverで確認する ルールを保存する前に、同じKQLをDiscoverで実行して「期待したイベントだけが返ってくるか」を必ず確認してください。この確認を省くと、想定外のイベントを拾うルールや、何もヒットしないルールを本番環境に入れてしまうリスクがあります。
About rule の設定:
| 項目 | 設定値 |
|---|---|
| Name | Failed Login Detection (Basic Rule) |
| Description | training-security-logs 内のログイン失敗イベントを検知する |
| Severity | Low |
| Risk score | 21 |

Schedule の設定:
| 項目 | 設定値 |
|---|---|
| Runs every | 5 minutes |
| Additional look-back time | 1 minute |
「Continue」をクリックし、「Create & enable rule」で保存します。

※ノイズ削減(重複アラートの圧縮や正常動作の除外)は別の回で扱います。
Step 6:過去データに対してルールを確認する
このサンプルは2025-03-18の過去データです。ルールを有効化しても、ルールは「現在時刻からの直近ウィンドウ」を見るため、今すぐアラートが自動生成されることはありません。これは故障ではなく正常な動作です。
過去データを確認するための2つの方法を使い分けます。Rule preview の手順:
- ルール編集画面右上の「Rule preview」をクリック
- 時間範囲を設定する
- 開始:
2025-03-18 10:00:00(UTC)/ 画面表示では19:00:00JST - 終了:
2025-03-18 10:30:30(UTC)/ 画面表示では19:30:30JST
- 開始:
- 「Refresh」をクリック
期待値:12件のアラートが表示される(内部侵害4件 + 外部ブルートフォース8件)

Manual run の手順:
- ルール詳細画面の右上メニューから「Manual run」を選ぶ
- 時間範囲を過去データの期間に合わせて指定する
- 「Run」をクリック
Security → Alertsを開き、Alerts画面の時間範囲も「Last 2 years」などに広げる
※Additional look-back timeをかなり長くとる方法も合います

アラートが見えないときの確認手順
| 手順 | 確認内容 |
|---|---|
| ① | Discoverで同じKQLを実行してヒットするか確認する |
| ② | 各画面の時間範囲が過去データに合っているか確認する |
| ③ | securitySolution:defaultIndex に training-security-logs が入っているか確認する(第1回参照) |
| ④ | ルール詳細の「Execution results」タブを確認する。「Succeeded」はクエリが正常終了したことを意味するだけで、ヒット件数がゼロのまま正常終了することがある |
生成されたアラートから読み取れること
Manual run後に Security → Alerts を開くと、次の状況が確認できます。
サマリー画面で全体傾向を把握する
画面上部の Summary タブでは、検知結果の全体傾向が一目でわかります。
| 確認項目 | このデータでの期待値 |
| Severity levels | すべて「Low」、計12件 |
| Alerts by name | Failed Login Detection (Basic Rule):12件 |
| Top alerts by source.ip | 45.33.21.11(約66%)、192.168.1.100(約33%) |
「どの送信元からの攻撃が多いか」がひと目でわかります。
テーブルで個別アラートを確認する
テーブルビューで確認すべき主なフィールドは次のとおりです。
| フィールド | 確認すること |
| @timestamp | いつ発生したか(時間が集中していないか) |
| Rule | どのルールで検知されたか |
| Severity / Risk Score | 重要度(今回は Low / 21) |
| host.name | 攻撃対象のホスト(PROD-SRV-01) |
| user.name | 試されたユーザー名(admin_root, guest など) |
今回の12件のアラートから、次の状況が推測できます。
- 同一ホスト(
PROD-SRV-01)に対して - 複数のユーザー名(
admin_root・administrator・guest・admin・root)で - 複数回のログイン失敗が発生している
- 送信元IPが2つあり、
45.33.21.11が大多数を占める
これはブルートフォース攻撃の典型的な兆候です。ただしこの時点では「疑いがある」という段階です。次の第3回でTimelineを使って攻撃の流れを詳しく追います。
この章のまとめ
event.outcome:"failure"だけでは、ログイン失敗以外の失敗イベントも含まれるevent.action:"user-login" and event.outcome:"failure"で、ログイン失敗だけを正確に絞れるevent.categoryはマルチバリューフィールドのため、ルールのKQL条件に使うとエラーになる場合がある- 最初のルールには Custom query を使い、件数ではなく1件1件を検知する
- 過去データの確認には、Rule preview(シミュレーション)と manual run(本番実行)を使い分ける
第2回チェックリスト
- [ ]
event.outcome:"failure"で18件、event.action:"user-login" and event.outcome:"failure"で12件ヒットする - [ ]
Failed Login Detection (Basic Rule)が作成され、有効化されている - [ ] Rule preview または manual run でアラートが確認できている
- [ ] Alertsのサマリーで
45.33.21.11と192.168.1.100の2つの送信元が見えている
次回は: Timelineを使って、192.168.1.100 からの攻撃をポートスキャンからデータ持ち出しまで1本の時系列で読み解きます。「アラートを見る」から「攻撃の流れを説明できる」へ進みます。


