Compartir a través de


Migración de reglas de detección de Splunk a Microsoft Sentinel

En este artículo se describe cómo identificar, comparar y migrar las reglas de detección de Splunk a reglas integradas de Microsoft Sentinel.

Si quiere migrar la implementación de Splunk Observability, obtenga más información sobre cómo hacer la migración de Splunk a registros de Azure Monitor.

Identificación y migración de reglas

Microsoft Sentinel usa análisis de aprendizaje automático para crear incidentes de alta fidelidad sobre los que se puede actuar; algunas de las detecciones que ya tiene pueden ser redundantes en Microsoft Sentinel. Por tanto, no migre todas las reglas de detección y análisis a ciegas. Revise estas consideraciones cuando identifique las reglas de detección existentes.

  • Asegúrese de seleccionar los casos de uso que justifican la migración de reglas, teniendo en cuenta la prioridad empresarial y la eficacia.
  • Asegúrese de entender los tipos de reglas de Microsoft Sentinel.
  • Asegúrese de entender la terminología de las reglas.
  • Revise las reglas que no hayan desencadenado ninguna alerta en los últimos 6 a 12 meses y determine si siguen siendo pertinentes.
  • Elimine las amenazas o alertas de bajo nivel que omite de forma rutinaria.
  • Use la funcionalidad existente y compruebe si las reglas de análisis integradas de Microsoft Sentinel podrían abordar los casos de uso actuales. Como Microsoft Sentinel usa análisis de aprendizaje automático para generar incidentes procesables y muy fiables, es probable que algunas de las detecciones existentes ya no sean necesarias.
  • Confirme los orígenes de datos conectados y revise los métodos de conexión de datos. Vuelva a revisar las conversaciones de recopilación de datos para garantizar la profundidad y la amplitud de los datos en todos los casos de uso que piensa detectar.
  • Pruebe las funcionalidades de la experiencia de migración de SIEM para determinar si la traducción automatizada es adecuada.
  • Explore los recursos de la comunidad, como SOC Prime Threat Detection Marketplace, para comprobar si las reglas están disponibles.
  • Piense si un convertidor de consultas en línea, como Uncoder.io, podría funcionar en las reglas.
  • Si las reglas no están disponibles o no se pueden convertir, se deben crear manualmente mediante una consulta de KQL. Revise la asignación de reglas para crear consultas.

Obtenga más información sobre los procedimientos recomendados para migrar reglas de detección.

Para migrar las reglas de análisis a Microsoft Sentinel:

  1. Compruebe que cuenta con un sistema de pruebas para cada regla que quiere migrar.

    1. Prepare un proceso de validación para las reglas migradas, incluidos escenarios y scripts de prueba completos.

    2. Asegúrese de que el equipo tiene recursos útiles para probar las reglas migradas.

    3. Confirme que tiene los orígenes de datos necesarios conectados y revise los métodos de conexión de datos.

  2. Compruebe si las detecciones están disponibles como plantillas integradas en Microsoft Sentinel:

    • Use la experiencia de migración de SIEM para automatizar la traducción y la migración.

      Para más información, consulte Uso de la experiencia de migración de SIEM.

    • Si las reglas integradas son suficientes, use plantillas de reglas integradas para crear reglas para su propia área de trabajo.

      En Microsoft Sentinel, vaya a la pestaña Configuración > Análisis > Plantillas de reglas y cree y actualice cada regla de análisis pertinente.

      Para más información, consulte Detección de amenazas integrada.

    • Si tiene detecciones que no están cubiertas por las reglas integradas de Microsoft Sentinel, pruebe un convertidor de consultas en línea, como Uncoder.io o SPL2KQL, para convertir las consultas a KQL.

      Identifique la condición del desencadenador y la acción de regla y, a continuación, construya y revise la consulta KQL.

    • Si ni las reglas integradas ni un convertidor de reglas en línea son suficientes, deberá crear la regla manualmente. En tal caso, siga estos pasos para empezar a crear la regla:

      1. Identifique los orígenes de datos que desea usar en la regla. Querrá crear una tabla de asignación entre los orígenes de datos y las tablas de datos de Microsoft Sentinel para identificar las tablas que quiere consultar.

      2. Identifique los atributos, campos o entidades en los datos que desea usar en las reglas.

      3. Identifique los criterios y la lógica de la regla. En esta fase, puede que desee usar plantillas de regla como ejemplos para construir las consultas KQL.

        Considere la posibilidad de usar filtros, reglas de correlación, listas activas, conjuntos de referencias, listas de control, anomalías de detección, agregaciones, etcétera. Puede usar las referencias proporcionadas por la solución de SIEM heredada para entender cómo asignar mejor la sintaxis de consulta.

      4. Identifique la condición del desencadenador y la acción de regla y, a continuación, construya y revise la consulta KQL. Al revisar la consulta, considere la posibilidad de usar los recursos de guía de optimización de KQL.

  3. Pruebe la regla con cada uno de los casos de uso pertinentes. Si no consigue los resultados esperados, es posible que quiera revisar la consulta de KQL y probarla de nuevo.

  4. Cuando esté satisfecho, puede considerar la regla migrada. Cree un cuaderno de estrategias para la acción de regla según sea necesario. Para obtener más información, vea Automatización de la respuesta a amenazas con cuadernos de estrategias en Microsoft Sentinel.

