Migrar as regras de detecção do Splunk para o Microsoft Sentinel

As regras de detecção do Splunk são componentes de gerenciamento de eventos e informações de segurança (SIEM) e podem ser comparadas às regras de análise no Microsoft Sentinel. Este artigo aborda os principais conceitos para identificar, comparar e migrar essas regras para o Microsoft Sentinel. A melhor maneira de começar é utilizando a experiência de migração de SIEM, que identifica automaticamente as regras de análise prontas para uso (OOTB) para tradução automática.

Se você quiser migrar sua implantação de Observabilidade do Splunk, saiba mais sobre como migrar do Splunk para os Logs do Azure Monitor.

Regras de auditoria

O Microsoft Sentinel usa a análise de aprendizado de máquina para criar incidentes acionáveis e de alta fidelidade. Algumas das detecções existentes no Splunk podem ser redundantes no Microsoft Sentinel. Examine essas considerações à medida que identifica as regras de detecção existentes.

  • Selecione casos de uso que justifiquem a migração da regra, considerando a prioridade e a eficiência dos negócios.
  • Verifique se você entende os tipos de regras do Microsoft Sentinel.
  • Verifique se você entende a terminologia de regras.
  • Por isso, é importante revisar as regras desatualizadas, principalmente aquelas que não geraram alertas nos últimos 6 a 12 meses, para verificar se ainda são relevantes.
  • Elimine ameaças de baixo nível ou alertas que você costuma ignorar.
  • Confirme as fontes de dados conectadas e examine os métodos de conexão de dados. A Análise do Microsoft Sentinel exige que o tipo de dados já esteja presente no workspace do Log Analytics antes de habilitar qualquer regra. Reveja as conversas de coleta de dados a fim de garantir a profundidade e a amplitude dos dados nos casos de uso que você planeja detectar. Depois utilize a experiência de migração de SIEM para garantir o correto mapeamento das fontes de dados.

Migrar regras

Depois de identificar as detecções do Splunk a serem migradas, confira estas considerações para o processo de migração:

  • Compare as funcionalidades das regras de análise OOTB do Microsoft Sentinel com seus casos de uso atuais. Use a experiência de migração de SIEM para verificar quais detecções do Splunk são automaticamente convertidas em modelos OOTB.
  • Traduza manualmente as detecções que não se alinham com as regras de análise OOTB. A melhor maneira de traduzir automaticamente as detecções do Splunk é com a experiência de migração do SIEM.
  • Descubra mais algoritmos para os seus casos de uso explorando os recursos da comunidade, como o Marketplace de Detecção de Ameaças do SOC Prime.
  • Traduza manualmente as detecções se as regras internas não estiverem disponíveis ou não forem traduzidas automaticamente. Crie as novas consultas KQL e revise o mapeamento de regras.

Para mais informações, confira as melhores práticas para migrar regras de detecção.

