Skip to content

8 Log Detections for Credential Stuffing and MFA Exploit Prevention

8 Log Detections for Credential Stuffing and MFA Exploit Prevention の翻訳です。

Auth0 Logs を Security Information and Event Management(SIEM)ツールへストリーミングした際に活用できる「検知ポイント」を紹介するブログシリーズを継続しています。Auth0 Log Streaming を使うと、リアルタイムの可視性と柔軟性を得られ、クレデンシャルスタッフィングのような繰り返し発生する脅威を検知するための、Auth0 セキュリティ監視を独自に構築できます。シリーズの過去記事では、サインアップ詐欺やリフレッシュトークンのセキュリティを取り上げました。

Auth0 Security Center は、クレデンシャルスタッフィングや MFA バイパス、サインアップ攻撃などに対してすでに強力な組み込み監視機能を提供しています。一方で、Auth0 環境のセキュリティ監視用の検知ルール集である Auth0 Detection Catalog は、それを補完するアプローチを提供します。この「Bring Your Own Detections」モデルにより、あなた固有の環境やニーズに合わせて検知を調整でき、透明性と柔軟性も得られます。

本記事では、Auth0 Detection Catalog から強力な 8 つの検知ルールを紹介し、セキュリティ実践を強化するためのヒントを提供します。これら 8 つの検知は、クレデンシャルスタッフィング、MFA 悪用、認可リクエスト乱用といった攻撃ベクトルを監視するよう設計されています。

クレデンシャルスタッフィングに対する「二段構え」

クレデンシャルスタッフィングは、第三者の侵害で漏えいした認証情報を利用する、しぶとい脅威です。高度なボットネットが関与することも多く、活動を隠蔽しようとします。Auth0 Detection Catalog には、これらの攻撃を特定・確証するために連携して機能する 2 つの検知があります。

クレデンシャルスタッフィングのシグナルを診断する

credential_stuffing_signals.yml は、ボリューム(量)に基づくシグナル、つまりボットが動いている典型的な兆候である 異常なバースト にフォーカスした検知です。

このルールは、大量のログイン失敗イベント(f, fu, fp, fcoa)や、特定の Auth0 Attack Protection イベント(pwd_leak, limit_wc, limit_sul, limit_mu)に関するパターンを分析し、進行中のクレデンシャルスタッフィング攻撃を診断するために設計されています。

提供されている Splunk クエリは、デフォルトで 1 時間のウィンドウ(必要に応じて調整可能)に対して、3 つの異なる検知シグナルを含みます。

  1. 単一 IP アドレスから発生する失敗イベントの高ボリューム
  2. テナント全体でのログイン失敗または Attack Protection イベントの大幅な急増
  3. 失敗イベントの送信元 IP のユニーク数が異常に増えるスパイク(住宅回線 IP を踏み台にする、大規模・分散型ボットネットを示すことが多い)

このクエリは、有効な比較のために「平常時の基準(normality)」を計算し、さらに JA3/JA4 の TLS フィンガープリントデータも収集します。このデータは関連する攻撃トラフィックをクラスタリングするうえで重要で、後続の調査を強力にします。次の検知でその活用例を示します。

index=auth0 data.tenant_name="{your-tenant-name}"
data.type IN (f, fu, fp, pwd_leak, limit_wc, limit_sul, limit_mu, fcoa)

``` Signal 1 - any single IP triggers excessive number of 
failed/attack protection events ```
| bin _time span=1h
| stats values(data.security_context.ja4) as ja4
 count as cnt_events_per_ip by _time data.ip
| where cnt_events_per_ip > {threshold_events_per_ip}
``` Normality for Signal 1 - average number of successful logins per 
    IP (per hour) ```
| join [
    search index=auth0 data.type = s
    | stats count AS successful_logins_per_ip by data.ip
    | stats avg(successful_logins_per_ip) AS avg_successful_logins_per_ip
]

``` Signal 2 - surge in failed login or attack protection events ```
```
| stats values(data.security_context.ja4) as ja4
count as cnt_total_per_event by _time data.type
| where cnt_total_per_event > {threshold_count_per_event}```
``` Normality for Signal 2 - average number successful logins (per hour) ```
```
| join [
    search index=auth0 data.type = s
    | stats count AS successful_logins_per_s by data.type
    | stats avg(successful_logins_per_s) AS avg_successful_logins_per_s
]```

