Partage via


Migrer des règles de détection Splunk vers Microsoft Sentinel

Les règles de détection Splunk sont des composants SIEM (Gestion des informations et des événements de sécurité) qui se comparent aux règles d’analyse dans Microsoft Sentinel. Cet article décrit les concepts permettant d’identifier, de comparer et de les migrer vers Microsoft Sentinel. La meilleure façon est de commencer par l’expérience de migration SIEM, qui identifie les règles d’analyse prêtes à l’emploi (OOTB) pour les traduire automatiquement.

Si vous souhaitez migrer votre déploiement Splunk Observability, découvrez comment migrer de Splunk vers des journaux Azure Monitor.

Règles d’audit

Microsoft Sentinel utilise l’analyse Machine Learning pour créer des incidents haute fidélité et actionnables. Certaines de vos détections Splunk existantes peuvent être redondantes dans Microsoft Sentinel, donc ne les migrez pas toutes aveuglement. Passez en revue ces considérations quand vous identifiez vos règles de détection existantes.

  • Veillez à sélectionner les cas d’usage qui justifient la migration des règles, en tenant compte des priorités et de l’efficacité de l’entreprise.
  • Vérifiez que vous comprenez les types de règles Microsoft Sentinel.
  • Vérifiez que vous comprenez la terminologie des règles.
  • Passez en revue les règles obsolètes qui n’ont pas d’alertes au cours des 6 à 12 derniers mois et déterminez si elles sont toujours pertinentes.
  • Éliminez les menaces ou les alertes de bas niveau que vous ignorez régulièrement.
  • Vérifiez que vous avez connecté toutes les sources de données requises et passez en revue vos méthodes de connexion de données. L’Analyse Microsoft Sentinel exige que le type de données soit présent dans l'espace de travail Log Analytics avant qu’une règle ne soit activée. Revenez sur les conversations de collecte de données pour vous assurer de la profondeur et de l’étendue des données dans vos cas d’usage. Utilisez ensuite l’expérience de migration SIEM pour vous assurer que les sources de données sont mappées de manière appropriée.

Migrer les règles

Après avoir identifié les détections Splunk à migrer, passez en revue les considérations suivantes pour le processus de migration :

  • Comparez les fonctionnalités existantes des règles d’analyse OOTB de Microsoft Sentinel à vos cas d’usage actuels. Utilisez l’expérience de migration SIEM pour voir quelles détections Splunk sont automatiquement converties en modèles OOTB.
  • Traduisez les détections qui ne s’alignent pas sur les règles d’analyse OOTB. La meilleure façon de traduire automatiquement les détections Splunk est d’utiliser l’expérience de migration SIEM.
  • Découvrez d’autres algorithmes pour vos cas d’usage en explorant les ressources de la communauté telles que la Place de marché de détection des menaces SOC Prime.
  • Traduisez manuellement les détections si les règles intégrées ne sont pas disponibles ou ne sont pas traduites automatiquement. Créez les nouvelles requêtes KQL et passez en revue le mappage des règles.

Pour plus d’informations, consultez les meilleures pratiques pour migrer des règles de détection.