Etapas para migrar regras

  1. Verifique se há um sistema de teste em vigor para cada regra que você deseja migrar.

    1. Prepare um processo de validação para suas regras migradas, incluindo scripts e cenários de teste completos.

    2. Verifique se a equipe tem recursos úteis para testar suas regras migradas.

    3. Confirme se você tem as fontes de dados necessárias conectadas e examine os métodos de conexão de dados.

  2. Verifique se as detecções estão disponíveis como modelos OOTB no Microsoft Sentinel:

    • Use a experiência de migração do SIEM para automatizar a tradução e a instalação dos modelos OOTB.

      Para obter mais informações, consulte Usar a experiência de migração do SIEM.

    • Se suas detecções não cobrirem todos os seus casos de uso, crie suas próprias regras no workspace usando os modelos de regras OOTB.

      No Microsoft Sentinel, vá para a página Hub de conteúdo.

      Filtre pelo Tipo de conteúdo para obter modelos de Regra de análise.

      Encontre e instale/atualize cada solução correspondente do Hub de conteúdo ou modelo de regra de análise independente.

      Para saber mais, confira Detectar ameaças prontas para uso.

    • Se você tiver detecções que não são cobertas pelas regras OOTB do Microsoft Sentinel, o primeiro passo é tentar a experiência de migração do SIEM para uma tradução automática.

    • Se nem as regras OOTB nem a migração de SIEM conseguirem traduzir completamente a detecção, crie a regra manualmente. Nesses casos, siga as etapas abaixo para criar sua regra:

      1. Identifique as fontes de dados que você deseja usar em sua regra. Identifique as tabelas do Microsoft Sentinel que deseja consultar, criando uma tabela de mapeamento entre as fontes de dados e as tabelas de dados correspondentes.

      2. Identifique quaisquer atributos, campos ou entidades em seus dados que você deseja usar em suas regras.

      3. Identifique os critérios de regra e a lógica. Nesta fase, encontre modelos de regras que possam servir de exemplo para construir suas consultas KQL.

        Considere filtros, regras de correlação, listas ativas, conjuntos de referência, watchlists, anomalias de detecção, agregações e assim por diante. Você pode usar referências fornecidas pelo SIEM herdado a fim de entender como mapear melhor a sintaxe da sua consulta.

      4. Identifique a condição de gatilho e a ação de regra e, em seguida, construa e revise sua consulta KQL. Ao revisar sua consulta, considere os recursos de diretrizes de otimização do KQL.

  3. Teste a regra com cada um de seus casos de uso relevantes. Revise e edite o KQL se os resultados não forem satisfatórios, testando novamente até alcançar os resultados esperados.

  4. Quando os resultados forem satisfatórios, você poderá considerar a regra migrada. Crie um guia estratégico para sua ação de regra, conforme necessário. Para saber mais, confira Automatizar a resposta a ameaças com guias estratégicos no Microsoft Sentinel.

Saiba mais sobre as regras de análise:

Comparar a terminologia de regra

Esta tabela esclarece as diferenças entre uma regra baseada na Linguagem de Consulta Kusto (KQL) no Microsoft Sentinel comparada a uma detecção do Splunk, que usa a Linguagem de Processamento de Busca (SPL).

Splunk Microsoft Sentinel
Tipo de regra • Agendado
• Em tempo real
• Consulta agendada
• Fusão
• Segurança da Microsoft
• Análise Comportamental de ML (Machine Learning)
Critérios Definir no SPL Definir no KQL
Disparar condição • Número de resultados
• Número de hosts
• Número de fontes
• Personalizado
Limite: número de resultados de consulta
Ação • Adicionar a alertas disparados
• Evento de log
• Resultados de saída para pesquisa
• E muito mais
• Criar alerta ou incidente
• Integra-se aos Aplicativos Lógicos

Mapear e comparar exemplos de regra

Use esses exemplos para comparar e mapear regras do Splunk para o Microsoft Sentinel em vários cenários.

Comandos de pesquisa comuns

Comando SPL Descrição Operador KQL Exemplo KQL
chart/ timechart Retorna resultados em uma saída tabular para gráficos de série temporal. operador render … | render timechart
dedup Remove os resultados subsequentes que correspondem a um critério especificado. distinct
summarize
… | summarize by Computer, EventID
eval Calcula uma expressão. Saiba mais sobre comandos eval comuns. extend T | extend duration = endTime - startTime
fields Remove campos dos resultados da pesquisa. project
project-away
T | project cost=price*quantity, price
head/tail Retorna os primeiros ou últimos N resultados. início T | top 5 by Name desc nulls last
lookup Adiciona valores de campo de uma fonte externa. externaldata
lookup
Exemplo KQL
rename Renomeia um campo. Use curingas para especificar vários campos. project-rename T | project-rename new_column_name = column_name
rex Especifica nomes de grupo usando expressões regulares para extrair campos. matches regex … | where field matches regex "^addr.*"
search Filtra os resultados para ocorrências que correspondem à expressão de pesquisa. search search "X"
sort Classifica os resultados da pesquisa pelos campos especificados. sort T | sort by strlen(country) asc, price desc
stats Fornece estatísticas, opcionalmente agrupadas por campos. Saiba mais sobre os comandos de estatísticas comuns. summarize Exemplo KQL
mstats Semelhante às estatísticas, usadas em métricas em vez de eventos. summarize Exemplo KQL
table Especifica quais campos manter no conjunto de resultados e retém dados no formato tabular. project T | project columnA, columnB
top/rare Exibe os valores mais ou menos comuns de um campo. início T | top 5 by Name desc nulls last
transaction Agrupa os resultados da pesquisa em transações.