``` Signal 3 - surge of observed IPs with failed events ```
```
| stats dc(data.ip) as cnt_total_ips values(data.ip) as ip
  values(data.security_context.ja4) as ja4 by _time
| where cnt_total_ips > {threshold_total_ips}```
``` Normality for Signal 3 - average number of IPs with 
successful logins (per hour) ```
```| join [
    search index=auth0 data.type = s
    | stats dc(data.ip) AS successful_logins_ips by _time
    | stats avg(successful_logins_ips) AS avg_successful_logins_ips
]```

疑わしい TLS フィンガープリントからのログイン

2 つ目の検知である logins_from_suspicious_tls_fingerprints.yml は、credential_stuffing_signals.yml を土台に、侵害された可能性のあるアカウントを確証するための検知です。

この検知は、成功したログインと、直前に credential_stuffing_signals.yml で確認された「疑わしい大量失敗」に含まれる JA4 フィンガープリント を相関させることで、アカウント侵害の可能性を識別します。

JA4 フィンガープリントは TLS の ClientHello メッセージから構成され、簡単に改ざん・偽装され得る User-Agent 文字列に頼らずに、利用アプリケーションを追跡するための代替指標として活用できます。

この検知は 2 ステップで構成されます。

  1. 大量のログイン失敗または Attack Protection イベントを発生させた IP を起点に、疑わしい JA4 フィンガープリントを特定します。このステップは、credential_stuffing_signals.yml で提案されている他のシグナルに置き換えることもできます。
  2. 次に、成功したログインイベント(s および scoa)をフィルタし、先ほど特定した疑わしいトラフィックと同じ JA4 フィンガープリントを共有するものだけを残します。

最終出力は、成功ログイン、疑わしい JA4 フィンガープリント、ユーザー名の一覧になります。これにより、大量失敗を引き起こした自動化ツール/インフラと “同一” のものが、実際にアカウント侵害に成功した可能性が高いことを強く示唆できます。

index=auth0 data.tenant_name="{your-tenant-name}"
   | bin _time span=1h
``` Successful login events and associated JA4 ```
   | search data.type IN (s, scoa)
   | rename data.security_context.ja4 as seen_ja4_hash
   | fields _time, data.type, seen_ja4_hash, data.user_name
``` Filter these events using the list of JA4 hashes seen in failed events 
pointing to credential stuffing ```
   | join type=inner seen_ja4_hash [
    search index=auth0 data.type IN (f, fu, fp, pwd_leak, 
    limit_wc, limit_sul, limit_mu, fcoa)
    | stats count as cnt_events_per_ip by data.security_context.ja4 data.ip
    | where cnt_events_per_ip > {threshold_events_per_ip}
    | fields data.security_context.ja4
    | rename data.security_context.ja4 as seen_ja4_hash
]
```Final output ```
   | table data.type, seen_ja4_hash, data.user_name

この検知では、JA4 フィンガープリントは異常活動(=クレデンシャルスタッフィング)に関連しているため疑わしいと見なされます。JA4 の一覧を絞り込み、高リスクのものに集中するため、以下 2 つの追加フィルタも適用することを推奨します。

  1. これらのフィンガープリントが、一般的なアプリケーションの公開 データベース に含まれているか?
  2. 脅威インテリジェンスのストリームがある場合、これらの JA4 フィンガープリントが悪性インフラと関連付けられているか?

これらを除外(または加味)することで精度の高い結果が得られ、誤検知も減らせます。代わりに logins_from_suspicious_tls_fingerprints.yml は JA3 フィンガープリント向けに調整することも可能です。Chrome に最近導入されたランダム化 の影響で JA3 の精度は落ちつつありますが、それでも過去の悪性活動への帰属(attribution)に高い確度がある場合には、有効なシグナルになり得ます。

また、JA4 フィンガープリントが高精度(正当ユーザーへ影響するリスクが小さい)と判断できる場合は、Auth0 Network/Tenant Access Control List を用いてこれらのフィンガープリントをブロックすることも推奨します。

認可リクエスト乱用の監視

認可リクエストの乱用は、見落とされがちです。脅威アクターは、クレデンシャルスタッフィングや MFA 悪用のような複雑な攻撃に入る前に、しばしばシンプルな高ボリュームの探索(プロービング)から始め、攻撃対象領域の把握、設定ミスの発見、既知の脆弱性のテストを行います。例えば、壊れた形式のリクエスト(malformed request)や、定型 URL の利用などです。こうした一見小さな失敗や逸脱を監視することで、より集中的な攻撃が迫っていることを早期に察知できます。