Étapes de migration de règles

  1. Vérifiez que vous avez mis en place un système de test pour chaque règle que vous souhaitez migrer.

    1. Préparez un processus de validation pour vos règles migrées, y compris des scénarios et des scripts de test complets.

    2. Assurez-vous que votre équipe dispose des ressources utiles pour tester vos règles migrées.

    3. Confirmez que vous avez connecté les sources de données nécessaires, et vérifiez vos méthodes de connexion de données.

  2. Vérifiez si vos détections sont disponibles en tant que modèles OOTB dans Microsoft Sentinel :

    • Utilisez l’expérience de migration SIEM pour automatiser la traduction et l’installation des modèles OOTB.

      Pour plus d’informations, consultez Utiliser l’expérience de migration SIEM.

    • Si vous avez des cas d’usage non reflétés dans les détections, créez des règles pour votre propre espace de travail avec des modèles de règles OOTB.

      Dans Microsoft Sentinel, accédez au Hub de contenu.

      Filtrez Type de contenu pour les modèles de Règle d’analyse.

      Recherchez et installez/mettez à jour chaque solution Hub de contenu correspondante ou modèle de règle d’analyse autonome.

      Pour plus d’informations, consultez Détection des menaces prête à l’emploi.

    • Si vous avez des détections qui ne sont pas couvertes par les règles OOTB de Microsoft Sentinel, essayez d’abord l’expérience de migration SIEM pour la traduction automatique.

    • Si ni les règles OOTB ni la migration SIEM ne traduisent complètement la détection, créez la règle manuellement. Dans ce cas, procédez comme suit pour créer votre règle :

      1. Identifiez les sources de données que vous souhaitez utiliser dans votre règle. Identifiez les tables Microsoft Sentinel que vous souhaitez interroger en créant une table de mappage entre les sources de données et les tables de données.

      2. Identifiez tous les attributs, champs ou entités de vos données que vous souhaitez utiliser dans vos règles.

      3. Identifiez les critères et la logique de vos règles. À ce stade, tentez de trouver des modèles de règle comme exemples pour construire vos requêtes KQL.

        Pensez aux filtres, aux règles de corrélation, aux listes actives, aux ensembles de référence, aux listes de surveillance, aux anomalies de détection, aux agrégations, etc. Vous pouvez utiliser les références fournies par votre SIEM héritée pour comprendre comment mapper au mieux la syntaxe de vos requêtes.

      4. Identifiez la condition du déclencheur et l’action de la règle, puis créez et passez en revue votre requête KQL. Lorsque vous examinez votre requête, tenez compte des aides relatives à l’optimisation de KQL.

  3. Testez la règle avec chacun de vos cas d’usage pertinents. Si elle ne fournit pas les résultats attendus, vérifiez et modifiez la requête KQL et testez-la à nouveau.

  4. Lorsque vous êtes satisfait, considérez que la règle a été migrée. Créez un playbook pour votre action de règle le cas échéant. Pour plus d’informations, consultez Automatisation de la réponse aux menaces avec des playbooks dans Microsoft Sentinel.

En savoir plus sur les règles d’analytique :

Comparer la terminologie des règles

Ce tableau vous aide à clarifier le concept d’une règle basée sur le Langage de requête Kusto (KQL) dans Microsoft Sentinel par rapport à une détection Splunk basée sur le Langage de traitement de la recherche (SPL).

Splunk Microsoft Sentinel
Type de règle • Planifiée
• Temps réel
• Requête planifiée
• Fusion
• Sécurité Microsoft
• Analytique comportementale du Machine Learning
Critères Définir dans SPL Définir dans KQL
Condition de déclencheur • Nombre de résultats
• Nombre d’hôtes
• Nombre de sources
• Personnalisé
Seuil : le nombre de résultats de la requête
Action • Ajouter aux alertes déclenchées
• Journaliser les événements
• Afficher les résultats à rechercher
• Et plus
• Créer une alerte ou un incident
• S’intègre à Logic Apps

Mapper et comparer des exemples de règles

Utilisez ces exemples pour comparer et mapper des règles de Splunk à Microsoft Sentinel dans différents scénarios.

Commandes de recherche courantes

Commande SPL Description Opérateur KQL Exemple KQL
chart/ timechart Retourne des résultats dans une sortie tabulaire pour le graphique de série chronologique. render, opérateur … | render timechart
dedup Supprime les résultats suivants qui correspondent à un critère spécifié. distinct
summarize
… | summarize by Computer, EventID
eval Calcule une expression. En savoir plus sur les commandes eval courantes. extend T | extend duration = endTime - startTime
fields Supprime les champs des résultats de la recherche. project
project-away
T | project cost=price*quantity, price
head/tail Retourne les N premiers ou derniers résultats. top T | top 5 by Name desc nulls last
lookup Ajoute des valeurs de champ à partir d’une source externe. externaldata
lookup
Exemple KQL
rename Renomme un champ. Utiliser des caractères génériques pour spécifier plusieurs champs. project-rename T | project-rename new_column_name = column_name
rex Spécifie des noms de groupe en utilisant des expressions régulières pour extraire des champs. matches regex … | where field matches regex "^addr.*"
search Filtre les résultats correspondant à l’expression de recherche. search search "X"
sort Trie les résultats de la recherche selon les champs spécifiés. sort T | sort by strlen(country) asc, price desc
stats Fournit des statistiques, éventuellement regroupées par champs. En savoir plus sur les commandes statistiques courantes. summarize Exemple KQL
mstats Comme pour les statistiques, utilisées sur des métriques à la place des événements. summarize Exemple KQL
table Spécifie les champs à conserver dans le jeu de résultats et conserve les données au format tabulaire. project T | project columnA, columnB
top/rare Affiche les valeurs les plus ou les moins courantes d’un champ. top T | top 5 by Name desc nulls last
transaction Regroupe les résultats de recherche dans les transactions.