Exemplo SPL
Exemplo: row_window_session Exemplo KQL
eventstats Gera estatísticas resumidas de campos em seus eventos e salva essas estatísticas em um novo campo.

Exemplo SPL
Exemplos:
join
make_list
mv-expand
Exemplo KQL
streamstats Localize a soma cumulativa de um campo.

Exemplo SPL:
... | streamstats sum(bytes) as bytes _ total \| timechart
row_cumsum ...\| serialize cs=row_cumsum(bytes)
anomalydetection Encontre anomalias no campo especificado.

Exemplo SPL
series_decompose_anomalies() Exemplo KQL
where Filtra os resultados da pesquisa usando expressões eval. Usado para comparar dois campos diferentes. where T | where fruit=="apple"

Comando lookup: exemplo de KQL

Users 
| where UserID in ((externaldata (UserID:string) [
@"https://storageaccount.blob.core.windows.net/storagecontainer/users.txt" 
h@"?...SAS..." // Secret token to access the blob 
])) | ... 

Comando stats: exemplo de KQL

Sales 
| summarize NumTransactions=count(), 
Total=sum(UnitPrice * NumUnits) by Fruit, 
StartOfMonth=startofmonth(SellDateTime) 

Comando mstats: exemplo de KQL

T | summarize count() by price_range=bin(price, 10.0) 

Comando transaction: exemplo de SPL

sourcetype=MyLogTable type=Event
| transaction ActivityId startswith="Start" endswith="Stop"
| Rename timestamp as StartTime
| Table City, ActivityId, StartTime, Duration

Comando transaction: exemplo de KQL

let Events = MyLogTable | where type=="Event";
Events
| where Name == "Start"
| project Name, City, ActivityId, StartTime=timestamp
| join (Events
| where Name == "Stop"
| project StopTime=timestamp, ActivityId)
on ActivityId
| project City, ActivityId, StartTime, 
Duration = StopTime – StartTime

Use row_window_session() para calcular os valores de início da sessão para uma coluna em um conjunto de linhas serializado.

...| extend SessionStarted = row_window_session(
Timestamp, 1h, 5m, ID != prev(ID))

Comando eventstats: exemplo de SPL

… | bin span=1m _time
|stats count AS count_i by _time, category
| eventstats sum(count_i) as count_total by _time

Comando eventstats: exemplo de KQL

Aqui está um exemplo com a instrução join:

let binSize = 1h;
let detail = SecurityEvent 
| summarize detail_count = count() by EventID,
tbin = bin(TimeGenerated, binSize);
let summary = SecurityEvent
| summarize sum_count = count() by 
tbin = bin(TimeGenerated, binSize);
detail 
| join kind=leftouter (summary) on tbin 
| project-away tbin1

Aqui está um exemplo com a instrução make_list:

let binSize = 1m;
SecurityEvent
| where TimeGenerated >= ago(24h)
| summarize TotalEvents = count() by EventID, 
groupBin =bin(TimeGenerated, binSize)
|summarize make_list(EventID), make_list(TotalEvents), 
sum(TotalEvents) by groupBin
| mvexpand list_EventID, list_TotalEvents

Comando anomalydetection: exemplo de SPL

sourcetype=nasdaq earliest=-10y
| anomalydetection Close _ Price

Comando anomalydetection: exemplo de KQL

let LookBackPeriod= 7d;
let disableAccountLogon=SignIn
| where ResultType == "50057"
| where ResultDescription has "account is disabled";
disableAccountLogon
| make-series Trend=count() default=0 on TimeGenerated 
in range(startofday(ago(LookBackPeriod)), now(), 1d)
| extend (RSquare,Slope,Variance,RVariance,Interception,
LineFit)=series_fit_line(Trend)
| extend (anomalies,score) = 
series_decompose_anomalies(Trend)