Obtenga más información sobre las reglas de análisis:

Comparación de la terminología de las reglas

Esta tabla ayuda a aclarar el concepto de una regla en Microsoft Sentinel en comparación con Splunk.

Splunk Microsoft Sentinel
Tipo de regla • Programadas
• Tiempo real
• Consulta programada
• Fusión
• Seguridad de Microsoft
• Análisis de comportamiento de Machine Learning (ML)
Criterios Definición en SPL Definición en KQL
Condición desencadenadora • Número de resultados:
• Número de hosts
• Número de orígenes
• Personalizado
Umbral: número de resultados de la consulta
Acción • Adición a alertas desencadenadas
• Registro de eventos
• Resultados de salida para la búsqueda
• Y mucho más
• Crear alerta o incidente
• Integrar con Logic Apps

Asignación y comparación de ejemplos de reglas

Use estos ejemplos para comparar y asignar reglas de Splunk a Microsoft Sentinel en varios escenarios.

Comandos de búsqueda comunes

Comando SPL Descripción Operador KQL Ejemplo de KQL
chart/ timechart Devuelve resultados en una salida tabular para el gráfico de series temporales. Operador render … | render timechart
dedup Quita los resultados posteriores que coinciden con un criterio especificado. distinct
summarize
… | summarize by Computer, EventID
eval Calcula una expresión. Obtenga información sobre los comandos de eval comunes. extend T | extend duration = endTime - startTime
fields Quita los campos de los resultados de la búsqueda. project
project-away
T | project cost=price*quantity, price
head/tail Devuelve los primeros o últimos N resultados. top T | top 5 by Name desc nulls last
lookup Agrega valores de campo de un origen externo. externaldata
lookup
Ejemplo de KQL
rename Cambia el nombre de un campo. Use caracteres comodín para especificar varios campos. project-rename T | project-rename new_column_name = column_name
rex Especifica los nombres de grupo mediante expresiones regulares para extraer campos. matches regex … | where field matches regex "^addr.*"
search Filtra los resultados por los resultados que coinciden con la expresión de búsqueda. search search "X"
sort Ordena los resultados de búsqueda por los campos especificados. sort T | sort by strlen(country) asc, price desc
stats Proporciona estadísticas, opcionalmente agrupadas por campos. Obtenga más información sobre los comandos de estadísticas comunes. summarize Ejemplo de KQL
mstats De forma similar a las estadísticas, se usa en métricas en lugar de eventos. summarize Ejemplo de KQL
table Especifica los campos que se deben conservar en el conjunto de resultados y conserva los datos en formato tabular. project T | project columnA, columnB
top/rare Muestra los valores más o menos comunes de un campo. top T | top 5 by Name desc nulls last
transaction Agrupa los resultados de búsqueda en transacciones.