Exemple SPL
Exemple : row_window_session Exemple KQL
eventstats Génère des statistiques récapitulatives à partir de champs de vos événements et enregistre ces statistiques dans un nouveau champ.

Exemple SPL
Exemples :
join
make_list
mv-expand
Exemple KQL
streamstats Rechercher la somme cumulée d’un champ.

Exemple SPL :
... | streamstats sum(bytes) as bytes _ total \| timechart
row_cumsum ...\| serialize cs=row_cumsum(bytes)
anomalydetection Rechercher des anomalies dans le champ spécifié.

Exemple SPL
series_decompose_anomalies() Exemple KQL
where Filtre les résultats de recherche en utilisant des expressions eval. Utilisé pour comparer deux champs différents. where T | where fruit=="apple"

Commande lookup : exemple 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 
])) | ... 

Commande stats : exemple KQL

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

Commande mstats : exemple KQL

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

Commande transaction : exemple SPL

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

Commande transaction : exemple 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

Utilisez row_window_session() pour calculer les valeurs de début de session d’une colonne dans un ensemble de lignes sérialisées.

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

Commande eventstats : exemple SPL

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

Commande eventstats : exemple KQL

Voici un exemple avec l’instruction 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

Voici un exemple avec l’instruction 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

Commande anomalydetection : exemple SPL

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

Commande anomalydetection : exemple 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)

Commandes eval courantes

Commande SPL Description Exemple SPL Commande KQL Exemple KQL
abs(X) Retourne la valeur absolue de X. abs(number) abs() abs(X)
case(X,"Y",…) Prend des paires d’arguments X et Y, où les arguments X sont des expressions booléennes. Quand ils sont évalués à TRUE, les arguments retournent l’argument Y correspondant. Exemple SPL case Exemple KQL
ceil(X) Arrondi vers le haut d’un nombre X. ceil(1.9) ceiling() ceiling(1.9)
cidrmatch("X",Y) Identifie les adresses IP qui appartiennent à un sous-réseau particulier. 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,…) Retourne la première valeur qui n’est pas Null. coalesce(null(), "Returned val", null()) coalesce() coalesce(tolong("not a number"),
tolong("42"), 33) == 42
cos(X) Calcule le cosinus de X. n=cos(0) cos() cos(X)
exact(X) Évalue une expression X en utilisant une arithmétique à virgule flottante double précision. exact(3.14*num) todecimal() todecimal(3.14*2)
exp(X) Retourne eX. exp(3) exp() exp(3)
if(X,Y,Z) Si X est évalué à TRUE, le résultat est le deuxième argument Y. Si X est évalué à FALSE, le résultat est le troisième argument Z. if(error==200,
"OK", "Error")
iif() Exemple KQL
isbool(X) Retourne TRUE si X est booléen. isbool(field) iif()
gettype
iif(gettype(X) =="bool","TRUE","FALSE")
isint(X) Retourne TRUE si X est un entier. isint(field) iif()
gettype
Exemple KQL
isnull(X) Retourne TRUE si X est Null. isnull(field) isnull() isnull(field)
isstr(X) Retourne TRUE si X est une chaîne. isstr(field) iif()
gettype
Exemple KQL
len(X) Cette fonction retourne la longueur en caractères d’une chaîne X. len(field) strlen() strlen(field)
like(X,"y") Retourne TRUE si et seulement si X est similaire au modèle SQLite dans Y. like(field, "addr%") has
contains
startswith
matches regex
Exemple KQL
log(X,Y) Retourne le logarithme du premier argument X en utilisant le deuxième argument Y comme base. La valeur par défaut de Y est 10. log(number,2) log
log2
log10
log(X)

log2(X)