Comandos eval comuns

Comando SPL Descrição Exemplo SPL Comando KQL Exemplo KQL
abs(X) Retorna o valor absoluto de X. abs(number) abs() abs(X)
case(X,"Y",…) Usa pares de argumentos X e Y, em que os argumentos X são expressões boolianas. Quando avaliados para TRUE, os argumentos retornam o argumento Y correspondente. Exemplo SPL case Exemplo KQL
ceil(X) Teto de um número X. ceil(1.9) ceiling() ceiling(1.9)
cidrmatch("X",Y) Identifica endereços IP que pertencem a uma sub-rede específica. cidrmatch
("123.132.32.0/25",ip)
ipv4_is_match()
ipv6_is_match()
ipv4_is_match('192.168.1.1', '192.168.1.255')
== false
coalesce(X,…) Retorna o primeiro valor que não é nulo. coalesce(null(), "Returned val", null()) coalesce() coalesce(tolong("not a number"),
tolong("42"), 33) == 42
cos(X) Calcula o cosseno de X. n=cos(0) cos() cos(X)
exact(X) Avalia uma expressão X usando aritmética de ponto flutuante de precisão dupla. exact(3.14*num) todecimal() todecimal(3.14*2)
exp(X) Retorna eX. exp(3) exp() exp(3)
if(X,Y,Z) Se X é avaliado como TRUE, o resultado é o segundo argumento Y. Se X é avaliado como FALSE, o resultado é avaliado como o terceiro argumento Z. if(error==200,
"OK", "Error")
iif() Exemplo KQL
isbool(X) Retorna TRUE se X é booliano. isbool(field) iif()
gettype
iif(gettype(X) =="bool","TRUE","FALSE")
isint(X) Retorna TRUE se X é um inteiro. isint(field) iif()
gettype
Exemplo KQL
isnull(X) Retorna TRUE se X é nulo. isnull(field) isnull() isnull(field)
isstr(X) Retorna TRUE se X é uma cadeia de caracteres. isstr(field) iif()
gettype
Exemplo KQL
len(X) Essa função retorna o comprimento de uma cadeia de caracteres X em número de caracteres. len(field) strlen() strlen(field)
like(X,"y") Retorna TRUE se e somente se X é como o padrão SQLite em Y. like(field, "addr%") has
contains
startswith
matches regex
Exemplo KQL
log(X,Y) Retorna o log do primeiro argumento X usando o segundo argumento Y como base. O valor padrão de Y é 10. log(number,2) log
log2
log10
log(X)

log2(X)

log10(X)
lower(X) Retorna o valor em minúsculas de X. lower(username) tolower tolower(username)
ltrim(X,Y) Retorna X com os caracteres no parâmetro Y cortados do lado esquerdo. A saída padrão de Y são espaços e tabulações. ltrim(" ZZZabcZZ ", " Z") trim_start() trim_start(“ ZZZabcZZ”,” ZZZ”)
match(X,Y) Retorna se X corresponde ao padrão de regex Y. match(field, "^\d{1,3}.\d$") matches regex … | where field matches regex @"^\d{1,3}.\d$")
max(X,…) Retorna o valor máximo em uma coluna. max(delay, mydelay) max()
arg_max()
… | summarize max(field)
md5(X) Retorna o hash MD5 de um valor de cadeia de caracteres X. md5(field) hash_md5 hash_md5("X")
min(X,…) Retorna o valor mínimo em uma coluna. min(delay, mydelay) min_of()
min()
arg_min
Exemplo KQL
mvcount(X) Retorna o número (total) de valores X. mvcount(multifield) dcount …| summarize dcount(X) by Y
mvfilter(X) Filtra um campo de vários valores baseado na expressão booliana X. mvfilter(match(email, "net$")) mv-apply Exemplo KQL
mvindex(X,Y,Z) Retorna um subconjunto do argumento de vários valores X de uma posição inicial (baseada em zero) Y até Z (opcional). mvindex( multifield, 2) array_slice array_slice(arr, 1, 2)
mvjoin(X,Y) Dado um campo de vários valores X e a cadeia de caracteres delimitadora Y, une os valores individuais de X usando Y. mvjoin(address, ";") strcat_array Exemplo KQL
now() Retorna a hora atual, representada no tempo do Unix. now() now() now()

