Analyser les logs de Nextcloud avec Wazuh

Sommaire

Bonjour à tous ! Aujourd'hui un article pour parler de sécurité sur Nextcloud : surveiller les logs de Nextcloud en utilisant Wazuh.

Le but étant de pouvoir voir ce qu'il se passe sur un serveur Nextcloud : partage, lecture d'un fichier, authentification...

Introduction

Que ça soit pour des raisons réglementaires (bonjour ISO27001/HDS), légales, que sais-je, vous aurez probablement besoin d'analyser les logs de votre instance Nextcloud (ou tout simplement pour alimenter vos process internes).

Si vous êtes dans un cadre ISO27001 ça rentre notamment dans plusieurs cases de l'annexe A, par exemple :

  • 8.12 - Prévention contre la fuite de données : en créant des règles Wazuh spécifique à vos données critiques/sensibles
  • 8.15 - Journalisation : en récoltant les logs sur l'activité de votre instance
  • 8.16 - Activités de surveillance : en étant alerté sur les comportements anormaux (connexion HNO, etc.)

Dans mon cas, je l'utilise pour lever les alertes relatives au DLP et plus largement pour tracer tous les éléments (partage, connexion, etc.).

Cela permet de faire du DLP (au niveau serveur de fichier) sans solution commerciale (cher et qui fonctionne globalement pas) en utilisant des solutions libres qui juste marchent.

Je vais parler rapidement de Wazuh, mais pour Nextcloud, je vous laisse regarder si vous ne connaissez pas.

Pourquoi Wazuh

Personnellement, j'utilise Wazuh depuis 2017 1er article sur le sujet en 2018. Vous ne l'aurez pas raté : c'est la solution à la mode pour un peu tout : XDR, SIEM, etc.

En bref : c'est une super solution pour alimenter votre gestion des logs ce n'est par contre pas une solution magique. Cela ne remplace pas un EDR ni même une solution de centralisation de log, même si c'est libre, c'est très lourd sur le run : les MàJ (agents/serveur), les alertes, le déploiement... Pour l'utiliser en production depuis 8 ans, il faut bien comprendre ce que ça nécessite et mettre les moyens en face, sinon ça devient un enfer à gérer.

Et même si c'est vendu comme la solution magique à tous vos problèmes, ce n'est pas adapté à tout le monde :

  • Si vous avez personne à mettre devant les alertes (équipe SOC), ça sert à rien
  • Si vous le déployez avant d'avoir fait la gouvernance autour du projet (process/scénarios) : vous allez être noyé sous les alertes
  • Si vous avez pas de solution de gestion de parc automatisé : ça va être compliqué pour le gérer
  • Si vous êtes limite au niveau infra ($$$) ça va être également difficile avec la stack OpenSearch

En dehors de ça : c'est un super produit libre avec une grosse communauté et j'en suis très content depuis presque 10 ans. Il permet de s'interfacer avec la plupart des systèmes (Windows/Aix/GNU/Linux) ou encore des systèmes sans agent via Syslog. Il est très utilisé par les équipes sécurité dans plusieurs domaines : data center, banque, etc.

A une certaine époque on appelait ça un HIDS : Host Intrusion Detected System, c'est (juste) un outil avec un agent qui check les logs et remonte des alertes selon des règles prédéfinies (loin des promesses XDR et bien loin des outils magiques à base d'IA).

Pour le reste et si ça vous intéresse, je vous laisse lire la documentation officielle (très qualitative) ainsi que tous les articles sur le sujet.

Wazuh et Nextcloud

Dans mon cas je fais une configuration/installation sur un serveur Ubuntu Server 24.04 LTS.

Pré-requis

Il faut d'abord avoir activé et configurer l'application Audit/Logging qui va créer le fichier audit.log :

Configuration de Wazuh

Après avoir vérifié la présence du fichier audit.log sur Nextcloud (pour moi, /data/nextcloud/data/audit.log).

Une fois fait, il faut rajouter le fichier à Wazuh dans le fichier /var/ossec/etc/ossec.conf sur l'agent :

1  <localfile>
2    <location>/data/nextcloud/data/audit.log</location>
3    <log_format>json</log_format>
4    <label key="@source">NextCloud</label>
5  </localfile>

En sachant que pour avoir une configuration centralisée, il est aussi possible de faire une configuration via le fichier agent.conf, cela évite de modifier en dur le fichier de conf côté agent.

L'attribut label key permet de son côté de rajouter un champ dans la log une fois arrivé sur le serveur manager pour filtrer les évènements de NextCloud. Dans ce cas, toutes les logs issus du fichier audit.log auront cet attribut.