log10(X)
lower(X) Retourne la valeur en minuscule de X. lower(username) tolower tolower(username)
ltrim(X,Y) Retourne X avec les caractères du paramètre Y supprimés à partir du côté gauche. La sortie par défaut de Y est constituée d’espaces et de tabulations. ltrim(" ZZZabcZZ ", " Z") trim_start() trim_start(“ ZZZabcZZ”,” ZZZ”)
match(X,Y) Retourne si X correspond au modèle d’expression régulière Y. match(field, "^\d{1,3}.\d$") matches regex … | where field matches regex @"^\d{1,3}.\d$")
max(X,…) Renvoie la valeur maximale d’une colonne. max(delay, mydelay) max()
arg_max()
… | summarize max(field)
md5(X) Retourne le hachage MD5 d’une valeur de chaîne X. md5(field) hash_md5 hash_md5("X")
min(X,…) Renvoie la valeur minimale d’une colonne. min(delay, mydelay) min_of()
min()
arg_min
Exemple KQL
mvcount(X) Retourne le nombre (total) de valeurs X. mvcount(multifield) dcount …| summarize dcount(X) by Y
mvfilter(X) Filtre un champ à valeurs multiples en fonction de l’expression booléenne X. mvfilter(match(email, "net$")) mv-apply Exemple KQL
mvindex(X,Y,Z) Retourne un sous-ensemble de l’argument à valeurs multiples X à partir d’une position de début (commençant à zéro) Y jusqu’à Z (facultatif). mvindex( multifield, 2) array_slice array_slice(arr, 1, 2)
mvjoin(X,Y) Pour un champ X à valeurs multiples et un délimiteur de chaîne Y, joint les valeurs individuelles de X en utilisant Y. mvjoin(address, ";") strcat_array Exemple KQL
now() Retourne l’heure actuelle, représentée en date/heure Unix. now() now() now()

now(-2d)
null() N’accepte pas d’arguments et retourne NULL. null() null null
nullif(X,Y) Inclut deux arguments X et Y, et retourne X si les arguments sont différents. Sinon, retourne NULL. nullif(fieldA, fieldB) iif iif(fieldA==fieldB, null, fieldA)
random() Retourne un nombre pseudo-aléatoire entre 0 et 2147483647. random() rand() rand()
relative_ time(X,Y) Étant donné une heure Epoch X et un spécificateur d’heure relative Y, retourne la valeur de l’heure Epoch de Y appliquée à X. relative_time(now(),"-1d@d") unix time Exemple KQL
replace(X,Y,Z) Retourne une chaîne formée en remplaçant la chaîne Z pour chaque d’une chaîne d’expression régulière Y dans la chaîne X. Retourne la date avec les numéros de mois et de jour permutés.
Par exemple, pour l’entrée 4/30/2015, la sortie est 30/4/2009 :

replace(date, "^(\d{1,2})/ (\d{1,2})/", "\2/\1/")
replace() Exemple KQL
round(X,Y) Retourne X arrondi au nombre de décimales spécifié par Y. Le comportement par défaut est d’arrondir à un entier. round(3.5) round round(3.5)
rtrim(X,Y) Retourne X avec les caractères de Y supprimés à partir du côté droit. Si Y n’est pas spécifié, les espaces et les tabulations sont supprimés. rtrim(" ZZZZabcZZ ", " Z") trim_end() trim_end(@"[ Z]+",A)
searchmatch(X) Retourne TRUE si l’événement correspond à la chaîne de recherche X. searchmatch("foo AND bar") iif() iif(field has "X","Yes","No")
split(X,"Y") Retourne X en tant que champ à valeurs multiples, séparées par le délimiteur Y. split(address, ";") split() split(address, ";")
sqrt(X) Retourne la racine carrée du nombre X. sqrt(9) sqrt() sqrt(9)
strftime(X,Y) Retourne la valeur de l’heure Epoch X rendue en utilisant le format spécifié par Y. strftime(_time, "%H:%M") format_datetime() format_datetime(time,'HH:mm')
strptime(X,Y) Étant donné une heure représentée par une chaîne X, retourne la valeur analysée d’après le format Y. strptime(timeStr, "%H:%M") format_datetime() Exemple KQL
substr(X,Y,Z) Retourne un champ de sous-chaîne X à partir de la position de début (commençant à 1) Y pour Z caractères (facultatif). substr("string", 1, 3) substring() substring("string", 0, 3)
time() Retourne le temps écoulé avec une résolution en microsecondes. time() format_datetime() Exemple KQL
tonumber(X,Y) Convertit la chaîne d’entrée X en un nombre, où Y (facultatif, valeur par défaut étant 10) définit la base du nombre vers lequel convertir. tonumber("0A4",16) toint() toint("123")
tostring(X,Y) Description Exemple SPL tostring() tostring(123)
typeof(X) Retourne une représentation sous forme de chaîne du type du champ. typeof(12) gettype() gettype(12)
urldecode(X) Retourne l’URL X décodée. Exemple SPL url_decode Exemple KQL