誤ったパラメータによる認可リクエスト失敗の急増

認可リクエストの失敗が大量に発生する場合、探索(プロービング)や DoS(サービス妨害)の兆候である可能性があります。many_failed_authorization_requests.yml は、標準パラメータの不正な値によって認可リクエストが壊れた形式になっている失敗が急増するケースを検知します。

攻撃者は次のような目的を持っている可能性があります。

  • インジェクション攻撃の実行: 攻撃者はまず SQL インジェクション、リモートコード実行、クロスサイトスクリプティングなどの基本的な攻撃から試すことがあります。
  • 認可コードやトークンの収集: OAuth 2.1 のパラメータ組み合わせを系統的に試し、例えば PKCE のダウングレード回避や redirect_uri 検証の脆弱性を探る可能性があります。
  • DoS(サービス妨害)攻撃: 壊れた形式のリクエストを大量に投げてテナントのレート制限を枯渇させようとします。

この検知は特に、次の OAuth 2.1 パラメータに関連する失敗を監視・カウントします。

  • 未登録または無効な redirect URI
  • 不明な audience または client
  • 未サポートの response type または challenge type

これらのカテゴリいずれかでカウントが指定しきい値を超えると検知し、調査のために具体的な “壊れた値” も提示します。

index=auth0 data.tenant_name="{your-tenant-name}"
    data.type = f
    data.description IN ("*is not supported by this server*",
 "*mismatch*", "*Unknown client*", "*Unsupported response type*",
 "*Service not found*", "The redirect_uri parameter is not valid*")
    | fields data.description
    ```Collect injection strings```
    | rex field=data.description "Callback URL mismatch. (?<mismatch_uri>[^ ]+)"
    | rex field=data.description "Code challenge type 
      (?<malformed_challenge_type>[^ ]+) is not supported by this server."
    | rex field=data.description "Unknown client: (?<malformed_client>.*)"
    | rex field=data.description "Unsupported response type: 
      (?<malformed_response_type>.*)"
    | rex field=data.description "Service not found: (?<malformed_audience>.*)"
    | rex field=data.description "The redirect_uri parameter 
    is not valid: "(?<malformed_redirect>[^"]*)""
    ```Prepare output: list injected strings and calculate 
    volumes for each parameter of the authorization request```
    | stats values(mismatch_uri) as mismatch_uri, values(malformed_challenge_type) 
    as malformed_challenge_type, values(malformed_client) as malformed_client,
      values(malformed_response_type) as malformed_response_type, 
    values(malformed_audience) as malformed_audience, 
    values(malformed_redirect) as malformed_redirect
    | transpose
    | rename "column" as field, "row 1" as value
    | eval count=mvcount(value)
    | table field, value, count
    | where count > {threshold}

Auth0 テナントの “正規URL” が使われている

Auth0 の多くの顧客は、シームレスで信頼されるユーザー体験を提供するために カスタムドメイン(例:login.yourcompany.com)を登録します。カスタムドメインのオンボードと有効化が完了した後、元の Auth0 テナント名 URL(例:yourtenant.auth0.com)を狙ってリクエストが飛ぶ正当な理由はほとんどありません。

この指標は見落とされがちですが、危険信号になり得ます。攻撃者はスクリプトでデフォルトとして正規(canonical)の Auth0 URL を使うことがありますし、カスタムドメインしか監視していないセキュリティ制御(例:WAF)を回避する目的で使うこともあります。

use_of_auth0_tenant_name_url.yml は、この動きを可視化するのに役立ちます。

index=auth0 data.tenant_name="{your-tenant-name}"
   data.type IN (s, f, fs, ss, w, fp, scoa, fcoa, sepft, fepft)
   data.hostname="{your-tenant-url}"
   | fields data.client_id, data.client_name, data.log_id
   | table _time, data.client_id, data.client_name, data.log_id

テナントの canonical URL を明示的に使用している「成功・失敗の認証イベント」に絞り込むことで、確立されたユーザーフローを回避しようとする試みを把握するための重要な洞察が得られます。

この指標をカタログに含める提案をしてくれた Vikas Jayaram に感謝します。

