IRQL -- Incident Response Query Language
Componha pipelines de funções IRQL a partir de blocos de construção: seletores, extratores e enriquecedores. O IRQL encapsula tabelas brutas de segurança do KQL por trás de funções componíveis que revelam a intenção, permitindo que analistas (e LLMs) expressem caças sem memorizar esquemas, localizações de clusters ou chaves de junção.
Gatilhos de Ativação
Use esta skill quando o usuário:
- Mencionar explicitamente IRQL, funções
Get_*,Extract_*ouEnrich_* - Disse "use IRQL" ou "escreva uma consulta IRQL"
- Solicitar um pipeline de caça componível usando seletores IRQL conhecidos
Não ative para consultas de segurança genéricas (ex.: "encontre logins com falha") a menos que o usuário explicitamente peça IRQL. Encaminhe essas para azure-kusto.
Não é um conversor de linguagem natural para IRQL. Esta skill compõe pipelines de funções IRQL e pode lidar com solicitações básicas em linguagem natural que mapeiam diretamente para seletores conhecidos e filtros simples. Para conversão geral de NL para KQL ou NL para IRQL, use uma skill dedicada de geração de consultas (disponível separadamente).
Pré-verificação de Funções IRQL
Antes de gerar um pipeline, verifique se o IRQL está disponível no banco de dados de destino:
.show functions
| where Name startswith "Get_" or Name startswith "Extract_" or Name startswith "Enrich_"
| project Name
Se nenhuma função IRQL for encontrada, informe ao usuário que o IRQL não está implantado no banco de dados de destino e sugira usar azure-kusto para consultas KQL brutas. As funções IRQL são um pré-requisito -- esta skill não implanta seletores IRQL base.
O que é IRQL
IRQL é um dialeto baseado em funções sobre o KQL. Ele fornece:
- Esquema unificado -- tabelas de segurança díspares projetam colunas consistentes independentemente da fonte de dados subjacente
- Componibilidade -- funções pequenas encadeiam via
| invokepara construir caças complexas a partir de etapas simples - Portabilidade -- o mesmo pipeline IRQL funciona em diferentes clusters/bancos de dados; apenas os primitivos
Get_*precisam ser redirecionados
IRQL não é uma linguagem separada. São funções KQL que você invoca. Qualquer KQL válido funciona junto com funções IRQL.
Implantando IRQL
As funções IRQL são funções KQL armazenadas (.create-or-alter function). Elas já devem estar implantadas no banco de dados de destino antes que esta skill possa gerar pipelines.
Cluster de exemplo público (funções pré-implantadas):
- Cluster:
https://kc7001.eastus.kusto.windows.net - Bancos de dados:
ValdyTimes,JoJosHospital
Para portar IRQL para um novo cluster/banco de dados, crie seletores Get_* que projetem suas tabelas de origem no esquema unificado (nomes de colunas abaixo) e, em seguida, implante extratores e enriquecedores. Os extratores e enriquecedores funcionam sem alteração, desde que o esquema de entrada corresponda.
Catálogo de Funções
1. Seletores -- Get_*
Retornam visualizações projetadas e com esquema unificado das tabelas de origem. Use o formulário mínimo por padrão; use _All quando colunas extras forem necessárias.
| Função | Colunas |
|---|---|
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. Extratores -- Extract_*
Derivam uma nova coluna de uma existente. Invocar após um seletor.
| Função | Coluna de Entrada | Adiciona |
|---|---|---|
Extract_Email_Sender_Domain(T) | EmailSender | Domain |
Extract_Employee_Firstname(T) | Name | Firstname |
Extract_Event_Network_Domain(T) | Url | DomainName |
3. Enriquecedores -- Enrich_*
Auxiliares de left-join que anexam contexto de uma tabela relacionada.
| Função | Coluna Chave | Enriquece com |
|---|---|---|
Enrich_Event_Authentication_Username(T) | Username | Eventos de autenticação para o usuário |
Enrich_Ip_Employee(T) | ClientIp | Identidade do funcionário a partir do IP |
Enrich_Username_Employee(T) | Username | Identidade do funcionário a partir do nome de usuário |
Enrich_Ip_Domain(T) | ClientIp | Domínios DNS resolvidos para IP |
Enrich_Ip_Event_NetworkOutbound(T) | ClientIp | Rede de saída a partir do IP |
Enrich_Ip_Network_Connection(T) | ClientIp | Fluxos de rede a partir do IP |
4. Enriquecimento Externo
| Função | Fonte | Requisito |
|---|---|---|
Enrich_Sha256_VirusTotal(T) | Relatório de arquivo VirusTotal | Chave de API + política de callout |
Get_CISA_KEV() / Enrich_CISA_KEV(T) | Catálogo CISA KEV | Política de callout |
Regras de Composição
Seletor -> Extrator -> Filtro -> Enriquecedor -> Sumarização/Project
- Comece com um Seletor:
Get_Event_Authentication,Get_Email, etc. - Extraia campos derivados:
| invoke Extract_Email_Sender_Domain() - Filtre para o sinal:
| where Result == "Failed Login" - Enriqueça com contexto:
| invoke Enrich_Username_Employee() - Sumarize / projete a resposta
Sempre use pipe (|) entre as etapas. Extratores e enriquecedores usam | invoke FunctionName().
Diretrizes de Geração de Consultas
- Use o seletor mínimo a menos que colunas extras sejam necessárias -> então use
_All - Encadeie extratores antes de enriquecedores (extratores adicionam colunas que os enriquecedores podem usar como chave)
- Coloque filtros
whereo mais cedo possível - Use
summarizepara agregações,projectpara seleção final de colunas - Termine com
order by+takepara limitar a saída
Exemplos
Para prompts adicionais e exemplos trabalhados, veja references/EXAMPLES.md.
Detecção de força 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
Triagem de phishing por senioridade do destinatário
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 pós-exploração a partir de um 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áfego de saída suspeito enriquecido com identidade
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
Anomalia de autenticação de IP externo
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
Ferramentas MCP Utilizadas
| Ferramenta | Propósito |
|---|---|
kusto_query | Executar pipelines IRQL em um banco de dados Kusto |
kusto_table_schema_get | Descobrir tabelas e colunas disponíveis |
kusto_cluster_list | Listar clusters ADX disponíveis |
kusto_database_list | Listar bancos de dados em um cluster |
Abrindo Consultas no Kusto Explorer (Somente Windows)
Recurso opcional de conveniência. O fluxo de trabalho padrão é exibir o KQL no chat e deixar o usuário copiá-lo para o Kusto Explorer ou extensão Kusto do VS Code manualmente. O auto-lançamento é opt-in.
Sempre exiba a consulta KQL completa na resposta do chat com a Etapa 1 (conectar) e Etapa 2 (consultar) claramente identificadas:
// 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>
Se o usuário pedir para salvar ou abrir no Kusto Explorer, siga o procedimento em references/KUSTO_EXPLORER_LAUNCH.md. Regras importantes:
- Use
ask_userpara confirmar antes de escrever arquivos ou executar executáveis - Exiba o conteúdo do arquivo no chat para que o usuário possa revisar antes de abrir
- Nunca use interpolação de shell ou here-strings — escreva arquivos via
Set-Content/Add-Content - Nunca codifique consultas em URLs de navegador
- No macOS/Linux, salve o arquivo
.kqle sugira a extensão Kusto do VS Code ou o ADX Web Explorer - Para visualização de grafos a partir de dados IRQL, veja
azure-kusto-grapheazure-kusto-irql-graph