Ejemplo de SPL
Ejemplo: row_window_session Ejemplo de KQL
eventstats Genera estadísticas de resumen de los campos de los eventos y guarda esas estadísticas en un nuevo campo.

Ejemplo de SPL
Ejemplos:
join
make_list
mv-expand
Ejemplo de KQL
streamstats Busque la suma acumulativa de un campo.

Ejemplo de SPL:
... | streamstats sum(bytes) as bytes _ total \| timechart
row_cumsum ...\| serialize cs=row_cumsum(bytes)
anomalydetection Busque anomalías en el campo especificado.

Ejemplo de SPL
series_decompose_anomalies() Ejemplo de KQL
where Filtra los resultados de búsqueda mediante eval expresiones. Se usa para comparar dos campos diferentes. where T | where fruit=="apple"

Comando de búsqueda: ejemplo 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: ejemplo de KQL

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

Comando mstats: ejemplo de KQL

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

comando transaction: ejemplo de SPL

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

comando transaction: ejemplo 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 los valores de inicio de sesión de una columna de un conjunto de filas serializado.

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

Comando eventstats: ejemplo 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: ejemplo de KQL

Este es un ejemplo con la instrucción 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

Este es un ejemplo con la instrucción 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: ejemplo de SPL

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

Comando anomalydetection: ejemplo 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 comunes de eval

Comando SPL Descripción Ejemplo de SPL Comando KQL Ejemplo de KQL
abs(X) Devuelve el valor absoluto de X. abs(number) abs() abs(X)
case(X,"Y",…) Toma pares de argumentos X y Y, donde los argumentos X son expresiones booleanas. Cuando se evalúa como TRUE, los argumentos devuelven el argumento correspondiente Y. Ejemplo de SPL case Ejemplo de KQL
ceil(X) Techo de un número X. ceil(1.9) ceiling() ceiling(1.9)
cidrmatch("X",Y) Identifica las direcciones IP que pertenecen a una subred determinada. 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,…) Devuelve el primer valor que no es NULL. coalesce(null(), "Returned val", null()) coalesce() coalesce(tolong("not a number"),
tolong("42"), 33) == 42
cos(X) Calcula el coseno del argumento. n=cos(0) cos() cos(X)
exact(X) Evalúa una expresión X con aritmética de punto flotante de precisión doble. exact(3.14*num) todecimal() todecimal(3.14*2)
exp(X) Devuelve eX. exp(3) exp() exp(3)
if(X,Y,Z) Si X se evalúa como TRUE, el resultado es el segundo argumento Y. Si X se evalúa como FALSE, el resultado se evalúa como el tercer argumento Z. if(error==200,
"OK", "Error")
iif() Ejemplo de KQL
isbool(X) Devuelve TRUE si X es booleano. isbool(field) iif()
gettype
iif(gettype(X) =="bool","TRUE","FALSE")
isint(X) Devuelve TRUE si X es un entero. isint(field) iif()
gettype
Ejemplo de KQL
isnull(X) Devuelve TRUE si X es null. isnull(field) isnull() isnull(field)
isstr(X) Devuelve TRUE si X es una cadena. isstr(field) iif()
gettype
Ejemplo de KQL
len(X) Esta función devuelve la longitud de caracteres de una cadena X. len(field) strlen() strlen(field)
like(X,"y") Devuelve TRUE si y solo si X es similar al patrón SQLite de Y. like(field, "addr%") has
contains
startswith
matches regex
Ejemplo de KQL
log(X,Y) Devuelve el registro del primer argumento X con el segundo argumento Y como base. El valor predeterminado de Y es 10. log(number,2) log
log2
log10
log(X)

log2(X)

