Créer un analyseur ASIM
Les utilisateurs de l’Advanced SIEM Information Model (ASIM) utilisent des analyseurs d’unification plutôt que des noms de tableaux dans leurs requêtes afin de voir les données dans un format normalisé et d’ajouter toutes les données pertinentes au schéma dans la requête. Les analyseurs d’unification, à leur tour, utilisent des analyseurs propres à la source pour gérer les détails spécifiques de chaque source.
Microsoft Sentinel fournit des analyseurs prédéfinis propres à la source pour de nombreuses sources de données. Vous pouvez modifier ou développer ces analyseurs propres à la source dans les cas suivants :
Quand votre appareil fournit des événements qui correspondent à un schéma ASIM, mais qu’un analyseur propre à la source pour votre appareil et le schéma approprié ne sont pas disponibles dans Microsoft Sentinel.
Quand des analyseurs ASIM propres à la source sont disponibles pour votre appareil, mais que votre appareil envoie des événements dans une méthode ou un format différent de ceux attendus par les analyseurs ASIM. Par exemple :
Votre appareil source est peut-être configuré pour envoyer des événements de manière non standard.
Votre appareil a peut-être une version différente de celle prise en charge par l’analyseur ASIM.
Les événements sont peut-être collectés, modifiés et transférés par un système intermédiaire.
Processus de développement de l’analyseur personnalisé
Le workflow suivant décrit les étapes générales de développement d’un analyseur ASIM personnalisé propre à la source :
Collectez des exemples de journaux.
Identifiez les schémas, y compris ceux représentés par les événements envoyés par la source.
Mappez les champs d’événement source aux schémas identifiés.
Développez un ou plusieurs analyseurs ASIM pour votre source. Vous devez développer un analyseur de filtrage et un analyseur sans paramètre pour chaque schéma pertinent pour la source.
Testez votre analyseur.
Déployez les analyseurs dans vos espaces de travail Microsoft Sentinel.
Mettez à jour l’analyseur d’unification ASIM approprié pour référencer le nouvel analyseur personnalisé.
Vous pouvez également faire contribuer vos analyseurs à la distribution ASIM principale. Les analyseurs qui contribuent peuvent également être mis à disposition dans tous les espaces de travail en tant qu’analyseurs intégrés.
Collecter des exemples de journaux
Pour créer des analyseurs ASIM efficaces, vous avez besoin d’un ensemble représentatif de journaux, ce qui, dans la plupart des cas, nécessite la configuration du système source et sa connexion à Microsoft Sentinel. Si vous n’avez pas l’appareil source disponible, les services de paiement à l’utilisation cloud vous permettent de déployer de nombreux appareils pour le développement et les tests.
En outre, la recherche de la documentation et des exemples du fournisseur pour les journaux peut aider à accélérer le développement et à réduire les erreurs en garantissant une couverture de format de journal large.
Un ensemble représentatif de journaux doit inclure :
- Événements avec différents résultats d’événement.
- Événements avec différentes actions de réponse.
- Différents formats pour le nom d’utilisateur, le nom d’hôte et les ID, ainsi que d’autres champs qui nécessitent la normalisation des valeurs.
Mappage
Avant de développer un analyseur, mappez les informations disponibles dans le ou les événements source au schéma que vous avez identifié :
- Mappez tous les champs obligatoires et de préférence également les champs recommandés.
- Essayez de mapper toutes les informations disponibles à partir de la source aux champs normalisés. Si elles ne sont pas disponibles dans le cadre du schéma sélectionné, mappez-les aux champs disponibles dans d’autres schémas.
- Mappez les valeurs des champs de la source aux valeurs normalisées autorisées par ASIM. La valeur d’origine est stockée dans un champ distinct, comme EventOriginalResultDetails.
Développement d’analyseurs
Développez à la fois un analyseur de filtrage et sans paramètre pour chaque schéma approprié.
Un analyseur personnalisé est une requête KQL développée dans la page Journaux de Microsoft Sentinel. La requête de l’analyseur a trois parties :
Champs Filtrer > Analyser > Préparer
Filtrage des enregistrements pertinents
Dans de nombreux cas, une table dans Microsoft Sentinel comprend plusieurs types d’événements. Par exemple :
- La table Syslog contient des données provenant de plusieurs sources.
- Les tables personnalisées peuvent inclure des informations provenant d’une source unique qui fournit plusieurs types d’événements et peut s’adapter à différents schémas.
Par conséquent, un analyseur doit d’abord filtrer uniquement les enregistrements pertinents pour le schéma cible.
Le filtrage en KQL s’effectue à l’aide de l’opérateur where. Par exemple, Sysmon event 1 rapporte la création du processus et doit donc être normalisé dans le schéma ProcessEvent. Comme l’événement Sysmon event 1 fait partie de la table Event, vous utilisez le filtre suivant :
Event | where Source == "Microsoft-Windows-Sysmon" and EventID == 1
Important
Un analyseur ne doit pas filtrer par heure. La requête qui utilise l’analyseur applique un intervalle de temps.
Filtrage par type de source à l’aide d’une Watchlist
Dans certains cas, l’événement proprement dit ne contient pas d’informations permettant de filtrer des types de sources spécifiques.
Par exemple, les événements DNS Infoblox sont envoyés en tant que messages Syslog et sont difficiles à distinguer des messages Syslog envoyés depuis d’autres sources. Dans ce cas, l’analyseur s’appuie sur une liste de sources qui définit les événements pertinents. Cette liste est conservée dans la Watchlist ASimSourceType.
Pour utiliser la Watchlist ASimSourceType dans vos analyseurs :
- Insérez la ligne suivante au début de votre analyseur :
let Sources_by_SourceType=(sourcetype:string){_GetWatchlist('ASimSourceType') | where SearchKey == tostring(sourcetype) | extend Source=column_ifexists('Source','') | where isnotempty(Source)| distinct Source };
- Ajoutez un filtre qui utilise la Watchlist dans la section filtrage de l’analyseur. Par exemple, l’analyseur DNS Infoblox comprend les éléments suivants dans la section de filtrage :
| where Computer in (Sources_by_SourceType('InfobloxNIOS'))
Pour utiliser cet échantillon dans votre analyseur :
Remplacez Computer par le nom du champ qui contient les informations sources de votre source. Vous pouvez le conserver comme Computer pour tous les analyseurs basés sur Syslog.
Remplacez le jeton InfobloxNIOS par la valeur de votre choix pour votre analyseur. Informez les utilisateurs de l’analyseur qu’ils doivent mettre à jour la Watchlist ASimSourceType à l’aide de la valeur que vous avez sélectionnée, ainsi que la liste des sources qui envoient des événements de ce type.
Filtrage basé sur les paramètres de l’analyseur
Quand vous développez des analyseurs de filtrage, vérifiez que votre analyseur accepte les paramètres de filtrage pour le schéma correspondant, comme décrit dans l’article de référence pour ce schéma. L’utilisation d’un analyseur existant comme point de départ garantit que votre analyseur comprend la signature de fonction appropriée. Dans la plupart des cas, le code de filtrage réel est identique aussi pour les analyseurs de filtrage du même schéma.
Lors du filtrage, assurez-vous de :
- Filtrez avant d’analyser à l’aide de champs physiques. Si les résultats filtrés ne sont pas suffisamment précis, répétez le test après l’analyse pour affiner vos résultats. Pour plus d’informations, consultez optimisation du filtrage.
- Ne filtrez pas si le paramètre n’est pas défini et possède toujours la valeur par défaut.
Les exemples suivants montrent comment implémenter le filtrage pour un paramètre de chaîne, où la valeur par défaut est généralement « * » et pour un paramètre de liste, où la valeur par défaut est généralement une liste vide.
srcipaddr=='*' or ClientIP==srcipaddr
array_length(domain_has_any) == 0 or Name has_any (domain_has_any)
Optimisation du filtrage
Pour garantir les performances de l’analyseur, notez les recommandations de filtrage suivantes :
- Filtrez toujours les données sur des champs prédéfinis plutôt que sur des champs analysés. Même s’il est parfois plus facile de filtrer en utilisant des champs analysés, l’impact est considérable sur les performances.
- Utilisez des opérateurs qui fournissent des performances optimisées. En particulier ==, has et startswith. L’utilisation d’opérateurs comme contains ou matches regex a également un impact considérable sur les performances.
Les recommandations de filtrage pour optimiser les performances peuvent ne pas être toujours faciles à suivre. Par exemple, l’utilisation de has est moins précise que contains. Dans d’autres cas, le fait de faire correspondre le champ intégré, comme SyslogMessage, est moins précis que la comparaison d’un champ extrait, tel que DvcAction. Dans ce type de cas, nous vous recommandons de toujours préfiltrer les données avec un opérateur d’optimisation des performances sur un champ prédéfini et de répéter le filtre en utilisant des conditions plus exactes après l’analyse.
Pour obtenir un exemple, consultez l’extrait de code d’analyseur Infoblox DNS suivant. L’analyseur vérifie d’abord que le champ SyslogMessage a le mot client. Toutefois, comme le terme peut être utilisé à un autre endroit du message, après l’analyse du champ Log_Type, l’analyseur revérifie que le mot client était bien la valeur du champ.
Syslog | where ProcessName == "named" and SyslogMessage has "client"
…
| extend Log_Type = tostring(Parser[1]),
| where Log_Type == "client"
Analyse
Une fois que la requête sélectionne les enregistrements appropriés, elle peut être amenée à les analyser. En règle générale, l’analyse est nécessaire si plusieurs champs d’événement sont transmis dans un seul champ de texte.
Les opérateurs KQL qui effectuent l’analyse sont listés ci-dessous, classés par optimisation des performances. Le premier offre les performances les plus optimisées, tandis que le dernier offre les performances les moins optimisées.
Opérateur | Description |
---|---|
split | Analyse une chaîne de valeurs délimitées. |
parse_csv | Analyser une chaîne de valeurs au format CSV (valeurs séparées par des virgules). |
parse | Analyser plusieurs valeurs à partir d’une chaîne arbitraire avec un modèle, qui peut être un modèle simplifié offrant de meilleures performances ou une expression régulière. |
extract_all | Analyser des valeurs uniques à partir d’une chaîne arbitraire avec une expression régulière. extract_all présente un niveau de performance similaire à parse si ce dernier utilise une expression régulière. |
extract | Extraire une valeur unique à partir d’une chaîne arbitraire avec une expression régulière. L’utilisation d’extract offre de meilleures performances que parse ou extract_all si une seule valeur est nécessaire. Toutefois, l’utilisation de plusieurs activations de extract sur la même chaîne source est moins efficace qu’un seul parse ou extract_all et doit être évitée. |
parse_json | Analyser les valeurs d’une chaîne au format JSON. Si seules quelques valeurs sont nécessaires à partir du JSON, l’utilisation de parse, extract, ou extract_all offre de meilleures performances. |
parse_xml | Analyser les valeurs d’une chaîne au format XML. Si seules quelques valeurs sont nécessaires à partir du XML, l’utilisation de parse, extract, ou extract_all offre de meilleures performances. |
En plus d’analyser la chaîne, la phase d’analyse peut nécessiter plus de traitement des valeurs d’origine, notamment :
Mise en forme et conversion de type. Une fois extrait, le champ source doit être mis en forme pour correspondre au champ de schéma cible. Par exemple, vous pouvez être amené à convertir une chaîne représentant la date et l’heure en un champ DateHeure. Les fonctions telles que todatetime et tohex sont utiles dans ces cas.
Recherche de valeur. La valeur du champ source, une fois extraite, peut devoir être mappée à l’ensemble de valeurs spécifié pour le champ de schéma cible. Par exemple, certaines sources signalent des codes de réponse DNS numériques, alors que le schéma impose les codes de réponse texte plus courants. Les fonctions iff et case peuvent être utiles pour mapper quelques valeurs.
Par exemple, l’analyseur DNS Microsoft attribue le champ EventResult en fonction de l’ID d’événement et du code de réponse en utilisant une instruction iff, comme suit :
extend EventResult = iff(EventId==257 and ResponseCode==0 ,'Success','Failure')
Pour plusieurs valeurs, utilisez datatable et lookup, comme illustré dans le même analyseur DNS :
let RCodeTable = datatable(ResponseCode:int,ResponseCodeName:string) [ 0, 'NOERROR', 1, 'FORMERR'....]; ... | lookup RCodeTable on ResponseCode | extend EventResultDetails = case ( isnotempty(ResponseCodeName), ResponseCodeName, ResponseCode between (3841 .. 4095), 'Reserved for Private Use', 'Unassigned')
Valeurs de mappage
Dans de nombreux cas, la valeur d’origine extraite doit être normalisée. Par exemple, dans ASIM, une adresse MAC utilise des points-virgules comme séparateur, tandis que la source peut envoyer une adresse MAC délimitée par un trait d’union. L’opérateur principal pour la transformation de valeurs est extend, en plus d’un large ensemble de fonctions KQL de chaîne, de données numériques et de date, comme illustré dans la section Analyse ci-dessus.
Utilisez les instructions case, iff et lookup lorsqu’il est nécessaire de mapper un ensemble de valeurs aux valeurs autorisées par le champ cible.
Lorsque chaque valeur source est mappée à une valeur cible, définissez le mappage à l’aide de l’opérateur datatable et lookup pour le mappage. Par exemple
let NetworkProtocolLookup = datatable(Proto:real, NetworkProtocol:string)[
6, 'TCP',
17, 'UDP'
];
let DnsResponseCodeLookup=datatable(DnsResponseCode:int,DnsResponseCodeName:string)[
0,'NOERROR',
1,'FORMERR',
2,'SERVFAIL',
3,'NXDOMAIN',
...
];
...
| lookup DnsResponseCodeLookup on DnsResponseCode
| lookup NetworkProtocolLookup on Proto
Notez que la recherche est utile et efficace également lorsque le mappage n’a que deux valeurs possibles.
Lorsque les conditions de mappage sont plus complexes, utilisez les fonctions iff ou case. La fonction iff active le mappage de deux valeurs :
| extend EventResult =
iff(EventId==257 and ResponseCode==0,'Success','Failure’)
La fonction case prend en charge plus de deux valeurs cibles. L’exemple ci-dessous montre comment combiner lookup et case. L’exemple lookup ci-dessus renvoie une valeur vide dans le champ DNSResponseCodeName si la valeur de la recherche est introuvable. L’exemple case ci-dessous l’augmente en utilisant le résultat de l’opération lookup si disponible et en spécifiant d’autres conditions dans le cas contraire.
| extend DnsResponseCodeName =
case (
DnsResponseCodeName != "", DnsResponseCodeName,
DnsResponseCode between (3841 .. 4095), 'Reserved for Private Use',
'Unassigned'
)
Préparer les champs du jeu de résultats
L’analyseur doit préparer les champs du jeu de résultats pour que les champs normalisés soient utilisés.
Les opérateurs KQL suivants sont utilisés pour préparer les champs dans votre jeu de résultats :
Opérateur | Description | Utilisation dans un analyseur |
---|---|---|
project-rename | Renomme les champs. | Si un champ existe dans l’événement actuel et doit uniquement être renommé, utilisez project-rename. Le champ renommé se comporte toujours comme un champ prédéfini, et les opérations sur le champ offrent de meilleures performances. |
project-away | Supprime des champs. | Utilisez project-away pour des champs spécifiques que vous souhaitez supprimer du jeu de résultats. Nous vous recommandons de ne pas supprimer les champs d’origine qui ne sont pas normalisés du jeu de résultats, sauf s’ils créent une confusion ou sont très volumineux et peuvent avoir des implications sur les performances. |
project | Sélectionne les champs qui existaient déjà ou qui ont été créés dans le cadre de l’instruction, et supprime tous les autres champs. | Non recommandé pour une utilisation dans un analyseur, car ce dernier ne doit pas supprimer les autres champs qui ne sont pas normalisés. Si vous devez supprimer des champs spécifiques, tels que les valeurs temporaires utilisées pendant l’analyse, utilisez project-away pour les supprimer des résultats. |
extend | Ajoutez des alias. | Outre son rôle dans la génération de champs calculés, l’opérateur extend est également utilisé pour créer des alias. |
Gérer les variantes d’analyse
Dans de nombreux cas, les événements d’un flux d’événements incluent des variantes qui nécessitent une logique d’analyse différente. Pour analyser différentes variantes dans un seul analyseur, utilisez des instructions conditionnelles telles que iff et case, ou utilisez une structure d’union.
Pour utiliser union pour gérer plusieurs variantes, créez une fonction distincte pour chaque variante et utilisez l’instruction d’union pour combiner les résultats :
let AzureFirewallNetworkRuleLogs = AzureDiagnostics
| where Category == "AzureFirewallNetworkRule"
| where isnotempty(msg_s);
let parseLogs = AzureFirewallNetworkRuleLogs
| where msg_s has_any("TCP", "UDP")
| parse-where
msg_s with networkProtocol:string
" request from " srcIpAddr:string
":" srcPortNumber:int
…
| project-away msg_s;
let parseLogsWithUrls = AzureFirewallNetworkRuleLogs
| where msg_s has_all ("Url:","ThreatIntel:")
| parse-where
msg_s with networkProtocol:string
" request from " srcIpAddr:string
" to " dstIpAddr:string
…
union parseLogs, parseLogsWithUrls…
Pour éviter les événements en double et le traitement excessif, assurez-vous que chaque fonction commence par filtrer, à l’aide de champs natifs, uniquement les événements qu’elle vise à analyser. En outre, si nécessaire, utilisez project-away à chaque branche, avant l’union.
Déployer des analyseurs
Déployez des analyseurs manuellement en les copiant dans la page Journal d’Azure Monitor et en enregistrant la demande en tant que fonction. Cette méthode est utile pour effectuer des tests. Pour plus d’informations, consultez Créer une fonction.
Pour déployer un grand nombre d’analyseurs, nous vous recommandons d’utiliser des modèles ARM d’analyseur, de la façon suivante :
Créez un fichier YAML basé sur le modèle correspondant à chaque schéma et ajoutez-y votre requête. Commencez par le modèle YAML correspondant à votre schéma et votre type d’analyseur, filtrage ou omission de paramètre.
Utilisez le convertisseur de fichier YAML ASIM en modèle ARM pour convertir votre fichier YAML en modèle ARM.
Si vous déployez une mise à jour, supprimez les anciennes versions des fonctions à l’aide du portail ou de l’outil PowerShell de suppression de fonction.
Déployez votre modèle en utilisant le portail Azure ou PowerShell.
Vous pouvez également combiner plusieurs modèles dans un même processus de déploiement en utilisant des modèles liés.