Chapitre 1222 minIntermédiaire
Réponse active et notifications : courriel et Teams
Par Josselyn C., prof de BTS SIO. Mis à jour le .
À la fin de ce chapitre, tu sauras
- configurer une réponse active limitée dans le temps ;
- citer les risques d'un blocage automatique et les précautions ;
- envoyer les alertes graves par courriel à travers un relais SMTP ;
- publier les alertes dans un canal Teams avec une intégration.
3 exercices corrigés1 schéma
La réponse active de Wazuh exécute automatiquement une action sur une machine quand une règle se déclenche : bloquer une adresse IP dans le pare-feu local pendant dix minutes, par exemple. Les notifications envoient les alertes graves aux personnes qui doivent agir, par courriel ou dans un canal de messagerie comme Microsoft Teams. Ce chapitre configure une réponse active limitée dans le temps, détaille les risques d'une réaction automatique, puis branche le courriel et Teams, et relie Wazuh à la gestion des incidents et à la supervision.
Comment fonctionne la réponse active
Deux blocs de l'ossec.conf du serveur travaillent ensemble :
- un bloc
<command>déclare un script de réponse : son nom, le programme à lancer, et s'il accepte une durée (timeout_allowed) ; - un bloc
<active-response>déclenche ce script : pour quelles règles (rules_id), ou à partir de quel niveau (level), sur quelle machine (location), pour combien de temps (timeout).
Valeur de location | Le script s'exécute sur |
|---|---|
local | L'agent qui a produit l'événement |
server | Le serveur Wazuh |
defined-agent | Un agent précis, désigné par <agent_id> |
all | Tous les agents |
Quand la règle se déclenche, le serveur envoie l'ordre à l'agent, qui exécute le script avec les droits du système (root ou SYSTEM) en lui passant l'alerte. Avec un timeout, l'agent annule l'action à l'expiration du délai : l'adresse bloquée est débloquée.
Wazuh fournit des scripts prêts à l'emploi. Sous Linux : firewall-drop (ajoute l'adresse source à iptables), firewalld-drop, host-deny (l'ajoute à /etc/hosts.deny), route-null (route vers nulle part), disable-account (désactive un compte), restart-wazuh. Sous Windows : netsh.exe (règle de blocage dans le pare-feu Windows), route-null.exe, restart-wazuh.exe.
Bloquer une adresse après une force brute SSH
srv-web est le serveur le plus exposé. On veut que toute adresse qui déclenche une alerte de force brute SSH soit bloquée sur srv-web pendant dix minutes. La commande firewall-drop est déjà déclarée dans l'ossec.conf du serveur ; il suffit d'ajouter :
<active-response>
<disabled>no</disabled>
<command>firewall-drop</command>
<location>local</location>
<rules_id>5712,5763</rules_id>
<timeout>600</timeout>
</active-response>
Puis on protège les adresses qui ne doivent jamais être bloquées, dans la section <global> du même fichier, à côté des entrées existantes :
<global>
<white_list>192.168.10.208/28</white_list> <!-- VLAN d'administration -->
<white_list>192.168.10.180</white_list> <!-- le serveur Wazuh lui-même -->
</global>
sudo systemctl restart wazuh-manager
Sur srv-web, le script appelle la commande iptables. Sur Debian 13, installe le paquet iptables s'il manque : il pilote en réalité nftables, le pare-feu du noyau. Pour tester, depuis une machine du laboratoire hors de la liste blanche, tape volontairement de mauvais mots de passe SSH vers srv-web jusqu'à déclencher la règle 5763 : la connexion suivante échoue, l'agent écrit l'action dans /var/ossec/logs/active-responses.log, et le tableau de bord montre une alerte de réponse active. Dix minutes plus tard, l'adresse est débloquée.
Les précautions avant d'automatiser
Une réponse automatique agit sans qu'un humain vérifie. Bien réglée, elle ralentit un attaquant ; mal réglée, elle devient une arme contre toi.
| Risque | Exemple | Précaution |
|---|---|---|
| Bloquer un utilisateur légitime | Un administrateur qui se trompe de mot de passe ; ou cinquante salariés qui sortent par la même adresse publique (NAT) et sont tous bloqués d'un coup | Liste blanche des adresses d'administration ; timeout court ; ne jamais bloquer une adresse partagée |
| Être retourné contre soi | Un attaquant forge des messages ou des paquets avec l'adresse source de srv-ad ; la réponse active bloque le contrôleur de domaine, et plus personne ne s'authentifie | Liste blanche des serveurs critiques et de la passerelle ; ne pas brancher de blocage sur des sources faciles à usurper, comme le syslog en UDP (chapitre 5) |
| Bloquer définitivement | Une réponse sans timeout laisse une règle de blocage que personne ne retire | Toujours un timeout ; la décision définitive appartient à un humain |
| Neutraliser ses propres comptes | disable-account déclenché par des échecs de connexion : un attaquant qui connaît la règle désactive les comptes des administrateurs en se trompant volontairement de mot de passe | Pas de disable-account automatique sur des échecs ; seulement sur une alerte de compromission certaine, et jamais sur les comptes d'administration de secours |
| Bloquer au mauvais endroit | firewall-drop ne protège que la machine où il s'exécute ; l'attaquant continue sur les autres | Pour un blocage réseau, une règle sur pfSense, décidée par un humain (règles de pare-feu pfSense) |
Recevoir les alertes par courriel
Le serveur Wazuh sait envoyer des courriels, mais ne gère pas l'authentification SMTP. Or tout serveur de messagerie moderne, celui de l'entreprise comme Microsoft 365, refuse un envoi anonyme. La solution documentée : un relais local, Postfix, installé sur srv-journaux, qui accepte les messages de Wazuh sans authentification sur l'interface locale et les transmet au vrai serveur avec la méthode que celui-ci accepte. Chez Sorbier, le serveur de messagerie interne smtp.sorbier.example accepte un compte d'envoi et son mot de passe.
1. Le relais Postfix. Installe-le (à la question du type de configuration, choisis Système satellite) avec le module d'authentification :
sudo apt install -y postfix libsasl2-modules
Dans /etc/postfix/main.cf, règle le relais vers le serveur de messagerie de Sorbier, en TLS et avec authentification, et n'écoute que la machine elle-même :
inet_interfaces = loopback-only
relayhost = [smtp.sorbier.example]:587
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_tls_security_level = encrypt
Le compte d'envoi et son mot de passe vont dans /etc/postfix/sasl_passwd, protégé :
[smtp.sorbier.example]:587 wazuh@sorbier.example:<MOT_DE_PASSE_DU_COMPTE_D_ENVOI>
sudo chmod 600 /etc/postfix/sasl_passwd
sudo postmap /etc/postfix/sasl_passwd
sudo systemctl restart postfix
echo "Test du relais" | mail -s "Test srv-journaux" securite@sorbier.example # paquet mailutils
2. Wazuh. Dans l'ossec.conf du serveur, les sections <global> et <alerts> existent déjà : modifie leurs valeurs.
<global>
<email_notification>yes</email_notification>
<smtp_server>localhost</smtp_server>
<email_from>wazuh@sorbier.example</email_from>
<email_to>securite@sorbier.example</email_to>
<email_maxperhour>12</email_maxperhour>
</global>
<alerts>
<log_alert_level>3</log_alert_level>
<email_alert_level>12</email_alert_level>
</alerts>
Toute alerte de niveau 12 ou plus part vers la liste securite@sorbier.example. Au-delà de 12 courriels par heure, Wazuh regroupe les alertes dans un seul message, pour ne pas inonder les boîtes pendant une attaque.
3. Des envois ciblés. Un bloc <email_alerts> envoie certaines alertes à une personne précise, sans attendre le regroupement :
<email_alerts>
<email_to>antoine.mercier@sorbier.example</email_to>
<rule_id>100110, 100320</rule_id>
<do_not_delay />
</email_alerts>
Le responsable reçoit immédiatement les modifications nocturnes des groupes d'administration (règle 100110) et les créations de comptes suivies d'une élévation (règle 100320).
Publier les alertes dans Teams
Chez Sorbier, l'équipe informatique travaille dans un canal Microsoft Teams. Y publier les alertes graves les rend visibles de tous, et la discussion sur l'alerte se fait au même endroit. Wazuh intègre nativement Slack, PagerDuty, VirusTotal, Shuffle et Maltiverse ; pour Teams, on écrit une intégration personnalisée.
1. Côté Teams. Les anciens connecteurs de webhooks entrants d'Office 365 ont été retirés en 2026 ; on passe par l'application Workflows. Dans le canal, menu … > Workflows, choisis le modèle d'envoi d'alertes de webhook vers un canal (Send webhook alerts to a channel), indique l'équipe et le canal : Teams donne une URL de webhook. Garde-la comme un secret : quiconque la connaît peut publier dans le canal.
2. Le script. Wazuh appelle un script dont le nom commence par custom-, placé dans /var/ossec/integrations/, avec trois paramètres : le fichier JSON de l'alerte, une clé d'API (inutile ici) et l'URL du webhook. Ce script en Python, /var/ossec/integrations/custom-teams, met l'alerte en forme de carte adaptative (Adaptive Card), le format qu'attend le flux Workflows :
#!/var/ossec/framework/python/bin/python3
# custom-teams : publie une alerte Wazuh dans un canal Teams (webhook créé avec Workflows).
# Wazuh appelle ce script avec trois paramètres : le fichier JSON de l'alerte, la clé d'API
# (vide ici) et l'URL du webhook (hook_url).
import json
import sys
import urllib.request
def carte(alerte):
regle = alerte.get("rule", {})
agent = alerte.get("agent", {})
techniques = ", ".join(regle.get("mitre", {}).get("id", [])) or "aucune"
faits = [
{"title": "Niveau", "value": str(regle.get("level", "?"))},
{"title": "Règle", "value": str(regle.get("id", "?"))},
{"title": "Agent", "value": agent.get("name", "?")},
{"title": "ATT&CK", "value": techniques},
{"title": "Heure", "value": alerte.get("timestamp", "?")},
]
return {
"type": "message",
"attachments": [
{
"contentType": "application/vnd.microsoft.card.adaptive",
"content": {
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.4",
"body": [
{
"type": "TextBlock",
"text": "Wazuh : " + regle.get("description", "alerte"),
"weight": "Bolder",
"size": "Medium",
"wrap": True,
},
{"type": "FactSet", "facts": faits},
],
},
}
],
}
def main():
fichier_alerte, hook_url = sys.argv[1], sys.argv[3]
with open(fichier_alerte, encoding="utf-8") as f:
alerte = json.load(f)
corps = json.dumps(carte(alerte)).encode("utf-8")
requete = urllib.request.Request(
hook_url, data=corps, headers={"Content-Type": "application/json"}
)
with urllib.request.urlopen(requete, timeout=10) as reponse:
print("Teams a répondu", reponse.status)
if __name__ == "__main__":
main()
La première ligne désigne le Python livré avec le serveur Wazuh : pas besoin d'en installer un autre. Le script n'utilise que la bibliothèque standard. Donne-lui les bons droits :
sudo chmod 750 /var/ossec/integrations/custom-teams
sudo chown root:wazuh /var/ossec/integrations/custom-teams
3. Le branchement. Dans l'ossec.conf du serveur :
<integration>
<name>custom-teams</name>
<hook_url>https://URL-DONNEE-PAR-WORKFLOWS</hook_url>
<level>12</level>
<alert_format>json</alert_format>
</integration>
Redémarre wazuh-manager. Chaque alerte de niveau 12 ou plus est publiée dans le canal sous forme de carte : description, niveau, règle, machine, techniques ATT&CK et heure. Des filtres <rule_id> ou <group> restreignent ce qui part. En cas de souci, le journal /var/ossec/logs/integrations.log dit ce qui s'est passé. N'oublie pas le flux : srv-journaux doit pouvoir joindre les services de Microsoft en HTTPS, ce que le pare-feu de Sorbier n'autorise pas par défaut pour un serveur du VLAN 20.
Relier les alertes à la gestion des incidents
Une notification n'est utile que si elle débouche sur une action tracée. Deux liens à établir :
- Avec l'outil de tickets. GLPI sait créer un ticket à partir d'un courriel reçu sur une boîte dédiée (ses collecteurs). En envoyant les alertes de niveau 12 et plus vers cette boîte, chaque alerte grave devient un ticket, avec un responsable, un statut et un historique. Le cours GLPI et gestion de parc présente l'outil.
- Avec la procédure de réponse. Une alerte qualifiée en incident déclenche la réponse à incident : main courante, confinement, éradication, retour à la normale, retour d'expérience. Si des données personnelles sont touchées, l'obligation de notifier la CNIL sous 72 heures s'applique.
Superviser Wazuh lui-même
Un SIEM en panne ne détecte plus rien, et personne ne s'en aperçoit : aucune alerte, c'est aussi ce qu'on voit quand tout va bien. La supervision de Sorbier, avec Zabbix (cours Supervision), doit donc surveiller srv-journaux comme n'importe quel serveur critique :
| Ce que la supervision surveille | Pourquoi |
|---|---|
L'état des services wazuh-indexer, wazuh-manager, filebeat et wazuh-dashboard | Un service arrêté coupe la chaîne de détection |
| L'espace disque, surtout celui des données de l'indexeur | Disque presque plein : l'indexeur bloque les écritures, les alertes ne sont plus stockées |
| La mémoire et la charge | L'indexeur est le premier à souffrir d'un manque de mémoire |
| Le nombre d'agents actifs | Une chute brutale signale un problème réseau, ou une attaque qui coupe les agents |
| La présence d'alertes récentes | Zéro alerte en une heure, sur un parc actif, est une anomalie |
À l'inverse, Grafana peut afficher des données de Wazuh : l'indexeur parle le même langage qu'OpenSearch, et Grafana sait l'interroger avec sa source de données OpenSearch. Un même écran peut ainsi montrer la charge des serveurs (Zabbix) et le nombre d'alertes de sécurité (Wazuh). Le tableau de bord de Wazuh reste l'outil d'enquête ; Grafana, celui de la vue d'ensemble.
Exercices
Exercice 1 sur 3 Configurer une réponse active Réussi À revoir
Sorbier publie un serveur SFTP, srv-depot, sous Debian, pour ses clients. Ses journaux SSH arrivent dans Wazuh comme ceux de srv-web. Écris le bloc <active-response> qui bloque pendant 30 minutes, sur ce seul serveur, toute adresse qui déclenche une force brute SSH (sur des comptes existants ou non), et dis quelles adresses tu mets en liste blanche.
Voir la réponseMasquer la réponse de l'exercice 1
La réponse active se branche sur une règle ; pour viser une seule machine, on crée la règle qui ne correspond qu'à elle. Dans local_rules.xml, une règle enfant des deux règles de force brute SSH (5712 sur des comptes inexistants, 5763 sur des comptes existants), limitée à srv-depot :
<group name="sorbier,sshd,">
<rule id="100160" level="10">
<if_sid>5712,5763</if_sid>
<hostname>^srv-depot$</hostname>
<description>Sorbier : force brute SSH sur srv-depot</description>
<mitre>
<id>T1110</id>
</mitre>
</rule>
</group>
Puis, dans l'ossec.conf du serveur :
<active-response>
<disabled>no</disabled>
<command>firewall-drop</command>
<location>local</location>
<rules_id>100160</rules_id>
<timeout>1800</timeout>
</active-response>
<hostname> compare le nom de machine de l'en-tête syslog du journal, ici srv-depot. location vaut local : le blocage s'exécute sur l'agent qui a vu l'attaque, c'est-à-dire srv-depot, la seule machine dont les journaux déclenchent la règle 100160. Une force brute contre srv-web reste signalée par 5712 ou 5763, sans blocage. Liste blanche : le VLAN d'administration 192.168.10.208/28, le serveur Wazuh, la passerelle, et les adresses publiques des clients connus si elles sont fixes, pour qu'un client qui se trompe de mot de passe ne soit pas coupé de son service. Le délai de 1 800 secondes reste un frein ; la vraie protection est l'authentification par clé.
Tu avais trouvé ?
Exercice 2 sur 3 Le blocage retourné Réussi À revoir
Un collègue propose : « Branchons firewall-drop en location all sur la règle 87702 du pare-feu (balayage) : toute adresse qui balaie sera bloquée sur toutes nos machines. » Donne deux raisons de refuser, et une alternative.
Voir la réponseMasquer la réponse de l'exercice 2
- L'usurpation : la règle 87702 se fonde sur le journal syslog du pare-feu, et un balayage se fait souvent avec des paquets dont l'adresse source est facile à falsifier. Un attaquant qui envoie des paquets « venant » de
192.168.10.177ferait bloquer le contrôleur de domaine sur toutes les machines : plus d'authentification, plus de DNS. C'est un déni de service déclenché par nos propres défenses. - La portée :
allexécute le blocage sur tous les agents, y compris les contrôleurs de domaine et le serveur Wazuh ; une erreur se paie partout à la fois. Et un balayage venu d'Internet est déjà arrêté par le pare-feu, puisque c'est lui qui l'a bloqué.
Alternative : notification seule pour les balayages venus de l'intérieur (une machine interne qui balaie est à examiner par un humain), et rien pour ceux venus d'Internet, que pfSense bloque déjà. Si un blocage réseau est nécessaire, il se décide et se pose sur pfSense, avec une liste blanche, par un administrateur.
Tu avais trouvé ?
Exercice 3 sur 3 Les courriels qui n'arrivent pas Réussi À revoir
Après avoir réglé <email_notification>yes</email_notification> et <smtp_server>smtp.office365.com</smtp_server> dans l'ossec.conf, un technicien ne reçoit aucun courriel, même pour une alerte de niveau 13. Explique pourquoi et décris la correction.
Voir la réponseMasquer la réponse de l'exercice 3
Wazuh ne gère pas l'authentification SMTP : il envoie le message sans identifiant, et le service de messagerie de Microsoft 365, comme tout serveur moderne, refuse un envoi non authentifié. La correction est celle du chapitre : un relais Postfix local (<smtp_server>localhost</smtp_server> dans Wazuh) qui transmet au service de messagerie avec la méthode qu'il accepte : authentifié pour un serveur interne (port 587, TLS, compte d'envoi dédié), connecteur par adresse IP pour Microsoft 365, qui désactive par défaut l'authentification SMTP par mot de passe à partir de décembre 2026 (relais vers <domaine>.mail.protection.outlook.com, port 25, en TLS). On teste d'abord le relais seul avec la commande mail, puis avec une alerte de niveau 12, et on lit /var/log/mail.log en cas d'échec. Il faut aussi que le flux sortant correspondant (TCP 587 ou 25) soit autorisé par le pare-feu.
Tu avais trouvé ?