log10(X)
lower(X) Devuelve un valor en minúscula de X. lower(username) tolower tolower(username)
ltrim(X,Y) Devuelve X con los caracteres del parámetro Y recortado desde el lado izquierdo. La salida predeterminada de Y son espacios y pestañas. ltrim(" ZZZabcZZ ", " Z") trim_start() trim_start(“ ZZZabcZZ”,” ZZZ”)
match(X,Y) Devuelve si X coincide con el patrón regex Y. match(field, "^\d{1,3}.\d$") matches regex … | where field matches regex @"^\d{1,3}.\d$")
max(X,…) Devuelve el valor máximo de una columna. max(delay, mydelay) max()
arg_max()
… | summarize max(field)
md5(X) Devuelve el hash MD5 de un valor de cadena X. md5(field) hash_md5 hash_md5("X")
min(X,…) Devuelve el valor mínimo de una columna. min(delay, mydelay) min_of()
min()
arg_min
Ejemplo de KQL
mvcount(X) Devuelve el número (total) de valores X. mvcount(multifield) dcount …| summarize dcount(X) by Y
mvfilter(X) Filtra un campo multivalor basado en la expresión booleana X. mvfilter(match(email, "net$")) mv-apply Ejemplo de KQL
mvindex(X,Y,Z) Devuelve un subconjunto del argumento multivalor X de una posición inicial (basada en cero) Y a Z (opcional). mvindex( multifield, 2) array_slice array_slice(arr, 1, 2)
mvjoin(X,Y) Dado un campo X multivalor y un delimitador de cadena Y y combina los valores individuales de X mediante Y. mvjoin(address, ";") strcat_array Ejemplo de KQL
now() Devuelve la hora actual, representada en tiempo Unix. now() now() now()

now(-2d)
null() No acepta argumentos y devuelve NULL. null() null null
nullif(X,Y) Incluye dos argumentos, X y Y, y devuelve X si los argumentos son diferentes. De lo contrario, devuelve NULL. nullif(fieldA, fieldB) iif iif(fieldA==fieldB, null, fieldA)
random() Devuelve un número pseudoaleatorio entre 0 a 2147483647. random() rand() rand()
relative_ time(X,Y) Dada una hora de época X y un especificador de hora relativo Y, devuelve el valor de hora de época de Y aplicado a X. relative_time(now(),"-1d@d") hora de unix Ejemplo de KQL
replace(X,Y,Z) Devuelve una cadena formada al sustituir la cadena Z por cada aparición de la cadena de expresión regular Y en la cadena X. Devuelve la fecha con los números de mes y día modificados.
Por ejemplo, para la entrada 4/30/2015, la salida es 30/4/2009:

replace(date, "^(\d{1,2})/ (\d{1,2})/", "\2/\1/")
replace() Ejemplo de KQL
round(X,Y) Devuelve X redondeado al número de posiciones decimales especificadas por Y. El valor predeterminado es redondear a un entero. round(3.5) round round(3.5)
rtrim(X,Y) Devuelve X con los caracteres de Y recortados desde el lado derecho. Si Y no se especifica, se recortan espacios y pestañas. rtrim(" ZZZZabcZZ ", " Z") trim_end() trim_end(@"[ Z]+",A)
searchmatch(X) Devuelve TRUE si el evento coincide con la cadena de búsqueda X. searchmatch("foo AND bar") iif() iif(field has "X","Yes","No")
split(X,"Y") Devuelve X como un campo multivalor, dividido por delimitador Y. split(address, ";") split() split(address, ";")
sqrt(X) Devuelve la raíz cuadrada de X. sqrt(9) sqrt() sqrt(9)
strftime(X,Y) Devuelve el valor de hora de época X representado con el formato especificado por Y. strftime(_time, "%H:%M") format_datetime() format_datetime(time,'HH:mm')
strptime(X,Y) Dada una hora representada por una cadena X, devuelve el valor analizado a partir del formato Y. strptime(timeStr, "%H:%M") format_datetime() Ejemplo de KQL
substr(X,Y,Z) Devuelve un campo de subcadena X de la posición inicial (basada en uno) Y para Z caracteres (opcionales). substr("string", 1, 3) substring() substring("string", 0, 3)
time() Devuelve el tiempo del reloj con resolución de microsegundos. time() format_datetime() Ejemplo de KQL
tonumber(X,Y) Convierte la cadena de entrada X en un número, donde Y (opcional, el valor predeterminado es 10) define la base del número al que se va a convertir. tonumber("0A4",16) toint() toint("123")
tostring(X,Y) Descripción Ejemplo de SPL tostring() tostring(123)
typeof(X) Devuelve una representación de cadena del tipo de campo. typeof(12) gettype() gettype(12)
urldecode(X) Devuelve la dirección URL X descodificada. Ejemplo de SPL url_decode Ejemplo de KQL

