azure-kusto-irql

Par microsoft · azure-skills

Composez des requêtes IRQL (Incident Response Query Language) pour les investigations de cybersécurité Kusto. Traduit les questions de threat hunting en langage naturel en pipelines IRQL composables utilisant les fonctions Get_*, Extract_* et Enrich_*. QUAND : requête IRQL, security hunt, threat hunting KQL, incident response query, composition de pipeline de hunting, échecs de connexion, investigation de phishing, mouvement latéral, exécution de processus, événements de création de fichiers.

npx skills add https://github.com/microsoft/azure-skills --skill azure-kusto-irql

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 fonctions Enrich_*
  • 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 :

  1. 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
  2. Composabilité -- les petites fonctions s'enchaînent via | invoke pour construire des chasses complexes à partir d'étapes simples
  3. 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
  1. Commencez par un Sélecteur : Get_Event_Authentication, Get_Email, etc.
  2. Extrayez des champs dérivés : | invoke Extract_Email_Sender_Domain()
  3. Filtrez vers le signal : | where Result == "Failed Login"
  4. Enrichissez avec le contexte : | invoke Enrich_Username_Employee()
  5. 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 where aussi tôt que possible
  • Utilisez summarize pour les agrégations, project pour la sélection de colonnes finales
  • Terminez avec order by + take pour 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_user pour 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 .kql et suggérez l'extension VS Code Kusto ou ADX Web Explorer
  • Pour la visualisation graphique à partir de données IRQL, voir azure-kusto-graph et azure-kusto-irql-graph

Skills similaires