La log suivante, côté serveur Nextcloud :

1{"reqId":"YyJkyYzSsNT9zHu8H3pm","level":1,"time":"2025-08-26T07:38:55+00:00","remoteAddr":"1.1.1.1","user":"admin","app":"admin_audit","method":"POST","url":"/index.php/login","message":"Login successful: \"admin\"","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36","version":"31.0.5.1","data":{"app":"admin_audit"}}

Deviendra donc, une fois sur le serveur manager :

1{"reqId":"YyJkyYzSsNT9zHu8H3pm","level":1,"time":"2025-08-26T07:38:55+00:00","remoteAddr":"1.1.1.1","user":"admin","app":"admin_audit","method":"POST","url":"/index.php/login","message":"Login successful: \"admin\"","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36","version":"31.0.5.1","data":{"app":"admin_audit"},"@source":"NextCloud"}

Nous avons donc les logs en écoute côté Wazuh, le label et les règles par défaut (déjà présente dans l'outil 0630-nextcloud_rules.xml).

On pourrait donc se dire, ça marche donc et c'est bon ? Oui... Mais non.

Pourquoi y'a pas de données dans le dashboard ?

Une fois cela fait, cela devrait marcher, mais un problème est présent dans le mapping côté template filebeat. Pour indéxer les éléments, un champ data est créé par Wazuh, alors que la log comporte déjà un champ "data":{"app":"admin_audit"} et cela génére une erreur.

Cela veut dire que les logs arrivent bien côté manager, sont bien gérés par les règles mais ne peuvent pas être renvoyées dans le Wazuh-Indexer via filebeat.

L'erreur est la suivante, dans le fichier /var/log/filebeat/filebeat (sur votre serveur filebeat) :

1Cache:publisher.EventCache{m:common.MapStr(nil)}} (status=400): {"type":"mapper_parsing_exception","reason":"failed to parse field [data.data] of type [keyword] in document with id 'tCO44ZgBXTGO9ki5YbEQ'. Preview of field's value: '{app= admin_audit}'","caused_by":{"type":"illegal_state_exception","reason":"Can't get text on a START_OBJECT at 1:199"}}

C'est un problème connu, j'ai retrouvé des cases ouverts sur le sujet :

Il n'existe à vu d'oeil pas de solution officielle côté Wazuh. Plusieurs solutions sont possibles : ne plus utiliser keyword, supprimer via un pipeline les champs data.data...

Dans l'attente d'une solution plus propre, la solution suivante a été appliquée.

Modification sur la machine hébergeant le filebeat du fichier /usr/share/filebeat/module/wazuh/alerts/ingest/pipeline.json pour y rajouter la configuration suivante :

1"rename": {
2"if": "ctx.location == '/data/nextcloud/data/audit.log'",
3"field": "data.data",
4"target_field": "data_json",
5"ignore_missing": true,
6"ignore_

Une fois fait, il faut ré-appliquer le pipeline avec la commande suivante :

1filebeat setup --pipelines

Cela permet tout simplement de changer data.data en data_json. Vous aurez tout de même un warning côté dashboard vu que le mapping n'est pas respecté.

Une fois fait, les logs remontent correctement dans le dashboard mais c'est un bricolage qu'il faudra réappliquer en cas de nouvelle version de pipeline Wazuh/filebeat. Cela permet néanmoins de contourner le problème et de logger correctement.

Règles Wazuh Custom

Par défaut, les règles de Wazuh pour Nextcloud ne remontent pas tous les éléments et certaines actions comme la suppression ne remontent pas d'alerte :

 1Starting wazuh-logtest v4.12.0
 2Type one log per line
 3
 4{"reqId":"hzqvrL3NWXFFxof9Id5E","level":1,"time":"2025-08-27T09:36:02+00:00","remoteAddr":"1.1.1.1","user":"admin","app":"admin_audit","method":"DELETE","url":"/remote.php/dav/files/admin/Templates%20credits.md","message":"File with id \"44\" deleted: \"/admin/files/Templates credits.md\"","userAgent"
 5:"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:142.0) Gecko/20100101 Firefox/142.0","@source":"NextCloud","version":"31.0.5.1","data":{"app":"admin_audit"}}
 6
 7** Wazuh-Logtest: WARNING: (7605): It is not possible to overwrite 'if_sid' value in rule '31100'. The original value is retained.
 8** Wazuh-Logtest: WARNING: (7612): Rule ID '100001' is duplicated. Only the first occurrence will be considered.
 9
10**Phase 1: Completed pre-decoding.
11
12**Phase 2: Completed decoding.
13name: 'json'
14@source: 'NextCloud'
15app: 'admin_audit'
16data.app: 'admin_audit'
17level: '1'
18message: 'File with id "44" deleted: "/admin/files/Templates credits.md"'
19method: 'DELETE'
20remoteAddr: '1.1.1.1'
21reqId: 'hzqvrL3NWXFFxof9Id5E'
22time: '2025-08-27T09:36:02+00:00'
23url: '/remote.php/dav/files/admin/Templates%20credits.md'
24user: 'admin'
25userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:142.0) Gecko/20100101 Firefox/142.0'
26version: '31.0.5.1'
27
28**Phase 3: Completed filtering (rules).
29id: '88208'
30level: '2'
31description: 'NextCloud INFO message.'
32groups: '['json', 'nextcloud']'
33firedtimes: '1'
34mail: 'False'

