IRQL -- Langage de Requête pour la Réponse aux Incidents
Composer des pipelines de fonctions IRQL à partir de blocs de construction sélecteurs, extracteurs et enrichisseurs. IRQL encapsule les tables de sécurité KQL brutes derrière des fonctions composables qui révèlent l'intention, permettant aux analystes (et aux LLM) d'exprimer des chasses sans mémoriser les schémas, les emplacements de cluster ou les clés de jointure.
Déclencheurs d'Activation
Utilisez cette compétence lorsque l'utilisateur :
- Mentionne explicitement IRQL, les fonctions
Get_*,Extract_*ouEnrich_* - Dit "utilise IRQL" ou "écris une requête IRQL"
- Demande un pipeline de chasse composable utilisant des sélecteurs IRQL connus
N'activez pas pour des requêtes de sécurité génériques (par exemple "trouver les échecs de connexion") à moins que l'utilisateur ne demande explicitement IRQL. Redirigez-les vers azure-kusto à la place.
Ce n'est pas un convertisseur langage-naturel-vers-IRQL. Cette compétence compose des pipelines de fonctions IRQL et peut gérer des requêtes de base en langage naturel qui correspondent directement à des sélecteurs connus et des filtres simples. Pour une conversion générale NL-vers-KQL ou NL-vers-IRQL, utilisez une compétence 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 compétence ne déploie pas les sélecteurs IRQL de base.
Ce qu'est IRQL
IRQL est un dialecte basé sur des fonctions au-dessus de KQL. Il fournit :
- Schéma unifié -- les tables de sécurité disparates projettent des noms de colonnes cohérents, quelle que soit la source de données sous-jacente
- Composabilité -- de 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 ; seules les primitives
Get_*doivent être re-pointé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 compétence puisse générer des pipelines.
Exemple de cluster public (fonctions pré-déployées) :
- Cluster :
https://kc7001.eastus.kusto.windows.net - Bases de données :
ValdyTimes,JoJosHospital
Pour porter IRQL vers 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 changement tant que le schéma d'entrée correspond.
Catalogue de Fonctions
1. Sélecteurs -- Get_*
Renvoient des vues projetées et unifiées par schéma des tables sources. Utilisez la forme minimale par défaut ; utilisez _All lorsque 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 à partir d'une 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_*
Aides de jointure gauche qui attachent le contexte d'une table associée.
| Fonction | Colonne Clé | Enrichit Avec |
|---|---|---|
Enrich_Event_Authentication_Username(T) | Username | Événements d'authentification pour l'utilisateur |
Enrich_Ip_Employee(T) | ClientIp | Identité de l'employé à partir de l'IP |
Enrich_Username_Employee(T) | Username | Identité de l'employé à partir du nom d'utilisateur |
Enrich_Ip_Domain(T) | ClientIp | Domaines DNS résolus en IP |
Enrich_Ip_Event_NetworkOutbound(T) | ClientIp | Réseau sortant depuis l'IP |
Enrich_Ip_Network_Connection(T) | ClientIp | Flux réseau depuis l'IP |
4. Enrichissement Externe
| Fonction | Source | Prérequis |
|---|---|---|
Enrich_Sha256_VirusTotal(T) | Rapport de fichier VirusTotal | Clé API + politique d'appel (callout policy) |
Get_CISA_KEV() / Enrich_CISA_KEV(T) | Catalogue CISA KEV | Politique d'appel |
Règles de Composition
Sélecteur -> Extracteur -> Filtre -> Enrichisseur -> Résumer/Projeter
- Commencez par un Sélecteur :
Get_Event_Authentication,Get_Email, etc. - Extrayez les champs dérivés :
| invoke Extract_Email_Sender_Domain() - Filtrez le signal :
| where Result == "Failed Login" - Enrichissez avec du contexte :
| invoke Enrich_Username_Employee() - Résumez / projetez la réponse
Utilisez toujours le tube (|) entre les étapes. Les extracteurs et enrichisseurs utilisent | invoke NomFonction().
Directives de Génération de Requêtes
- Utilisez le sélecteur minimal sauf si des colonnes supplémentaires sont nécessaires -> alors utilisez
_All - Enchaînez les extracteurs avant les enrichisseurs (les extracteurs ajoutent des colonnes sur lesquelles les enrichisseurs peuvent se baser)
- Placez les filtres
wherele plus tôt possible - Utilisez
summarizepour les agrégations,projectpour la sélection finale des colonnes - Terminez par
order by+takepour limiter la sortie
Exemples
Pour des exemples supplémentaires et des invites travaillées, consultez references/EXAMPLES.md.
Détection par 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 du 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 à partir d'un indicateur
let victims =
Get_Event_FileCreation_All
| where Filename has "<INDICATEUR>"
| 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 l'identité
Get_Event_NetworkOutbound
| invoke Extract_Event_Network_Domain()
| where DomainName has_any ("<DOMAINE_SUSPECT_1>", "<DOMAINE_SUSPECT_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 sur 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 consiste à afficher le KQL dans le chat et à laisser l'utilisateur le copier dans Kusto Explorer ou l'extension Kusto de VS Code manuellement. Le lancement automatique est uniquement sur option.
Affichez toujours la requête KQL complète dans la réponse du chat avec les étapes 1 (connexion) et 2 (requête) clairement étiquetées :
// Étape 1 : Connectez-vous à votre cluster (ignorer si déjà connecté)
// Exemple : décommentez pour vous connecter au cluster d'entraînement KC7
// #connect cluster('kc7001.eastus.kusto.windows.net').database('ValdyTimes')
// Ou remplacez par votre propre cluster :
// #connect cluster('<VOTRE_CLUSTER>').database('<VOTRE_BASE_DE_DONNEES>')
// Étape 2 : Exécutez la requête ci-dessous
<REQUETE_KQL>
Si l'utilisateur demande à sauvegarder ou 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 du fichier dans le chat pour que l'utilisateur puisse le vérifier avant ouverture
- N'utilisez jamais d'interpolation shell ou de here-strings — écrivez les fichiers via
Set-Content/Add-Content - N'encodez jamais les requêtes dans les URL du navigateur
- Sur macOS/Linux, enregistrez le fichier
.kqlet suggérez l'extension Kusto de VS Code ou ADX Web Explorer - Pour la visualisation de graphes à partir de données IRQL, voir
azure-kusto-graphetazure-kusto-irql-graph