Exemple SPL case(X,"Y",…)

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

Exemple KQL case(X,"Y",…)

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

Exemple KQL if(X,Y,Z)

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

Exemple KQL isint(X)

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

Exemple KQL isstr(X)

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

Exemple like(X,"y")

… | where field has "addr"

… | where field contains "addr"

… | where field startswith "addr"

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

Exemple KQL min(X,…)

min_of (expr_1, expr_2 ...)

…|summarize min(expr)

…| summarize arg_min(Price,*) by Product

Exemple KQL mvfilter(X)

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

Exemple KQL mvjoin(X,Y)

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

Exemple KQL relative time(X,Y)

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

Exemple KQL replace(X,Y,Z)

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

Exemple KQL strptime(X,Y)

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

Exemple KQL time()

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

tostring(X,Y)

Retourne une valeur de champ de X sous forme de chaîne.

  • Si la valeur de X est un nombre, X est remise en forme en valeur de chaîne.
  • Si X est une valeur booléenne, X est remis en forme en TRUE ou FALSE.
  • Si X est un nombre, le deuxième argument Y est facultatif et peut être hex (convertit X en hexadécimal), commas (met en forme X avec des virgules et deux décimales) ou duration (convertit X d’un format d’heure en secondes en un format d’heure lisible : HH:MM:SS).
Exemple SPL tostring(X,Y)

Cet exemple retourne :

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

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

Exemple SPL urldecode(X)

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

Exemple KQL des commandes stats courantes

Commande SPL Description Commande KQL Exemple KQL
avg(X) Retourne la moyenne des valeurs du champ X. avg() avg(X)
count(X) Retourne le nombre d’occurrences du champ X. Pour indiquer une valeur de champ spécifique à mettre en correspondance, mettez en forme X en eval(field="value"). count() summarize count()
dc(X) Retourne le nombre de valeurs distinctes du champ X. dcount() …\| summarize countries=dcount(country) by continent
earliest(X) Retourne la valeur chronologiquement la plus ancienne de X. arg_min() … \| summarize arg_min(TimeGenerated, *) by X
latest(X) Retourne la valeur chronologiquement la plus récente de X. arg_max() … \| summarize arg_max(TimeGenerated, *) by X
max(X) Retourne la valeur maximale du champ X. Si les valeurs de X sont non numériques, la valeur maximale est déterminée d’après l’ordre alphabétique. max() …\| summarize max(X)
median(X) Retourne la valeur la plus proche de la moyenne du champ X. percentile() …\| summarize percentile(X, 50)
min(X) Retourne la valeur minimale du champ X. Si les valeurs de X sont non numériques, la valeur minimale est déterminée d’après l’ordre alphabétique. min() …\| summarize min(X)
mode(X) Retourne la valeur la plus fréquente du champ X. top-hitters() …\| top-hitters 1 of Y by X
perc(Y) Retourne la valeur du centile X du champ Y. Par exemple, perc5(total) retourne la cinquième valeur de centile d’un champ total. percentile() …\| summarize percentile(Y, 5)
range(X) Retourne la différence entre la valeur maximale et la valeur minimale du champ X. range() range(1, 3)
stdev(X) Retourne l’écart type de l’échantillon du champ X. stdev stdev()
stdevp(X) Retourne l’écart type de la population du champ X. stdevp() stdevp()
sum(X) Retourne la somme des valeurs du champ X. sum() sum(X)
sumsq(X) Retourne la somme des carrés des valeurs du champ X.
values(X) Retourne la liste de toutes les valeurs distinctes du champ X sous la forme d’une entrée à valeurs multiples. L’ordre des valeurs est alphabétique. make_set() …\| summarize r = make_set(X)
var(X) Retourne la variance de l’échantillon du champ X. variance variance(X)

Étapes suivantes

Dans cet article, vous avez appris à mapper vos règles de migration de Splunk vers Microsoft Sentinel.