MFA 悪用の兆候を捉える:誤用とボリューム攻撃

MFA は重要ですが、攻撃者は常に MFA 悪用の方法を探しています。次の 4 つの検知は、MFA チャレンジ要求の異常バーストや、不審な登録パターンを監視します。

MFA 要素(電話番号・Auth0 Guardian)の誤用

脅威アクターは、同じ電話番号や単一の Auth0 Guardian アプリ インストールを、複数の侵害アカウントで使い回します。

複数ユーザーが同一の電話番号を共有する正当なケース(家族、あるいは同一人物が仕事用・個人用メールで 2 ユーザー登録する等)もありますが、同一デバイスや電話番号に紐づくユーザー数が過剰に多い場合、単一アクターによるアカウント侵害の兆候である可能性があります。あるいは、トールフラウド(通話料詐欺)のようなボリューム攻撃の前兆かもしれません。

両検知とも、要素(電話番号/Auth0 Guardian の識別子)ごとの登録ユーザー数を提供します。例えば次のように集計します。

index=auth0 data.tenant_name="{your-tenant-name}"
   data.description="Guardian - Enrollment complete (sms)"
   data.type=gd_enrollment_complete
   | fields data.details.authenticator.phone_number, data.user_id, data.ip
   | stats dc(data.user_id) as users_count values(data.ip) 
   by data.details.authenticator.phone_number
   | where users_count > 1

ボリューム型の MFA 悪用(Push 疲労・SMS 爆撃)

MFA push fatigue(プッシュ疲労)は、ユーザーに大量の MFA リクエストを送りつけ、「うっとうしさ」からユーザーが誤って承認してしまうことを狙う機会主義的な攻撃です。

risk_for_mfa_push_fatigue.yml は、潜在的な脅威行動の 2 つの側面を見ます。具体的には、ユーザーに送られたプッシュ通知数と、プッシュ通知がどれだけ短時間で送られたかを計算します。

index=auth0 data.tenant_name="{your-tenant-name}"
   data.type=gd_send_pn
   | fields data.user_id, data.ip
   | stats min(_time) as window_start_time, max(_time) as window_end_time, 
   count as count_pushes_per_user by data.user_id
```| stats max(count_pushes_per_user) as max_count```
   | eval window_duration_seconds = window_end_time - window_start_time
   | eval window_duration_mins = window_duration_seconds/60
   | where window_duration_mins<={time_window_threshold} 
   AND count_pushes_per_user > {count_pushes_per_user_threshold}
```Display the information in a table```
   | table count_pushes_per_user, window_duration_mins, data.user_id, data.ip

SMS pumping(SMS 爆撃)は通常、金銭的目的(=トールフラウド)と関連します。この種の攻撃は、使い捨てドメインを伴う サインアップ詐欺 と隣接して起きることもあります。sms_bombarding.yml は、ユーザーあたりに送信された SMS の件数ボリュームを調べます。この検知の拡張として、送信総数の監視や、失敗率を加味することも可能です。

index=auth0 data.tenant_name="{your-tenant-name}"
   data.type = gd_send_sms data.description="Guardian - Second factor sms sent"
   | fields data.user_id
```The period of observations - adjust```
   | bin _time span=1h
   | stats count as sms_per_user by data.user_id
   | where sms_per_user > {threshold_for_max_sms}

これらの検知は高ボリューム攻撃のシグナルを捉え、攻撃が成功する前、あるいは高額なトールコストが発生する前に活動を止めることを可能にします。ユーザー単位/IP 単位/テナント全体での MFA リクエスト量を監視することが、こうした悪用を見抜く鍵です。

次のステップ

セキュリティは共同責任であり、Auth0 プラットフォームの柔軟性は防御力を高めるためのツールを提供します。ここで紹介した Auth0 Detection Catalog の 8 つの検知は、実際の脅威インテリジェンスと現実のインシデントから得られたベストプラクティスを反映しています。

次をおすすめします。

  1. 採用してデプロイする: これらの検知を取り込み、Auth0 Log Streaming を使って SIEM に実装してください。
  2. 貢献する: このカタログはオープンソースのコミュニティ活動です。価値のある検知を開発した場合は、GitHub の Auth0 Detection Catalog へコントリビュートして、コミュニティ全体の安全性向上に協力してください。

今日からログをストリーミングし、脅威検知の主導権を取り戻しましょう!