このトピックでは、Agentic SOC プラットフォーム内で Simple Log Service (SLS) の SQL クエリ機能を使用してカスタム検出ルールを構築する方法を示します。このルールを使用すると、休眠アカウントからのログインなどのセキュリティインシデントを監視し、リアルタイムアラートを生成できます。
背景
目的: 休眠アカウントからのログインを検出します。
方法: スケジュールされた SQL クエリを使用して、最近のログインを履歴ベースラインと比較します。これにより、最近ログインしたが、長期間にわたって履歴レコードに表示されていないユーザーを特定します。
コアロジック
検出ロジックは、主に 3 つの部分で構成されています。
最近のアクティビティの定義: 過去 20 分間に発生したすべてのログインイベントをクエリします。
履歴ベースラインの定義: より長い期間、具体的には過去 24 時間以内にホストにログインしたユーザーをクエリしますが、直近の 20 分間は除外します。
データセットの比較: 最近のアクティビティを履歴ベースラインと結合します。ユーザーが最近のアクティビティに表示されても、履歴ベースラインにレコードがない場合、そのログインは異常と見なされます。
最近のアクティビティの定義
(
select
user_id,
src_ip,
username,
uuid,
start_time
from
log
where
cast(start_time as bigint) >= cast(to_unixtime (current_timestamp) as bigint) - 20 * 60
and cast(start_time as bigint) < cast(to_unixtime (current_timestamp) as bigint)
) a構文分析:
from log:logテーブルからデータをクエリします。to_unixtime(current_timestamp): 現在の UNIX タイムスタンプを秒単位で返します。cast(... as bigint): タイムスタンプを算術演算と比較のためにbigint(長整数) データ型に変換します。where ...: 現在の時刻で終了する 20 分間のスライディングタイムウィンドウを定義します。>= ... - 20 * 60: ログの開始時刻 (start_time) は、「現在時刻 - 20 分」以上である必要があります。< ...: ログの開始時刻は、「現在時刻」より前である必要があります。
ロジック分析:
目的: 分析の主要なオブジェクトの範囲を定めるために、「最近のアクティビティ」として
aという名前のセットを定義します。結果:
user_idやsrc_ipなど、過去 20 分間にアクティブだったユーザーの一時的な結果セット。キーポイント: 「最近」の期間は、現在時刻から遡る 20 分 のタイムウィンドウとして正確に定義されます。
履歴ベースラインの定義
(
select
user_id,
username,
uuid
from
log
where
schema='HOST_LOGIN_ACTIVITY' and
cast(start_time as bigint) >= cast(to_unixtime (current_timestamp) as bigint) - 24 * 3600
and cast(start_time as bigint) < cast(to_unixtime (current_timestamp) as bigint) - 20 * 60
) b構文分析:
schema='HOST_LOGIN_ACTIVITY': ホストのログインアクティビティログのみをクエリすることで、履歴ベースラインの精度を高めます。where ...: 24 時間前から 20 分前までの時間範囲を定義します。>= ... - 24 * 3600: ログの開始時刻は、「現在時刻 - 24 時間」以上である必要があります。< ... - 20 * 60: ログの開始時刻は、「現在時刻 - 20 分」より前である必要があります。
ロジック分析:
目的: アクティビティが異常かどうかを判断するためのリファレンスとして、「履歴ベースライン」セット
bを構築します。結果: 直近の 20 分間を除き、過去 1 日以内にログインしたユーザーを含む一時的な結果セット。
キーポイント: このタイムウィンドウは 24 時間前から 20 分前までに設定されています。これにより、履歴ベースラインデータが最近のアクティビティデータと重複しないようにし、自己比較による論理エラーを防ぎます。
差分比較のための LEFT JOIN の使用
... a
left join
... b on a.username = b.username and a.uuid = b.uuid and a.user_id = b.user_id構文分析:
LEFT JOIN: 左テーブル (a、最近のユーザー) をベースとして使用し、その各レコードを右テーブル (b、履歴ユーザー) のレコードと照合します。on a.username = b.username and a.uuid = b.uuid and a.user_id=b.user_id: 結合条件を指定します。username、uuid、およびuser_idフィールドを一緒に使用してユーザーエンティティを一意に識別し、正確な照合を保証します。
ロジック分析:
目的: 「最近のアクティビティ」(
a) を「履歴ベースライン」(b) と関連付けて、最近の各ユーザーアクティビティに対応する履歴ログインレコードを見つけます。結果: テーブル
aのすべてのレコードと、ユーザー ID フィールドに基づいて正常に照合されたテーブルbのレコードを含む結合結果セットを生成します。キーポイント: このクエリは
LEFT JOINの非対称的な性質を活用します。テーブルaのユーザーがテーブルbに存在しない場合、結果ではテーブルbのすべての列がNULLになります。これが、新しいアクティビティを特定するためのコアメカニズムです。
最終結果のフィルター
where
(
b.username is null
or b.username = ''
)構文分析:
b.username is null: これはLEFT JOINの特性を活用するためのキーです。最近ログインしたユーザー (テーブルa内) が履歴ベースライン (テーブルb) に見つからない場合、b.usernameはNULLになります。or b.username = '': これは、ログフィールドがNULLではなく空の文字列''である場合を処理するための防御的な条件です。
ロジック分析:
目的: 結合された結果をフィルターして、最近出現したが履歴レコードがないアクティビティを分離します。
結果: このフィルターを適用した後、結果セットには
LEFT JOINで照合に失敗したレコード、つまり探している異常なイベントのみが含まれます。キーポイント:
b.username is nullは、検出ロジック全体のコアな決定点です。前のステップで生成されたNULL値を使用して、「最近存在し、履歴には存在しない」レコードを巨大なデータセットから分離します。
アラートを出力するための SELECT DISTINCT の使用
select distinct
a.user_id,
a.src_ip,
a.username,
a.uuid構文分析:
SELECT DISTINCT: 指定されたフィールドを選択して出力し、結果から重複を削除します。これにより、単一の異常イベントに対して 1 つのアラートのみが生成されることが保証されます。
ロジック分析:
目的: アラートに直接使用できる異常イベントの最終リストをフォーマットして出力します。
結果: クリーンで重複排除されたアラートのリスト。各レコードには、ユーザー ID やソース IP など、異常イベントを追跡するために必要なコア情報が含まれています。
キーポイント:
DISTINCTの使用は重要です。結果を重複排除して、検出ウィンドウ (20 分) 内の同じユーザーからの同じ異常な動作がアラートを 1 つだけトリガーするようにします。
完全なソリューション
最終的な SQL クエリ
*|set session mode=scan;
select distinct
a.user_id,
a.src_ip,
a.username,
a.uuid
from
(
select
user_id,
src_ip,
username,
uuid,
start_time
from
log
where
cast(start_time as bigint) >= cast(to_unixtime (current_timestamp) as bigint) -20 * 60
and cast(start_time as bigint) < cast(to_unixtime (current_timestamp) as bigint)
) a
left join (
select
user_id,
username,
uuid
from
log
where
schema='HOST_LOGIN_ACTIVITY' and
cast(start_time as bigint) >= cast(to_unixtime (current_timestamp) as bigint) - 24 * 3600
and cast(start_time as bigint) < cast(to_unixtime (current_timestamp) as bigint) -20 * 60
) b on a.username = b.username
and a.uuid = b.uuid
and a.user_id=b.user_id
where
(
b.username is null
or b.username = ''
)Agentic SOC でのルールの設定
Agentic SOC の購入と有効化
購入オプションについては、「購入と有効化」をご参照ください。すべてのカスタム脅威検知サービスにアクセスするには、ログアクセストラフィック と Log Storage Capacity の両方を購入することをお勧めします。
コンソールにログインし、Create Custom Rule ページに移動します
にログオンします。
左側のナビゲーションウィンドウで、 を選択します。コンソールの左上隅で、資産が所在するリージョンを選択します:Chinese Mainland または Outside Chinese Mainland。
カスタム タブで、Create Custom Rule をクリックします。
アラート生成ルールの構成
Create Custom Rule パネルの Basic Information タブで、ルール名と説明を入力し、次へ をクリックします。
SQL 検出ルールを構成します。次のパラメーター設定を参照してください。
パラメーター
値
ルール本文
SQL
ログ範囲
ログオンログ - ホストログオン成功ログ。
SQL クエリ
最終的な SQL クエリセクションからコードをコピーします。
スケジューリング間隔
固定間隔 - 20 分。
SQL タイムウィンドウ
24 時間。
開始時刻
ルールが有効化されたとき。
生成構造
その他のアラートログ。
アラームメトリック
異常ログオン。
アラートの重大度
中。
ATT&CK 戦術
永続化 - T1136 アカウントの作成。
エンティティマッピング
ネットワークアドレス
is_malware: 1ip:$src_ipnet_connect_dir: in
ホスト
is_asset: 1uuid:$uuid
インシデント生成ルールの構成
Alert Settings ページで、構成を完了したら、次へ をクリックします。
イベントルールを構成します。次のパラメーター設定を参照してください。
Generate Event:はい。
Incident Generation Method:タイプ別に集約。
集約ウィンドウ:20 分。
ルールの検証
新しいルールは、デフォルトで Disabled になっています。テストしてその効果を評価できます。テスト中、システムは自動的にアラートフィールドを調整します。ルールが有効になった後のアラートの精度と標準化を確保するため、生成された調整の提案を使用して、ルールの SQL またはプレイブックを最適化してください。
対象のルールのEnabling StatusをTestingに変更します。
対象のルールの「操作」列で、View Alert Test Result をクリックします。
テスト結果の詳細ページで、アラートの傾向チャートと生成されたアラートのリストを表示します。
アラートの操作列で、[詳細]をクリックして、そのキャリブレーション結果を表示します。
カスタムルールの有効化
ルールがテストに合格したら、Enabling Status を
Enabledに設定します。重要ルールを有効にする前にテストすることをお勧めします。
テスト結果の例

リスク評価
誤検知: 長期休暇や出張後に初めてログインする通常のユーザーが誤ってフラグ付けされる可能性があります。履歴の参照期間を延長する (たとえば、24 時間から 72 時間へ) か、ユーザーのホワイトリストを構成することで、誤検知を減らすことができます。
偽陰性: ログ収集の中断や非標準のフィールドフォーマットにより、SQL クエリが時間間隔を誤って計算し、検出漏れにつながる可能性があります。ログデータの完全性と一貫性を確保してください。
SQL 構文ドキュメント
SQL 構文の詳細については、「SQL 分析の構文と機能」をご参照ください。
脅威検出ルールの構成方法については、「脅威検出ルールを構成する」をご参照ください。