now(-2d)
null() Não aceita argumentos e retorna NULL. null() null null
nullif(X,Y) Inclui dois argumentos, X e Y, e retorna X se os argumentos forem diferentes. Caso contrário, retorna NULL. nullif(fieldA, fieldB) iif iif(fieldA==fieldB, null, fieldA)
random() Retorna um número pseudo-aleatório entre 0 e 2147483647. random() rand() rand()
relative_ time(X,Y) Dado um tempo de época X e um especificador de tempo relativo Y, retorna o valor temporal da época de Y aplicado a X. relative_time(now(),"-1d@d") tempo do unix Exemplo KQL
replace(X,Y,Z) Retorna uma cadeia de caracteres formada substituindo a cadeia Z para toda ocorrência da cadeia de caracteres da expressão regular Y na cadeia de caracteres X. Retorna a data com os números do mês e do dia alternados entre si.
Por exemplo, para a entrada 4/30/2015, a saída é 30/4/2009:

replace(date, "^(\d{1,2})/ (\d{1,2})/", "\2/\1/")
replace() Exemplo KQL
round(X,Y) Retorna X arredondado para o número de casas decimais especificado por Y. O padrão é arredondar para um inteiro. round(3.5) round round(3.5)
rtrim(X,Y) Retorna X com os caracteres de Y cortados do lado direito. Se Y não for especificado, espaços e tabulações serão cortados. rtrim(" ZZZZabcZZ ", " Z") trim_end() trim_end(@"[ Z]+",A)
searchmatch(X) Retorna TRUE se o evento corresponder à cadeia de caracteres de pesquisa X. searchmatch("foo AND bar") iif() iif(field has "X","Yes","No")
split(X,"Y") Retorna X como um campo de vários valores, dividido pelo delimitador Y. split(address, ";") split() split(address, ";")
sqrt(X) Retorna a raiz quadrada de X. sqrt(9) sqrt() sqrt(9)
strftime(X,Y) Retorna o valor temporal de época X renderizado usando o formato especificado por Y. strftime(_time, "%H:%M") format_datetime() format_datetime(time,'HH:mm')
strptime(X,Y) Dado um tempo representado por uma cadeia de caracteres X, retorna o valor analisado com base no formato Y. strptime(timeStr, "%H:%M") format_datetime() Exemplo KQL
substr(X,Y,Z) Retorna um campo substring X da posição inicial (baseada em um) Y para Z (opcional) caracteres. substr("string", 1, 3) substring() substring("string", 0, 3)
time() Retorna a hora do relógio de parede com resolução de microssegundos. time() format_datetime() Exemplo KQL
tonumber(X,Y) Converte a cadeia de caracteres de entrada X em um número, em que Y (opcional, o valor padrão é 10) define a base do número ao qual converter. tonumber("0A4",16) toint() toint("123")
tostring(X,Y) Descrição Exemplo SPL tostring() tostring(123)
typeof(X) Retorna uma representação de cadeia de caracteres do tipo do campo. typeof(12) gettype() gettype(12)
urldecode(X) Retorna a URL X decodificada. Exemplo SPL url_decode Exemplo KQL

Exemplo de SPL case(X,"Y",…)

case(error == 404, "Not found",
error == 500,"Internal Server Error",
error == 200, "OK")

Exemplo de KQL case(X,"Y",…)

T
| extend Message = case(error == 404, "Not found", 
error == 500,"Internal Server Error", "OK") 

Exemplo de KQL if(X,Y,Z)

iif(floor(Timestamp, 1d)==floor(now(), 1d), 
"today", "anotherday")

Exemplo de KQL isint(X)

iif(gettype(X) =="long","TRUE","FALSE")

Exemplo de KQL isstr(X)

iif(gettype(X) =="string","TRUE","FALSE")

Exemplo do like(X,"y")

… | where field has "addr"

… | where field contains "addr"

… | where field startswith "addr"

… | where field matches regex "^addr.*"

Exemplo de KQL min(X,…)

