azure-kusto-irql について
KQL 上で IRQL パイプラインを組み立てる、セキュリティアナリスト向けのスキルです。統一スキーマのセレクター、抽出器、エンリッチャーを組み合わせますが、対象データベースへの IRQL 関数のデプロイが必要です。
主な機能
- 01セレクター・抽出器・エンリッチャーの連結
- 02セキュリティテーブル間のスキーマ統一
- 03フィルター、集計、射影の適用
- 04IRQL 関数のデプロイ状況の確認
活用シーン
- 01KQL での組み合わせ可能なセキュリティ調査
- 02認証イベントへの従業員情報の付加
- 03メール、ネットワーク、プロセス活動の調査
MCP 対応
Kusto MCP ツールを使って IRQL パイプラインを実行し、クラスター、データベース、テーブル、スキーマ情報を確認します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ microsoft/ azure-skills --skill azure-kusto-irqlインストール後、Claude Code で/azure-kusto-irqlを入力して読み込まれたか確認します。
同梱ファイルreferences/EXAMPLES.mdreferences/KUSTO_EXPLORER_LAUNCH.md
詳細
IRQL -- インシデント対応クエリ言語
セレクター、抽出器、エンリッチャーのビルディングブロックを組み合わせて、IRQL の関数パイプラインを作成します。IRQL は、意図が分かりやすく組み合わせ可能な関数で生の KQL セキュリティテーブルをラップするため、アナリスト(および LLM)は、スキーマ、クラスターの場所、結合キーを記憶しなくてもハンティングを表現できます。
アクティベーションのトリガー
次の場合にこのスキルを使用します。
- ユーザーが IRQL、
Get_*、Extract_*、またはEnrich_*関数に明示的に言及した場合 - 「IRQL を使って」または「IRQL クエリを書いて」と依頼した場合
- 既知の IRQL セレクターを使った、組み合わせ可能なハンティングパイプラインを求められた場合
一般的なセキュリティクエリ(例:「ログイン失敗を見つけて」)では、ユーザーが IRQL を明示的に求めない限り、このスキルを有効にしないでください。その場合は、代わりに azure-kusto を使用してください。
自然言語から IRQL への変換ツールではありません。 このスキルは IRQL 関数パイプラインを組み立てます。また、既知のセレクターや単純なフィルターに直接対応する基本的な自然言語の依頼を処理する場合があります。一般的な自然言語から KQL または IRQL への変換には、専用のクエリ生成スキル(別途利用可能)を使用してください。
IRQL 関数の事前確認
パイプラインを生成する前に、対象データベースで IRQL が利用できることを確認してください。
.show functions
| where Name startswith "Get_" or Name startswith "Extract_" or Name startswith "Enrich_"
| project Name
IRQL 関数が見つからない場合は、対象データベースに IRQL がデプロイされていないことをユーザーに伝え、代わりに生の KQL クエリには azure-kusto を使うよう提案してください。IRQL 関数は前提条件です。このスキルは基本 IRQL セレクターをデプロイしません。
IRQL とは
IRQL は、KQL を基盤とする関数ベースの方言です。次の機能を提供します。
- 統一スキーマ -- 元のデータソースに関係なく、異なるセキュリティテーブルを一貫した列名に投影します
- 組み合わせ可能性 -- 小さな関数を
| invokeで連結し、単純な手順から複雑なハンティングを構築できます - 移植性 -- 同じ IRQL パイプラインを異なるクラスターやデータベースで使用できます。再設定が必要なのは
Get_*プリミティブのみです
IRQL は独立した言語ではありません。呼び出して使用する KQL 関数です。有効な KQL はすべて IRQL 関数と併用できます。
IRQL のデプロイ
IRQL 関数は、保存された KQL 関数(.create-or-alter function)です。このスキルでパイプラインを生成する前に、対象データベースにデプロイしておく必要があります。
公開サンプルクラスター(関数はデプロイ済み):
- クラスター:
https://kc7001.eastus.kusto.windows.net - データベース:
ValdyTimes、JoJosHospital
IRQL を新しいクラスターやデータベースに移植するには、ソーステーブルを統一スキーマ(列名は以下を参照)に投影する Get_* セレクターを作成し、その後、抽出器とエンリッチャーをデプロイします。入力スキーマが一致していれば、抽出器とエンリッチャーは変更せずに動作します。
関数カタログ
1. セレクター -- Get_*
ソーステーブルを射影し、スキーマを統一したビューを返します。デフォルトでは最小限の形式を使用し、追加の列が必要な場合は _All を使用します。
| 関数 | 列 |
|---|---|
Get_Event_Authentication | EnvTime、Hostname、ClientIp、Username、Result |
Get_Event_Authentication_All | + Description、UserAgent、PasswordHash |
Get_Email | EnvTime、EmailSender、EmailRecipient、Subject、Url |
Get_Email_All | + ReplyTo、Verdict |
Get_Employees | Name、ClientIp、Email、Username、Hostname、Role |
Get_Employees_All | + HireDate、UserAgent、Domain |
Get_Event_FileCreation | EnvTime、Hostname、Filename、Path |
Get_Event_FileCreation_All | + Username、Sha256、ProcessName |
Get_Event_NetworkInbound | EnvTime、ClientIp、Url |
Get_Event_NetworkInbound_All | + Method、UserAgent、StatusCode |
Get_Event_NetworkOutbound | EnvTime、ClientIp、Url |
Get_Event_NetworkOutbound_All | + Method、UserAgent |
Get_Dns_All | EnvTime、Domain、ClientIp |
Get_Event_Process | EnvTime、ProcessCommandLine、ProcessName、Hostname、Username |
Get_Event_Process_All | + ParentProcessName、ParentProcessHash、ProcessHash |
Get_SecurityAlerts_All | EnvTime、AlertType、Severity、Description、Indicators |
Get_Network_Connection_All | EnvTime、SourceIp、SourcePort、DestinationIp、DestinationPort、Protocol、Bytes |
2. 抽出関数 -- Extract_*
既存の列から新しい列を導出します。セレクターの後に呼び出します。
| 関数 | 入力列 | 追加する列 |
|---|---|---|
Extract_Email_Sender_Domain(T) | EmailSender | Domain |
Extract_Employee_Firstname(T) | Name | Firstname |
Extract_Event_Network_Domain(T) | Url | DomainName |
3. エンリッチャー -- Enrich_*
関連テーブルのコンテキストを付加する、左外部結合のヘルパーです。
| 関数 | キー列 | 付加する情報 |
|---|---|---|
Enrich_Event_Authentication_Username(T) | Username | ユーザーの認証イベント |
Enrich_Ip_Employee(T) | ClientIp | IP から特定した従業員の身元情報 |
Enrich_Username_Employee(T) | Username | ユーザー名から特定した従業員の身元情報 |
Enrich_Ip_Domain(T) | ClientIp | IP に解決された DNS ドメイン |
Enrich_Ip_Event_NetworkOutbound(T) | ClientIp | IP からのアウトバウンドネットワーク通信 |
Enrich_Ip_Network_Connection(T) | ClientIp | IP からのネットワークフロー |
4. 外部エンリッチメント
| 関数 | ソース | 要件 |
|---|---|---|
Enrich_Sha256_VirusTotal(T) | VirusTotal のファイルレポート | API キー + コールアウトポリシー |
Get_CISA_KEV() / Enrich_CISA_KEV(T) | CISA KEV カタログ | コールアウトポリシー |
クエリの組み立てルール
Selector -> Extract -> Filter -> Enrich -> Summarize/Project
- セレクターから開始する:
Get_Event_Authentication、Get_Emailなど - 派生フィールドを抽出する:
| invoke Extract_Email_Sender_Domain() - シグナルに絞り込む:
| where Result == "Failed Login" - コンテキストを付加する:
| invoke Enrich_Username_Employee() - 回答を集計/射影する
各ステップの間には必ずパイプ(|)を入れます。抽出関数とエンリッチャーは | invoke FunctionName() を使用します。
クエリ生成のガイドライン
- 追加の列が必要でない限り、最小限のセレクターを使用します。必要な場合は
_Allを使用します。 - エンリッチャーがキーとして使用する列を抽出関数で追加できるよう、抽出関数をエンリッチャーより前につなげます。
whereフィルターはできるだけ早い段階に配置します。- 集計には
summarize、最終的な列の選択にはprojectを使用します。 - 出力を制限するため、最後に
order byとtakeを指定します。
例
追加のプロンプトや詳しい使用例については、references/EXAMPLES.md を参照してください。
ブルートフォースの検出
Get_Event_Authentication
| where Result == "Failed Login"
| summarize FailedCount = count() by Username
| where FailedCount > 19
| invoke Enrich_Username_Employee()
| project Username, Name, Role, Email, FailedCount
| order by FailedCount desc
受信者の職位に基づくフィッシングのトリアージ
Get_Email
| invoke Extract_Email_Sender_Domain()
| project EnvTime, EmailSender, Domain, Username = EmailRecipient, Subject, Url
| invoke Enrich_Username_Employee()
| extend Seniority = case(
Role has_any ("CEO", "Chief", "Director", "VP", "President"), 3,
Role has_any ("Manager", "Lead", "Senior"), 2,
1)
| summarize
TotalEmails = count(),
SeniorityScore = sum(Seniority),
Recipients = make_set(Name, 50),
DistinctRecipients = dcount(Username)
by Domain
| where DistinctRecipients >= 2
| order by SeniorityScore desc
| take 20
インジケーターからの侵入後のピボット
let victims =
Get_Event_FileCreation_All
| where Filename has "<INDICATOR>"
| distinct Hostname;
Get_Event_Process
| where Hostname in (victims)
| where ProcessCommandLine has_any ("rundll32", "regsvr32", "powershell", "systeminfo")
| project EnvTime, Hostname, Username, ProcessName, ProcessCommandLine
| order by EnvTime asc
身元情報を付加した不審なアウトバウンド通信
Get_Event_NetworkOutbound
| invoke Extract_Event_Network_Domain()
| where DomainName has_any ("<SUSPICIOUS_DOMAIN_1>", "<SUSPICIOUS_DOMAIN_2>")
| invoke Enrich_Ip_Employee()
| project EnvTime, Name, Role, DomainName, Url, ClientIp
| order by EnvTime desc
外部 IP による認証の異常
Get_Event_Authentication_All
| where not(ClientIp startswith "10.") and not(ClientIp startswith "192.168.")
| summarize
Attempts = count(),
Failures = countif(Result == "Failed Login"),
Users = make_set(Username)
by ClientIp
| order by Failures desc
| take 20
使用する MCP ツール
| ツール | 目的 |
|---|---|
kusto_query | Kusto データベースに対して IRQL パイプラインを実行します |
kusto_table_schema_get | 利用可能なテーブルと列を確認します |
kusto_cluster_list | 利用可能な ADX クラスターを一覧表示します |
kusto_database_list | クラスター内のデータベースを一覧表示します |
Kusto Explorer でクエリを開く(Windows のみ)
任意の便利機能です。 デフォルトのワークフローでは、チャットに KQL を出力し、ユーザーが手動で Kusto Explorer または VS Code Kusto 拡張機能にコピーします。自動起動はオプトインした場合のみ実行されます。
Step 1(接続)と Step 2(クエリ)を明確にラベル付けし、チャットの応答には常に KQL クエリ全体を出力してください。
// Step 1: Connect to your cluster (skip if already connected)
// Example: uncomment to connect to the KC7 training cluster
// #connect cluster('kc7001.eastus.kusto.windows.net').database('ValdyTimes')
// Or replace with your own cluster:
// #connect cluster('<YOUR_CLUSTER>').database('<YOUR_DATABASE>')
// Step 2: Run the query below
<KQL_QUERY>
ユーザーが Kusto Explorer での保存または起動を依頼した場合は、references/KUSTO_EXPLORER_LAUNCH.md の手順に従ってください。主なルールは次のとおりです。
- ファイルへの書き込みや実行ファイルの起動の前に、
ask_userを使って確認します - 開く前に、ユーザーが確認できるようファイルの内容をチャットに表示します
- シェル補間やヒアストリングは使用せず、
Set-Content/Add-Contentを使ってファイルを書き込みます - クエリをブラウザーの URL にエンコードしません
- macOS/Linux では、
.kqlファイルを保存し、VS Code Kusto 拡張機能または ADX Web Explorer を提案します - IRQL データからグラフを可視化するには、
azure-kusto-graphおよびazure-kusto-irql-graphを参照してください