IRQL -- Incident Response Query Language
Composez des pipelines de fonctions IRQL à partir de blocs de construction selecteurs, extracteurs et enrichisseurs. IRQL encapsule les tables de sécurité brutes KQL derrière des fonctions composables révélant l'intention, afin que les analystes (et les LLM) puissent exprimer des chasses sans mémoriser les schémas, les emplacements de clusters ou les clés de jointure.
Activation Triggers
Utilisez cette skill quand l'utilisateur :
- Mentionne explicitement IRQL,
Get_*,Extract_*, ou les fonctionsEnrich_* - Dit « utiliser IRQL » ou « écrire une requête IRQL »
- Demande un pipeline de chasse composable utilisant des sélecteurs IRQL connus
Ne pas activer pour les requêtes de sécurité génériques (p. ex. « trouver les connexions échouées ») sauf si l'utilisateur demande explicitement IRQL. Routez-les vers azure-kusto à la place.
Pas un convertisseur langage naturel vers IRQL. Cette skill compose des pipelines de fonctions IRQL et peut traiter des requêtes basiques en langage naturel qui correspondent directement à des sélecteurs connus et des filtres simples. Pour la conversion générale NL-vers-KQL ou NL-vers-IRQL, utilisez une skill dédiée de génération de requêtes (disponible séparément).
Vérification Préalable des Fonctions IRQL
Avant de générer un pipeline, vérifiez qu'IRQL est disponible sur la base de données cible :
.show functions
| where Name startswith "Get_" or Name startswith "Extract_" or Name startswith "Enrich_"
| project Name
Si aucune fonction IRQL n'est trouvée, informez l'utilisateur qu'IRQL n'est pas déployé sur la base de données cible et suggérez d'utiliser azure-kusto pour les requêtes KQL brutes à la place. Les fonctions IRQL sont un prérequis -- cette skill ne déploie pas les sélecteurs IRQL de base.
Qu'est-ce qu'IRQL
IRQL est un dialecte basé sur les fonctions au-dessus de KQL. Il fournit :
- Schéma unifié -- les tables de sécurité disparates se projettent en noms de colonnes cohérents, indépendamment de la source de données sous-jacente
- Composabilité -- les petites fonctions s'enchaînent via
| invokepour construire des chasses complexes à partir d'étapes simples - Portabilité -- le même pipeline IRQL fonctionne sur différents clusters/bases de données ; seuls les primitives
Get_*doivent être réorientées
IRQL n'est pas un langage séparé. Ce sont des fonctions KQL que vous invoquez. Tout KQL valide fonctionne aux côtés des fonctions IRQL.
Déploiement d'IRQL
Les fonctions IRQL sont des fonctions KQL stockées (.create-or-alter function). Elles doivent déjà être déployées sur la base de données cible avant que cette skill puisse générer des pipelines.
Cluster exemple public (fonctions pré-déployées) :
- Cluster :
https://kc7001.eastus.kusto.windows.net - Bases de données :
ValdyTimes,JoJosHospital
Pour porter IRQL à un nouveau cluster/base de données, créez des sélecteurs Get_* qui projettent vos tables sources dans le schéma unifié (noms de colonnes ci-dessous), puis déployez les extracteurs et enrichisseurs. Les extracteurs et enrichisseurs fonctionnent sans modification tant que le schéma d'entrée correspond.
Catalogue des Fonctions
1. Sélecteurs -- Get_*
Retournent des vues projetées et unifiées par schéma des tables sources. Utilisez la forme minimale par défaut ; utilisez _All quand des colonnes supplémentaires sont nécessaires.
| Fonction | Colonnes |
|---|---|
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. Extracteurs -- Extract_*
Dérivent une nouvelle colonne d'une colonne existante. Invoquez après un sélecteur.
| Fonction | Colonne d'Entrée | Ajoute |
|---|---|---|
Extract_Email_Sender_Domain(T) |
EmailSender |
Domain |
Extract_Employee_Firstname(T) |
Name |
Firstname |
Extract_Event_Network_Domain(T) |
Url |
DomainName |
3. Enrichisseurs -- Enrich_*
Les aides left-join qui attachent le contexte d'une table associée.
| Fonction | Colonne Clé | Enrichit Avec |
|---|---|---|
Enrich_Event_Authentication_Username(T) |
Username |
Événements d'auth pour l'utilisateur |
Enrich_Ip_Employee(T) |
ClientIp |
Identité employé depuis IP |
Enrich_Username_Employee(T) |
Username |
Identité employé depuis username |
Enrich_Ip_Domain(T) |
ClientIp |
Domaines DNS résolus en IP |
Enrich_Ip_Event_NetworkOutbound(T) |
ClientIp |
Trafic sortant depuis IP |
Enrich_Ip_Network_Connection(T) |
ClientIp |
Flux réseau depuis IP |
4. Enrichissement Externe
| Fonction | Source | Prérequis |
|---|---|---|
Enrich_Sha256_VirusTotal(T) |
Rapport de fichier VirusTotal | Clé API + politique de callout |
Get_CISA_KEV() / Enrich_CISA_KEV(T) |
Catalogue CISA KEV | Politique de callout |
Règles de Composition
Selector -> Extract -> Filter -> Enrich -> Summarize/Project
- Commencez par un Sélecteur :
Get_Event_Authentication,Get_Email, etc. - Extrayez des champs dérivés :
| invoke Extract_Email_Sender_Domain() - Filtrez vers le signal :
| where Result == "Failed Login" - Enrichissez avec le contexte :
| invoke Enrich_Username_Employee() - Résumez / projetez la réponse
Toujours faire un pipe (|) entre les étapes. Les extracteurs et enrichisseurs utilisent | invoke FunctionName().
Directives de Génération de Requêtes
- Utilisez le sélecteur minimal sauf si des colonnes supplémentaires sont nécessaires -> utilisez
_All - Enchaînez les extracteurs avant les enrichisseurs (les extracteurs ajoutent des colonnes que les enrichisseurs peuvent utiliser comme clé)
- Placez les filtres
whereaussi tôt que possible - Utilisez
summarizepour les agrégations,projectpour la sélection de colonnes finales - Terminez avec
order by+takepour limiter la sortie
Exemples
Pour des invites supplémentaires et des exemples détaillés, voir references/EXAMPLES.md.
Détection de force brute
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
Triage de phishing par ancienneté du destinataire
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
Pivot post-exploitation depuis un indicateur
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
Trafic sortant suspect enrichi avec identité
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
Anomalie d'authentification IP externe
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
Outils MCP Utilisés
| Outil | Objectif |
|---|---|
kusto_query |
Exécuter des pipelines IRQL contre une base de données Kusto |
kusto_table_schema_get |
Découvrir les tables et colonnes disponibles |
kusto_cluster_list |
Lister les clusters ADX disponibles |
kusto_database_list |
Lister les bases de données dans un cluster |
Ouverture des Requêtes dans Kusto Explorer (Windows Uniquement)
Fonctionnalité de commodité optionnelle. Le flux de travail par défaut est de sortir le KQL dans le chat et de laisser l'utilisateur le copier manuellement dans Kusto Explorer ou l'extension VS Code Kusto. Le lancement automatique est exclusif à l'acceptation.
Toujours sortir la requête KQL complète dans la réponse du chat avec l'étape 1 (connexion) et l'étape 2 (requête) clairement indiquées :
// 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>
Si l'utilisateur demande d'enregistrer ou d'ouvrir dans Kusto Explorer, suivez la procédure dans references/KUSTO_EXPLORER_LAUNCH.md. Règles clés :
- Utilisez
ask_userpour confirmer avant d'écrire des fichiers ou de lancer des exécutables - Affichez le contenu des fichiers dans le chat afin que l'utilisateur puisse examiner avant d'ouvrir
- Ne jamais utiliser l'interpolation de shell ou here-strings — écrire des fichiers via
Set-Content/Add-Content - Ne jamais coder les requêtes dans les URLs du navigateur
- Sur macOS/Linux, enregistrez le fichier
.kqlet suggérez l'extension VS Code Kusto ou ADX Web Explorer - Pour la visualisation graphique à partir de données IRQL, voir
azure-kusto-graphetazure-kusto-irql-graph