min_of (expr_1, expr_2 ...)

…|summarize min(expr)

…| summarize arg_min(Price,*) by Product

Exemplo de KQL mvfilter(X)

T | mv-apply Metric to typeof(real) on 
(
 top 2 by Metric desc
)

Exemplo de KQL mvjoin(X,Y)

strcat_array(dynamic([1, 2, 3]), "->")

Exemplo de KQL relative time(X,Y)

let toUnixTime = (dt:datetime)
{
(dt - datetime(1970-01-01))/1s 
};

Exemplo de KQL replace(X,Y,Z)

replace( @'^(\d{1,2})/(\d{1,2})/', @'\2/\1/',date)

Exemplo de KQL strptime(X,Y)

format_datetime(datetime('2017-08-16 11:25:10'),
'HH:mm')

Exemplo de KQL time()

format_datetime(datetime(2015-12-14 02:03:04),
'h:m:s')

tostring(X,Y)

Retorna um valor de campo X como uma cadeia de caracteres.

  • Se o valor X for um número, X será reformatado como um valor de cadeia de caracteres.
  • Se X for um valor booliano, X será reformatado para TRUE ou FALSE.
  • Se X for um número, o segundo argumento Y será opcional e poderá ser hex (converte X para hexadecimal), commas (formata X com vírgulas e duas casas decimais) ou duration (converte X de um formato de tempo em segundos para um formato de tempo legível: HH:MM:SS).
Exemplo de SPL tostring(X,Y)

Este exemplo retorna:

foo=615 and foo2=00:10:15:

… | eval foo=615 | eval foo2 = tostring(
foo, "duration")

Exemplo de SPL urldecode(X)

urldecode("http%3A%2F%2Fwww.splunk.com%2Fdownload%3Fr%3Dheader")

Exemplo de KQL de comandos stats comuns

Comando SPL Descrição Comando KQL Exemplo KQL
avg(X) Retorna a média dos valores do campo X. avg() avg(X)
count(X) Retorna o número de ocorrências do campo X. Para indicar um valor de campo específico a ser correspondido, formate X como eval(field="value"). count() summarize count()
dc(X) Retorna a contagem de valores distintos do campo X. dcount() …\| summarize countries=dcount(country) by continent
earliest(X) Retorna o valor cronologicamente mais antigo encontrado de X. arg_min() … \| summarize arg_min(TimeGenerated, *) by X
latest(X) Retorna o valor cronologicamente mais recente encontrado de X. arg_max() … \| summarize arg_max(TimeGenerated, *) by X
max(X) Retorna o valor máximo do campo X. Se os valores de X não forem numéricos, o valor máximo será encontrado por meio da ordenação alfabética. max() …\| summarize max(X)
median(X) Retorna o valor mais ao meio do campo X. percentile() …\| summarize percentile(X, 50)
min(X) Retorna o valor mínimo do campo X. Se os valores de X não forem numéricos, o valor mínimo será encontrado por meio da ordenação alfabética. min() …\| summarize min(X)
mode(X) Retorna o valor mais frequente do campo X. top-hitters() …\| top-hitters 1 of Y by X
perc(Y) Retorna o valor X do percentual do campo Y. Por exemplo, perc5(total) retorna o quinto valor percentual de um campo total. percentile() …\| summarize percentile(Y, 5)
range(X) Retorna a diferença entre os valores máximo e mínimo do campo X. range() range(1, 3)
stdev(X) Retorna o desvio padrão de amostra do campo X. stdev stdev()
stdevp(X) Retorna o desvio padrão da população do campo X. stdevp() stdevp()
sum(X) Retorna a soma dos valores do campo X. sum() sum(X)
sumsq(X) Retorna a soma dos quadrados dos valores do campo X.
values(X) Retorna a lista de todos os valores distintos do campo X como uma entrada de vários valores. A ordem dos valores é alfabética. make_set() …\| summarize r = make_set(X)
var(X) Retorna a variação de amostra do campo X. variance variance(X)

Próximas etapas

Neste artigo, você aprendeu a mapear suas regras de migração do Splunk para o Microsoft Sentinel.