Ejemplo de SPL case(X,"Y",...)

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

Ejemplo de KQL case(X,"Y",...)

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

Ejemplo de KQL if(X,Y,Z)

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

Ejemplo de KQL isint(X)

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

Ejemplo de KQL isstr(X)

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

Ejemplo like(X,"y")

… | where field has "addr"

… | where field contains "addr"

… | where field startswith "addr"

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

Ejemplo de KQL min(X,...)

min_of (expr_1, expr_2 ...)

…|summarize min(expr)

…| summarize arg_min(Price,*) by Product

Ejemplo de KQL mvfilter(X)

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

Ejemplo de KQL mvjoin(X,Y)

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

Ejemplo de KQL relative time(X,Y)

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

Ejemplo de KQL replace(X,Y,Z)

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

Ejemplo de KQL strptime(X,Y)

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

Ejemplo de KQL time()

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

tostring(X,Y)

Devuelve un valor de campo de X como una cadena.

  • Si el valor de X es un número, X se vuelve a formatear en un valor de cadena.
  • Si X es un valor booleano, X se vuelve a formatear a TRUE o FALSE.
  • Si X es un número, el segundo argumento Y es opcional y puede ser hex (convierte X en hexadecimal), commas (formatos X con comas y dos posiciones decimales), o duration (convierte X de un formato de tiempo en segundos a un formato de tiempo legible: HH:MM:SS).
Ejemplo de SPL tostring(X,Y)

En este ejemplo se devuelve lo siguiente:

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

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

Ejemplo de SPL urldecode(X)

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

Ejemplo de KQL de comandos de estadísticas comunes

Comando SPL Descripción Comando KQL Ejemplo de KQL
avg(X) Devuelve el promedio de los valores del campo X. avg() avg(X)
count(X) Devuelve el número de repeticiones del campo X. Para indicar un valor de campo específico que debe coincidir, dé formato a X como eval(field="value"). count() summarize count()
dc(X) Devuelve el recuento de valores distintos del campo X. dcount() …\| summarize countries=dcount(country) by continent
earliest(X) Devuelve el valor cronológico más antiguo visto de X. arg_min() … \| summarize arg_min(TimeGenerated, *) by X
latest(X) Devuelve el valor cronológico más reciente visto de X. arg_max() … \| summarize arg_max(TimeGenerated, *) by X
max(X) Devuelve el valor máximo del campo X. Si los valores de X no son numéricos, el valor máximo se encuentra a través del orden alfabético. max() …\| summarize max(X)
median(X) Devuelve el valor del campo X. percentile() …\| summarize percentile(X, 50)
min(X) Devuelve el valor mínimo del campo X. Si los valores de X no son numéricos, el valor mínimo se encuentra mediante el orden alfabético. min() …\| summarize min(X)
mode(X) Devuelve el valor más frecuente del campo X. top-hitters() …\| top-hitters 1 of Y by X
perc(Y) Devuelve el valor X del percentil del campo Y. Por ejemplo, perc5(total) devuelve el quinto valor de percentil de un campo total. percentile() …\| summarize percentile(Y, 5)
range(X) Devuelve la diferencia entre los valores máximos y mínimos del campo X. range() range(1, 3)
stdev(X) Obtiene la desviación estándar de muestra del campo X. stdev stdev()
stdevp(X) Obtiene la desviación estándar de población del campo X. stdevp() stdevp()
sum(X) Devuelve la suma de los valores del campo X. sum() sum(X)
sumsq(X) Devuelve la suma de los cuadrados de los valores del campo X.
values(X) Devuelve la lista de todos los valores distintos del campo X como una entrada de varios valores. El orden de los valores es alfabético. make_set() …\| summarize r = make_set(X)
var(X) Devuelve la varianza de muestra del campo X. variance variance(X)

Pasos siguientes

En este artículo ha aprendido a asignar las reglas de migración de Splunk a Microsoft Sentinel.