IRQL -- Lenguaje de Consulta para Respuesta a Incidentes
Componga pipelines de funciones IRQL a partir de bloques de construcción selectores, extractores y enriquecedores. IRQL envuelve tablas KQL de seguridad sin procesar detrás de funciones componibles que revelan la intención, permitiendo a los analistas (y LLMs) expresar búsquedas sin memorizar esquemas, ubicaciones de clústeres o claves de unión.
Disparadores de Activación
Use este skill cuando el usuario:
- Mencione explícitamente IRQL, funciones
Get_*,Extract_*oEnrich_* - Diga "usa IRQL" o "escribe una consulta IRQL"
- Solicite un pipeline de búsqueda componible usando selectores IRQL conocidos
No active para consultas de seguridad genéricas (ej. "encuentra inicios de sesión fallidos") a menos que el usuario pida explícitamente IRQL. Enrute esas al skill azure-kusto.
No es un convertidor de lenguaje natural a IRQL. Este skill compone pipelines de funciones IRQL y puede manejar solicitudes básicas en lenguaje natural que se asignen directamente a selectores conocidos y filtros simples. Para conversión general de NL a KQL o NL a IRQL, use un skill de generación de consultas dedicado (disponible por separado).
Verificación Previa de Funciones IRQL
Antes de generar un pipeline, verifique que IRQL esté disponible en la base de datos destino:
.show functions
| where Name startswith "Get_" or Name startswith "Extract_" or Name startswith "Enrich_"
| project Name
Si no se encuentran funciones IRQL, informe al usuario que IRQL no está desplegado en la base de datos destino y sugiera usar azure-kusto para consultas KQL sin procesar. Las funciones IRQL son un requisito previo -- este skill no despliega los selectores base de IRQL.
Qué es IRQL
IRQL es un dialecto basado en funciones sobre KQL. Proporciona:
- Esquema unificado -- tablas de seguridad dispares proyectan nombres de columna consistentes independientemente de la fuente de datos subyacente
- Componibilidad -- funciones pequeñas se encadenan mediante
| invokepara construir búsquedas complejas a partir de pasos simples - Portabilidad -- el mismo pipeline IRQL funciona en diferentes clústeres/bases de datos; solo los primitivos
Get_*necesitan ser reorientados
IRQL no es un lenguaje separado. Son funciones KQL que se invocan. Cualquier KQL válido funciona junto con las funciones IRQL.
Despliegue de IRQL
Las funciones IRQL son funciones KQL almacenadas (.create-or-alter function). Deben estar ya desplegadas en la base de datos destino antes de que este skill pueda generar pipelines.
Clúster público de ejemplo (funciones pre-desplegadas):
- Clúster:
https://kc7001.eastus.kusto.windows.net - Bases de datos:
ValdyTimes,JoJosHospital
Para portar IRQL a un nuevo clúster/base de datos, cree selectores Get_* que proyecten sus tablas fuente en el esquema unificado (nombres de columna abajo), luego despliegue extractores y enriquecedores. Los extractores y enriquecedores funcionan sin cambios siempre que el esquema de entrada coincida.
Catálogo de Funciones
1. Selectores -- Get_*
Devuelven vistas proyectadas y unificadas en esquema de tablas fuente. Use la forma mínima por defecto; use _All cuando se necesiten columnas adicionales.
| Función | Columnas |
|---|---|
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. Extractores -- Extract_*
Derivan una nueva columna a partir de una existente. Se invocan después de un selector.
| Función | Columna de Entrada | Añade |
|---|---|---|
Extract_Email_Sender_Domain(T) | EmailSender | Domain |
Extract_Employee_Firstname(T) | Name | Firstname |
Extract_Event_Network_Domain(T) | Url | DomainName |
3. Enriquecedores -- Enrich_*
Ayudantes de left-join que adjuntan contexto de una tabla relacionada.
| Función | Columna Clave | Enriquece Con |
|---|---|---|
Enrich_Event_Authentication_Username(T) | Username | Eventos de autenticación para el usuario |
Enrich_Ip_Employee(T) | ClientIp | Identidad del empleado desde IP |
Enrich_Username_Employee(T) | Username | Identidad del empleado desde nombre de usuario |
Enrich_Ip_Domain(T) | ClientIp | Dominios DNS resueltos a IP |
Enrich_Ip_Event_NetworkOutbound(T) | ClientIp | Red saliente desde IP |
Enrich_Ip_Network_Connection(T) | ClientIp | Flujos de red desde IP |
4. Enriquecedores Externos
| Función | Fuente | Requisito |
|---|---|---|
Enrich_Sha256_VirusTotal(T) | Informe de archivo de VirusTotal | Clave API + política de callout |
Get_CISA_KEV() / Enrich_CISA_KEV(T) | Catálogo CISA KEV | Política de callout |
Reglas de Composición
Selector -> Extract -> Filter -> Enrich -> Summarize/Project
- Comience con un Selector:
Get_Event_Authentication,Get_Email, etc. - Extraiga campos derivados:
| invoke Extract_Email_Sender_Domain() - Filtre la señal:
| where Result == "Failed Login" - Enriquezca con contexto:
| invoke Enrich_Username_Employee() - Resuma / proyecte la respuesta
Use siempre pipe (|) entre pasos. Los extractores y enriquecedores usan | invoke FunctionName().
Directrices de Generación de Consultas
- Use el selector mínimo a menos que se necesiten columnas adicionales -> entonces
_All - Encadene extractores antes que enriquecedores (los extractores añaden columnas que los enriquecedores pueden usar como clave)
- Coloque los filtros
wherelo más temprano posible - Use
summarizepara agregaciones,projectpara selección final de columnas - Termine con
order by+takepara limitar la salida
Ejemplos
Para ejemplos adicionales y prompts trabajados, consulte references/EXAMPLES.md.
Detección de fuerza bruta
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
Triaje de phishing por antigüedad del destinatario
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
Pivote post-explotación desde un indicador
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
Tráfico saliente sospechoso enriquecido con identidad
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
Anomalía de autenticación desde IP externa
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
Herramientas MCP Utilizadas
| Herramienta | Propósito |
|---|---|
kusto_query | Ejecutar pipelines IRQL contra una base de datos Kusto |
kusto_table_schema_get | Descubrir tablas y columnas disponibles |
kusto_cluster_list | Listar clústeres ADX disponibles |
kusto_database_list | Listar bases de datos en un clúster |
Abrir Consultas en Kusto Explorer (Solo Windows)
Característica de conveniencia opcional. El flujo de trabajo predeterminado es mostrar el KQL en el chat y permitir que el usuario lo copie manualmente a Kusto Explorer o la extensión Kusto de VS Code. El auto-lanzamiento solo es opt-in.
Siempre muestre la consulta KQL completa en la respuesta del chat con el Paso 1 (conectar) y el Paso 2 (consultar) claramente etiquetados:
// Paso 1: Conéctese a su clúster (omitir si ya está conectado)
// Ejemplo: descomente para conectar al clúster de entrenamiento KC7
// #connect cluster('kc7001.eastus.kusto.windows.net').database('ValdyTimes')
// O reemplace con su propio clúster:
// #connect cluster('<YOUR_CLUSTER>').database('<YOUR_DATABASE>')
// Paso 2: Ejecute la consulta a continuación
<KQL_QUERY>
Si el usuario pide guardar o abrir en Kusto Explorer, siga el procedimiento en references/KUSTO_EXPLORER_LAUNCH.md. Reglas clave:
- Use
ask_userpara confirmar antes de escribir archivos o lanzar ejecutables - Muestre el contenido del archivo en el chat para que el usuario lo revise antes de abrirlo
- Nunca use interpolación de shell o here-strings — escriba archivos mediante
Set-Content/Add-Content - Nunca codifique consultas en URLs del navegador
- En macOS/Linux, guarde el archivo
.kqly sugiera la extensión Kusto de VS Code o ADX Web Explorer - Para visualización de gráficos a partir de datos IRQL, consulte
azure-kusto-graphyazure-kusto-irql-graph