Cela est dû au fait que les règles sont anciennes selon le repo Github et qu'elles ne matchent par les bons éléments. La règle qui devrait fonctionner est celle-ci :

1  <rule id="88215" level="6">
2    <if_sid>88200,88201</if_sid>
3    <match>File deleted: </match>
4    <description>NextCloud file deleted.</description>
5    <group>pci_dss_10.2.4,pci_dss_10.2.5,gdpr_IV_35.7.d,gdpr_IV_32.2,hipaa_164.312.b,nist_800_53_AU.14,nist_800_53_AC.7,tsc_CC6.1,tsc_CC6.8,tsc_CC7.2,tsc_CC7.3,</group>
6    <options>no_full_log</options>
7  </rule>

Pour corriger on peut donc appliquer les règles suivantes :

 1<!-- File deleted -->
 2<rule id="88215" level="6" overwrite="yes">
 3<if_sid>88200,88201</if_sid>
 4<match>deleted: </match>
 5<description>NextCloud file deleted.</description>
 6        <group>nextcloud,file_deletion,pci_dss_10.2.4,pci_dss_10.2.5,gdpr_IV_35.7.d,gdpr_IV_32.2,hipaa_164.312.b,nist_800_53_AU.14,nist_800_53_AC.7,tsc_CC6.1,tsc_CC6.8,tsc_CC7.2,tsc_CC7.3</group>
 7        <options>no_full_log</options>
 8</rule>
 9
10<!-- File created -->
11<rule id="88214" level="6" overwrite="yes">
12        <if_sid>88200,88201</if_sid>
13        <match>created: </match>
14        <description>NextCloud file created.</description>
15        <group>nextcloud,file_creation,pci_dss_10.2.4,pci_dss_10.2.5,gdpr_IV_35.7.d,gdpr_IV_32.2,hipaa_164.312.b,nist_800_53_AU.14,nist_800_53_AC.7,tsc_CC6.1,tsc_CC6.8,tsc_CC7.2,tsc_CC7.3</group>
16        <options>no_full_log</options>
17</rule>
18
19<!-- File accessed / downloaded -->
20<rule id="88213" level="6" overwrite="yes">
21<if_sid>88200,88201</if_sid>
22<match>accessed: </match>
23<description>NextCloud file accessed / downloaded.</description>
24<group>nextcloud,file_access,pci_dss_10.2.4,pci_dss_10.2.5,gdpr_IV_35.7.d,gdpr_IV_32.2,hipaa_164.312.b,nist_800_53_AU.14,nist_800_53_AC.7,tsc_CC6.1,tsc_CC6.8,tsc_CC7.2,tsc_CC7.3</group>
25<options>no_full_log</options>
26</rule>
27
28<rule id="88202" level="3" overwrite="yes">
29        <if_sid>88200,88201</if_sid>
30        <match>Login attempt: </match>
31        <description>NextCloud authentication attempt.</description>
32        <group>pci_dss_10.2.4,pci_dss_10.2.5,gdpr_IV_35.7.d,gdpr_IV_32.2,hipaa_164.312.b,nist_800_53_AU.14,nist_800_53_AC.7,tsc_CC6.1,tsc_CC6.8,tsc_CC7.2,tsc_CC7.3,</group>
33        <options>no_full_log</options>
34</rule>
35
36</group>

Conclusion

Et voilà, vous avez maintenant toutes les infos pour faire remonter les logs de Nextcloud dans Wazuh. Il vous restera à pousser vos règles custom pour matcher par exemple votre convention de nommage pour les fichiers sensibles (une solution en plus pour le DLP & ISO27001.).

J’espère que cet article vous aura plu, si vous avez des questions ou des remarques sur ce que j’ai pu écrire n’hésitez pas à réagir avec moi en commentaire ou par mail.

Merci pour votre lecture et à bientôt !

Mickael Rigonnaux @tzkuat