
Scanner de malware Linux multi-moteur avec cinq étapes de détection (MD5, motif HEX, YARA, ClamAV, statistique), surveillance inotify en temps réel, quarantaine et alertes multi-canaux
Scanner de malwares pour Linux — détection des menaces multi-étapes (MD5, SHA-256, HEX, YARA, analyse statistique), intégration ClamAV, surveillance inotify en temps réel, opérations de quarantaine/nettoyage/restauration et alertes multi-canaux (email, Slack, Telegram, Discord).
(C) 2002-2026, R-fx Networks <[email protected]>
(C) 2026, Ryan MacDonald <[email protected]>
Sous licence GNU GPL v2
Moteur de scan natif 43x plus rapide — le pipeline de scan natif a été entièrement réécrit avec un traitement parallèle par lots. Benchmark réel sur ~10 000 fichiers :
| Version | Temps | Fichiers | Détections |
|---|---|---|---|
| v1.6.6 | 1,217s | 9,931 | 35 |
| v2.0.1 | 28s | 9,931 | 35 |
La correspondance des signatures MD5 et HEX utilise désormais grep par lots avec des workers parallèles Aho-Corasick, éliminant la surcharge de compilation des motifs par fichier et ~500 000 forks de sous-processus par scan. Configurez le nombre de workers parallèles avec scan_workers (par défaut : auto).
Autres points saillants : gestion du cycle de vie des scans (--kill, --pause, --stop/--continue, -L), analyse des hashs SHA-256 avec détection automatique du matériel CPU (scan_hashtype), scan YARA natif (scan_yara=1), alertes via webhook Discord, correctifs des alertes Slack/Telegram, prise en charge des wildcards hexadécimaux ClamAV dans le moteur natif, et plus de 200 correctifs de bogues dans l'ensemble de la base de code. Voir CHANGELOG pour tous les détails.
./install.sh
maldet -a /home/?/public_html
maldet -r /home/?/public_html 2
maldet -co scan_yara=1 -a /home/?/public_html
maldet -q SCANID
maldet -m users
maldet -u
---
## 1. Introduction
Architecture de LMD, étapes de détection et plateformes prises en charge.
Linux Malware Detect (LMD) est un scanner de malwares pour Linux publié sous licence GNU GPLv2, conçu autour des menaces rencontrées dans les environnements d'hébergement mutualisé. Il utilise les données de menace des systèmes de détection d'intrusion en périphérie de réseau pour extraire les malwares activement utilisés dans les attaques et génère des signatures pour leur détection. En outre, les données de menace proviennent de soumissions d'utilisateurs via la fonctionnalité de vérification (checkout) de LMD et de ressources communautaires dédiées aux malwares.
LMD se concentre sur les classes de malwares que les produits antivirus traditionnels manquent fréquemment : shells PHP, injecteurs JavaScript, backdoors encodées en base64, bots IRC et autres menaces de la couche application web qui ciblent les comptes d'utilisateurs d'hébergement mutualisé plutôt que les composants internes du système d'exploitation.
**Étapes de détection**
- Correspondance d'empreintes MD5 pour l'identification exacte des menaces
- Correspondance de motifs HEX via le moteur natif de recherche par lots (grep) avec workers parallèles
- Analyse par signatures composées (csig) avec logique booléenne multi-motifs (AND/OR/seuil), correspondance insensible à la casse, correspondance étendue (UTF-16LE) et jokers à espacement borné
- Analyse native de règles YARA avec prise en charge complète des modules et règles personnalisées
- Analyse statistique de la longueur des chaînes pour détecter les menaces obscurcies (base64, gzinflate)
- Intégration ClamAV pour une couverture étendue avec les signatures ClamAV maintenues par LMD
**Analyse et surveillance**
- Analyse de tous les fichiers, des fichiers récemment modifiés ou d'une liste de fichiers
- Surveillance de fichiers en temps réel via l'inotify du noyau (événements create/modify/move)
- Analyse des téléversements HTTP via le hook `inspectFile` de ModSecurity2
- Analyse en arrière-plan pour les opérations massives sans surveillance
- Filtrage par expression régulière d'inclusion/exclusion par analyse
**Quarantaine et réponse**
- File de quarantaine avec stockage de fichiers à zéro permission
- Quarantaine/restauration par lot par identifiant d'analyse
- Règles de nettoyage spécifiques aux signatures pour la suppression des malwares
- Restauration complète des fichiers (contenu, propriétaire, permissions, mtime)
**Alertes et rapports**
- Alertes e-mail HTML + texte avec le design unifié rfxn (marque bleu sarcelle, entrées en cartes)
- Prise en charge du relais SMTP (TLS/SSL) pour les environnements sans MTA local
- Alertes par entrée via Slack Block Kit, Telegram MarkdownV2, Discord embed
- Modèles d'alerte personnalisables via les remplacements `alert/custom.d/`
- Rapports d'analyse avec détails de correspondance par fichier, types de correspondance codés par couleur
**Infrastructure**
- Liaison automatique des signatures ClamAV pour une couverture double moteur
- Cron quotidien avec détection automatique de plus de 12 panneaux de contrôle d'hébergement
- Contrôle des ressources CPU/IO (nice, ionice, cpulimit)
- Mises à jour automatiques des signatures et de la version
- Unité de service systemd et prise en charge du script init SysV
### Plateformes prises en charge
LMD fonctionne sur toute distribution Linux avec bash et les utilitaires GNU standard. Plateformes testées :
| Plateforme | Système d'init | Chemin de configuration du paquet |
|----------|-------------|---------------------|
| RHEL / Rocky / AlmaLinux 8, 9, 10 | systemd | `/etc/sysconfig/maldet` |
| CentOS 6, 7 | SysV / systemd | `/etc/sysconfig/maldet` |
| Debian 10, 11, 12 | systemd | `/etc/default/maldet` |
| Ubuntu 20.04, 22.04, 24.04 | systemd | `/etc/default/maldet` |
| Gentoo | OpenRC | — |
| Slackware | SysV | — |
| FreeBSD | — | — (partiel ; pas d'inotify) |
---
## 2. Installation
Installation, mise à niveau et suppression de LMD d'un système.
Le script `install.sh` inclus gère toutes les tâches d'installation. Les installations précédentes sont automatiquement sauvegardées.```bash
./install.sh
L'installateur :
/usr/local/maldetectmaldet dans /usr/local/sbin//etc/cron.daily/maldetconf.maldet), les signatures personnalisées et les fichiers d'exclusion lors des mises à niveauLes installations précédentes sont enregistrées dans /usr/local/maldetect.bk{PID} avec un lien symbolique maldetect.last vers la sauvegarde la plus récente.
Chemins par défaut :
/usr/local/maldetect/usr/local/sbin/maldet/etc/cron.daily/maldet/usr/lib/systemd/system/maldet.serviceTous les paramètres destinés à l'utilisateur et leurs valeurs par défaut. Voir man maldet(1) pour la référence complète.
Le fichier de configuration principal est /usr/local/maldetect/conf.maldet. Toutes les options sont commentées pour faciliter la configuration. Les options utilisent 0/1 pour désactiver/activer, sauf indication contraire.
La configuration peut également être remplacée au moment de l'exécution à l'aide de l'option -co :```bash
maldet -co quarantine_hits=1,email_addr=[email protected] -a /home
### 3.1 Options générales
| Variable | Description | Défaut |
|----------|---------|---------|
| `autoupdate_signatures` | Mettre à jour automatiquement les signatures chaque jour via cron | `1` |
| `autoupdate_version` | Mettre à jour automatiquement la version de LMD chaque jour via cron | `1` |
| `autoupdate_version_hashed` | Vérifier le hash SHA-256 de l'exécutable LMD par rapport à la version en amont (repli sur MD5) | `1` |
| `sigup_interval` | Heures entre les vérifications automatiques de mise à jour des signatures via une tâche cron indépendante (`/etc/cron.d/maldet-sigup`) ; 0 = désactivé | `6` |
| `cron_prune_days` | Jours de conservation des données de quarantaine/session/temp | `21` |
| `cron_daily_scan` | Activer l'analyse automatique quotidienne via cron | `1` |
| `scan_days` | Jours à prendre en compte pour les fichiers modifiés lors des analyses cron quotidiennes | `1` |
| `import_config_url` | URL de téléchargement d'une configuration distante de remplacement | — |
| `import_config_expire` | Expiration du cache pour la configuration importée (secondes) | `43200` |
| `sig_import_md5_url` | URL de téléchargement des signatures MD5 personnalisées | — |
| `sig_import_hex_url` | URL de téléchargement des signatures HEX personnalisées | — |
| `sig_import_yara_url` | URL de téléchargement des règles YARA personnalisées | — |
| `sig_import_sha256_url` | URL de téléchargement des signatures SHA-256 personnalisées | — |
| `sig_import_csig_url` | URL de téléchargement des signatures composées personnalisées | — |
| `session_legacy_compat` | Générer des fichiers de session texte brut hérités en plus du TSV : `auto` (détecter les sessions au format ancien), `1` (toujours), `0` (TSV uniquement) | `auto` |
### 3.2 Alertes
| Variable | Description | Défaut |
|----------|---------|---------|
| `email_alert` | Activer les alertes par e-mail après les analyses | `0` |
| `email_addr` | Adresse du destinataire des alertes | `[email protected]` |
| `email_subj` | Modèle d'objet de l'e-mail | `maldet alert from $(hostname)` |
| `email_ignore_clean` | Supprimer les alertes lorsque toutes les détections ont été nettoyées | `1` |
| `email_panel_user_alerts` | Envoyer des alertes aux utilisateurs du panneau lors d'une détection | `0` |
| `email_panel_from` | En-tête De pour les alertes des utilisateurs du panneau | `[email protected]` |
| `email_panel_replyto` | En-tête Répondre à pour les alertes des utilisateurs du panneau | `[email protected]` |
| `email_panel_alert_subj` | Objet des alertes pour les utilisateurs du panneau | `maldet alert from $(hostname)` |
| `email_format` | Format de l'e-mail : `text`, `html` ou `both` | `html` |
| `smtp_relay` | URL du relais SMTP (par ex., `smtps://smtp.gmail.com:465`) | — |
| `smtp_from` | Adresse de l'expéditeur pour l'envoi via relais SMTP | — |
| `smtp_user` | Nom d'utilisateur pour l'authentification SMTP | — |
| `smtp_pass` | Mot de passe pour l'authentification SMTP | — |
| `slack_alert` | Activer les alertes Slack par téléversement de fichier | `0` |
| `slack_subj` | Nom de fichier pour le téléversement Slack | `maldet alert from $(hostname)` |
| `slack_token` | Jeton de l'API Bot Slack (portées : `files:write`, `files:read`) | — |
| `slack_channels` | Liste de noms ou d'identifiants de canaux séparés par des virgules | `maldetreports` |
| `telegram_alert` | Activer les alertes Telegram | `0` |
| `telegram_bot_token` | Jeton de l'API Bot Telegram | — |
| `telegram_channel_id` | Identifiant du chat ou du groupe Telegram | — |
| `discord_alert` | Activer les alertes Discord via webhook | `0` |
| `discord_webhook_url` | URL du webhook Discord pour l'envoi des alertes | — |
### 3.3 Options d'analyse
| Variable | Description | Défaut |
|----------|---------|---------|
| `scan_hashtype` | Algorithme de hachage pour l'étape 1 : `auto`, `sha256`, `md5`, `both` | `auto` |
| `scan_max_depth` | Profondeur maximale de répertoire pour find | `15` |
| `scan_min_filesize` | Taille de fichier minimale à analyser | `24` octets |
| `scan_max_filesize` | Taille de fichier maximale à analyser | `2048k` |
| `scan_hexdepth` | Profondeur en octets pour la correspondance des signatures HEX | `262144` |
| `scan_hex_chunk_size` | Fichiers par micro-lot lors de l'analyse HEX+CSIG (plage : 1024-20480) | `10240` |
| `scan_csig` | Activer l'analyse par signatures composées (csig) (mode natif uniquement) | `1` |
| `scan_workers` | Workers parallèles pour les passes d'analyse MD5, SHA-256, HEX et CSIG | `auto` |
| `scan_cpunice` | Priorité nice du processus d'analyse (-19 à 19) | `19` |
| `scan_ionice` | Priorité de la classe d'ordonnancement E/S (0 à 7) | `6` |
| `scan_cpulimit` | Limite CPU stricte en pourcentage (0=désactivé) | `0` |
| `scan_ignore_root` | Ignorer les fichiers appartenant à root lors des analyses (non appliqué en mode surveillance par défaut ; voir `monitor_scan_owner_filters`) | `1` |
| `scan_ignore_user` | Ignorer les fichiers appartenant à des utilisateurs spécifiques | — |
| `scan_ignore_group` | Ignorer les fichiers appartenant à des groupes spécifiques | — |
| `scan_user_access` | Autoriser les utilisateurs non root à lancer des analyses | `0` |
| `scan_user_access_minuid` | UID minimal pour la création des répertoires utilisateur avec --mkpubpaths | `100` |
| `scan_find_timeout` | Délai d'expiration pour la génération de la liste de fichiers find (0=désactivé, min 60 s, 14400=4 h recommandé) | `0` |
| `scan_export_filelist` | Enregistrer les résultats de find dans tmp/find_results.last | `0` |
| `scan_tmpdir_paths` | Chemins temporaires inscriptibles par tous inclus dans les analyses -a/-r | `/tmp /var/tmp /dev/shm /var/fcgi_ipc` |
| `string_length_scan` | Activer l'analyse statistique de la longueur des chaînes | `0` |
| `string_length` | Longueur minimale de chaîne suspecte | `150000` |
| `scan_progress_log_interval` | Secondes entre les points de contrôle du journal de progression lors des analyses en arrière-plan (0=désactivé) | `60` |
| `scan_meta_cleanup_age` | Heures de conservation des fichiers méta d'analyse terminés/interrompus (0=désactivé) | `48` |
| `maint_compress_age` | Jours avant que les fichiers de session terminés soient compressés en gzip (0=désactivé) | `30` |
| `maint_archive_age` | Jours avant que les sessions compressées soient regroupées dans des archives mensuelles (0=désactivé) | `90` |
### 3.4 Analyse YARA
L'analyse YARA native invoque le binaire `yara` (ou `yr` de YARA-X) indépendamment de ClamAV, et prend en charge les modules YARA complets, les règles compilées et les fichiers de règles personnalisés que le sous-ensemble YARA limité de ClamAV ne peut pas traiter. Lorsque les deux sont disponibles, `yr` (YARA-X) est préféré. En mode `auto`, l'analyse YARA native n'est activée que si ClamAV est indisponible et qu'un binaire yara/yr est trouvé, évitant ainsi la double évaluation des règles.
| Variable | Description | Défaut |
|----------|---------|---------|
| `scan_yara` | Activer l'étape d'analyse YARA native : `auto` (détecter le binaire, repli sur ClamAV), `0` (désactivé), `1` (activé) | `auto` |
| `scan_yara_timeout` | Délai d'expiration en secondes (0=aucun délai) | `300` |
| `scan_yara_scope` | Portée des règles lorsque ClamAV est également actif : `all` (analyse native complète) ou `custom` (uniquement les règles personnalisées en natif, ClamAV gère rfxn.yara) | `custom` |
| `sig_import_yara_url` | URL de téléchargement des règles YARA personnalisées lors de la mise à jour des signatures | — |
**Règles YARA personnalisées** peuvent être placées à deux emplacements, tous deux préservés lors des mises à niveau :
- `sigs/custom.yara` — règles dans un fichier unique
- `sigs/custom.yara.d/` — répertoire drop-in pour les fichiers de règles `.yar` et `.yara`
Compatible avec les ensembles de règles tiers tels que [YARA Forge](https://yarahq.github.io/) et [Signature Base](https://github.com/Neo23x0/signature-base). Les règles compilées (sortie de `yarac`) sont également prises en charge via `sigs/compiled.yarc`.
**Analyse par lots :** YARA 4.0+ et toutes les versions de YARA-X utilisent `--scan-list` pour une analyse par lots efficace des fichiers. Les versions plus anciennes de YARA reviennent automatiquement à une analyse fichier par fichier.
Activer à l'exécution sans modifier la configuration :```bash
maldet -co scan_yara=1 -a /home/?/public_html
Un script hook configurable peut être invoqué après la fin d'un scan, recevant
les résultats du scan via des arguments positionnels, des variables d'environnement LMD_*, et
éventuellement du JSON sur stdin. Le hook n'interrompt jamais le scan — les échecs sont
journalisés, mais pas fatals. Voir maldet(1) pour le contrat complet du hook.
Lorsque le scan ClamAV est activé (scan_clamscan=1 ou auto avec un binaire détecté), LMD sélectionne le meilleur moteur ClamAV disponible par ordre de priorité :
clamdscan distant (si scan_clamd_remote=1 et que la config existe)clamd local exécuté en tant que rootclamd local exécuté en tant que non-root (avec --fdpass)clamscan (repli, plus lent)Les signatures LMD sont automatiquement liées par symlinks vers les répertoires de données ClamAV par install.sh, donnant à ClamAV accès aux signatures MD5 (rfxn.hdb), HEX (rfxn.ndb) et YARA (rfxn.yara) de LMD.
Contrôle de validation des signatures : Avant de déployer des signatures mises à jour vers les répertoires de données ClamAV, LMD les valide via clamscan -d contre un répertoire de transit. Si la validation échoue, les signatures LMD existantes sont supprimées du chemin ClamAV afin d'empêcher des bases malformées de casser ClamAV. Le signal de rechargement SIGUSR2 envoyé à clamd n'est émis que lorsqu'au moins un répertoire de données ClamAV passe la validation (problème #467).
| Variable | Fonction | Défaut |
|---|---|---|
scan_clamscan | Activer ClamAV comme moteur de scan : auto (détecte le binaire à l'exécution), 0 (désactivé), 1 (activé) | auto |
Les sources ultérieures remplacent les valeurs précédentes :
internals/internals.conf — chemins internes, découverte des binaires, définitions d'URLconf.maldet — configuration utilisateurinternals/compat.conf — correspondances de variables obsolètes/etc/sysconfig/maldet ou /etc/default/maldet — surcharges système-co|--config-option — surcharges à l'exécutionInterface en ligne de commande, codes de sortie et exemples courants. Voir man maldet(1) pour la référence complète des options.```
usage: maldet [OPTION] [ARGUMENT]
SCANNING: -a, --scan-all PATH scan all files in path (wildcard: ?) -r, --scan-recent PATH DAYS scan files created/modified in last X days -f, --file-list FILE scan files from a line-separated file list -b, --background run scan in the background
SCAN FILTERS: -i, --include-regex REGEX include only matching paths -x, --exclude-regex REGEX exclude matching paths -co, --config-option V=V,... override config options at runtime -U, --user USER run as specified user
MONITORING: -m, --monitor USERS|PATHS|FILE|RELOAD start inotify monitoring -k, --kill-monitor stop inotify monitoring
SCAN MANAGEMENT: -L, --list-active list active scans (text/json/tsv) --kill SCANID abort a running scan --pause SCANID [DURATION] pause a running scan (e.g., 2h, 30m) --unpause SCANID resume a paused scan --stop SCANID checkpoint and stop a running scan --continue SCANID resume a stopped scan from checkpoint --maintenance rotate histories, compress/archive old sessions
QUARANTINE & RESTORE: -q, --quarantine SCANID quarantine hits from scan -n, --clean SCANID clean malware from scan hits -s, --restore FILE|SCANID restore quarantined file(s) -qd PATH override quarantine directory for this run
REPORTING: -e, --report [SCANID|list|latest|hooks|active] view scan report --all show full history with -e list (default: recent) --format text|json|html|tsv set report output format (default: text) --mailto ADDRESS email report to address --json-report [SCANID|list] shorthand: --report --format json --alert-daily generate inotify monitor digest alert --digest fire unified digest (monitor + hook sources) -l, --log view event log
UPDATES: -u, --update-sigs [--force] update malware signatures -d, --update-ver [--force|--beta] update LMD version --cron-sigup cron sig update (internal use)
OTHER: -p, --purge clear logs, quarantine, temp data -c, --checkout FILE submit suspected malware to rfxn.com --test-alert TYPE CHANNEL test alert delivery (scan|digest, email|slack|telegram|discord) --mkpubpaths create per-user pub/ data directories --web-proxy IP:PORT set HTTP/HTTPS proxy -hscan, --hook-scan scan via service hook (internal use) -v, --version show version information -h, --help show detailed help
### 4.1 Codes de sortie
| Code | Signification |
|------|---------------|
| `0` | Succès, aucune détection de malware |
| `1` | Erreur ou tous les chemins de scan inexistants |
| `2` | Détections de malware trouvées |
**Exemples :**```bash
# Scan all files under user web roots
maldet -a /home/?/public_html
# Scan recent files with auto-quarantine and YARA enabled
maldet -co quarantine_hits=1,scan_yara=1 -r /home/?/public_html 2
# Background scan with email alert to specific address
maldet -b -co [email protected] -a /var/www
# View the most recent scan report
maldet -e
# Email a specific report
maldet --mailto [email protected] -e 050910-1534.21135
# Output scan report as JSON (pipe to jq for formatting)
maldet --format json -e 050910-1534.21135
# List all reports as JSON
maldet --format json -e list
# Shorthand JSON output (equivalent to --format json -e)
maldet --json-report 050910-1534.21135
# Restore all quarantined files from a scan
maldet -s 050910-1534.21135
Sortie JSON : Utilisez --format json -e ou --json-report pour générer du JSON structuré
(schéma v1.2) avec les métadonnées du scanner, les détails de l'analyse (chemin, heures, nombre de fichiers), les entrées
par détection avec le nom de la signature, le chemin du fichier, le type de détection, le propriétaire, les permissions et le statut
de quarantaine, ainsi qu'un résumé avec des répartitions par type. Les sessions TSV et texte brut héritées
sont prises en charge ; les sessions héritées incluent "source": "legacy" et affichent les champs enrichis
indisponibles (hash, taille, propriétaire, etc.) comme null.
Les analyses de longue durée sur de grands systèmes de fichiers (1M+ fichiers) peuvent être contrôlées sans kill -9 :```bash
maldet -L
maldet --format json -L
maldet --kill 260327-1509.25279
maldet --pause 260327-1509.25279 2h
maldet --unpause 260327-1509.25279
maldet --stop 260327-1509.25279
maldet --continue 260327-1509.25279
maldet --maintenance
**Reprise du point de contrôle :** `--stop` écrit un fichier de point de contrôle enregistrant l'étape d'analyse,
le nombre de correspondances, les options de configuration et la progression par worker. `--continue` valide le point de contrôle,
avertit si les signatures ont changé, reconstruit la liste de fichiers à partir de l'état actuel du système de fichiers, restaure
les correspondances précédentes et reprend l'analyse depuis l'étape interrompue. Les workers HEX reprennent à la granularité
des chunks (~30s de travail perdu par worker).
**Support du moteur :** Le moteur natif (workers HEX/CSIG/hash) et le `clamscan` autonome
prennent en charge toutes les opérations du cycle de vie. Le ClamAV basé sur un démon (`clamdscan`/`clamd`) ne prend en charge
que `--kill` — `--pause` et `--stop` sont rejetés avec un message d'erreur, car
l'état des E/S du démon est opaque et partagé avec d'autres clients.
---
## 5. Options d'exclusion
Exclure des chemins, des types de fichiers et des signatures des analyses et de la surveillance.
Quatre fichiers d'ignore contrôlent ce qui est exclu de l'analyse :
| Fichier | Format | Rôle |
|------|--------|---------|
| `ignore_paths` | Chemins un par ligne | Exclure des répertoires ou fichiers des analyses |
| `ignore_file_ext` | Extensions un par ligne | Exclure des extensions de fichiers (`.js`, `.css`) |
| `ignore_sigs` | Motifs un par ligne | Ignorer les signatures correspondantes (regex, correspondance de sous-chaîne) |
| `ignore_inotify` | Chemins littéraux un par ligne | Exclure les événements de surveillance inotify |
Tous les fichiers d'ignore sont situés sous `/usr/local/maldetect/`.
**Exemples :**```
# ignore_paths
/home/user/public_html/cgi-bin
# ignore_file_ext
.js
.css
# ignore_sigs
base64.inject.unclassed
# ignore_inotify (user-owned — your additions only)
/home/user/public_html/cache/
backup-
# ignore_inotify.defaults (LMD-managed — refreshed on every upgrade)
# Ships under /usr/local/maldetect/internals/ with curated defaults
# for systemd-private tmpdirs, MariaDB temp tables, Redis, ClamAV, etc.
# Do NOT edit — add your own entries to ignore_inotify instead.
Remarque: les entrées ignore_sigs sont traitées comme des motifs regex étendus et effectuent une correspondance par sous-chaîne. Une entrée php.shell supprimera php.shell, php.shell.v2, {YARA}php.shell.backdoor, etc. Utilisez ^php\.shell$ pour une correspondance exacte. Le caractère . correspond à n'importe quel caractère en regex; échappez-le avec \. pour un point littéral.
Analyse quotidienne automatisée, nettoyage des données et mises à jour des signatures.
La tâche cron installée dans /etc/cron.daily/maldet effectue trois opérations:
cron_prune_days (défaut: 21)autoupdate_signatures et autoupdate_version sont activés)scan_days derniers jours, défaut: 1)L'analyse quotidienne détecte automatiquement les panneaux de contrôle installés et ajuste les chemins d'analyse en conséquence:
Si le mode surveillance est actif, les analyses quotidiennes sont ignorées et un rapport quotidien des événements de surveillance est émis à la place.
Pour des chemins d'analyse personnalisés, utilisez le fichier hook /usr/local/maldetect/cron/custom.cron. Pour les surcharges de configuration spécifiques à cron, utilisez /etc/sysconfig/maldet (RHEL), /etc/default/maldet (Debian) ou /usr/local/maldetect/cron/conf.maldet.cron.
Un script watchdog hebdomadaire (/etc/cron.weekly/maldet-watchdog) fournit des mises à jour de signatures de secours indépendantes lorsque le cron principal est cassé ou obsolète.
Surveillance de fichiers en temps réel avec inotify du noyau, alertes d'empreintes et gestion du superviseur.
La surveillance de fichiers en temps réel utilise le sous-système inotify du noyau pour détecter les événements de création, de modification et de déplacement de fichiers. Nécessite un noyau avec CONFIG_INOTIFY_USER (standard sur tous les noyaux modernes).```bash
maldet -m users
maldet -b -m users
maldet -m /home/mike,/home/ashton
maldet -m /root/monitor_paths
maldet -k
**Comment ça fonctionne :**
`maldet -m` exécute un processus superviseur au premier plan par défaut. Le superviseur gère un enfant `inotifywait` et assure la récupération après crash, les rechargements de configuration et les alertes de synthèse (digest). Utilisez `-b` pour démarrer le superviseur en démon et revenir immédiatement.
1. `monitor_init()` configure des watches inotify sur tous les fichiers des chemins surveillés
2. Les événements fichier sont mis en file d’attente et analysés par lots toutes les `inotify_sleep` secondes (par défaut : 15)
3. La configuration est rechargée toutes les `inotify_reloadtime` secondes (par défaut : 3600)
4. Les paramètres noyau `max_user_watches` et `max_user_instances` sont automatiquement ajustés pour des performances optimales
5. Si `inotifywait` plante, le superviseur le redémarre avec un backoff exponentiel (2, 4, 8, 16, 32 secondes) ; après 3 échecs consécutifs, le superviseur se termine
**Alertes de synthèse :** elles sont envoyées périodiquement à l’intervalle défini par `digest_interval` (par défaut : `24h`). Si le nombre de détections depuis le dernier digest dépasse `digest_escalate_hits`, une alerte d’escalade immédiate est envoyée (par défaut : `0`, désactivé).
**Chemins additionnels :** Pour surveiller des chemins supplémentaires sans modifier `conf.maldet`, ajoutez-les un par ligne au fichier référencé par `monitor_paths_extra` (par défaut : `/usr/local/maldetect/monitor_paths.extra`). Ils sont fusionnés avec la liste de surveillance principale à chaque rechargement de la configuration.
En mode `users`, seuls les sous-répertoires correspondant à `inotify_docroot` (par défaut : `public_html,public_ftp`) sont surveillés, ainsi que les répertoires temporaires système `/tmp`, `/var/tmp` et `/dev/shm`.
**Fichiers d’ignorance (inotify) :** Les exclusions de surveillance regroupent deux fichiers — le fichier utilisateur `/usr/local/maldetect/ignore_inotify` et le fichier géré par LMD `/usr/local/maldetect/internals/ignore_inotify.defaults`. Les deux sont séparés par lignes et acceptent les commentaires `#` et les lignes vides. Le fichier utilisateur `ignore_inotify` accepte par défaut les expressions rationnelles étendues POSIX (ERE) — les ancres (`^`, `$`) et les jokers (`.*`, `.+`) fonctionnent. Pour exclure un chemin littéral contenant des métacaractères d’expression rationnelle, préfixez l’entrée avec `literal:` (p. ex. `literal:/tmp/app.cache`). Le fichier `ignore_inotify.defaults` géré par LMD est traité comme des sous-chaînes littérales — ses entrées sélectionnées sont automatiquement échappées au chargement. Le fichier de défauts est écrasé à chaque mise à jour de LMD ; ajoutez les exclusions spécifiques au site uniquement dans `ignore_inotify`.
---
## 8. Système de signatures
Types de signatures, conventions de nommage, mises à jour et fichiers de règles personnalisés.
LMD est fourni avec cinq types de signatures :
| Type | Fichier | Format | Nombre |
|------|------|--------|-------|
| Hachages MD5 | `sigs/md5v2.dat` | `HASH:SIZE:{MD5}sig.name.N` | ~14,801 |
| Hachages SHA-256 | `sigs/sha256v2.dat` | `HASH:SIZE:{SHA256}sig.name.N` | CDN |
| Motifs HEX | `sigs/hex.dat` | `HEXSTRING:{HEX}sig.name.N` | ~2,054 |
| Signatures composées | `sigs/csig.dat` | `SUBSIG1\|\|SUBSIG2:signame` | CDN |
| Règles YARA | `sigs/rfxn.yara` | syntaxe YARA | ~783 règles |
| YARA compilé | `sigs/compiled.yarc` | sortie `yarac` | optionnel |
Des signatures compatibles ClamAV sont également maintenues :
- `sigs/rfxn.hdb` — format MD5 ClamAV
- `sigs/rfxn.ndb` — format HEX ClamAV
- `sigs/rfxn.hsb` — format SHA-256 ClamAV (nécessite ClamAV >= 0.97)
**Convention de nommage des signatures :** `{TYPE}category.name.variant_number`
Les catégories incluent : `bin.` (binaire), `c.` (langage C), `exp.` (exploit), `php.` (PHP), `js.` (JavaScript), `perl.` (Perl), `html.` (hameçonnage), `base64.inject.`, `gzbase64.`
**Préfixes de détection dans les rapports d’analyse :**
| Préfixe | Source |
|--------|--------|
| `{MD5}` | Correspondance de hachage MD5 (étape 1) |
| `{SHA256}` | Correspondance de hachage SHA-256 (étape 1) |
| `{HEX}` | Correspondance de motif HEX (étape 2) |
| `{CSIG}` | Correspondance de signature composée (étape 2.5) |
| `{SA}` | Analyse statistique (longueur de chaîne) |
| `{YARA}` | Analyse YARA native (`scan_yara=1`) |
| `{CAV}` | Moteur ClamAV (clamd/clamscan) |
### 8.1 Mises à jour des signatures
Les signatures sont mises à jour quotidiennement via la tâche cron ou manuellement :```bash
maldet -u # update signatures
maldet -u --force # force update even if current
Les signatures personnalisées peuvent être ajoutées en trois formats, tous conservés lors des mises à jour :
Des URL d'importation distantes peuvent être configurées pour un téléchargement automatique lors des mises à jour de signatures :
Isoler, restaurer et nettoyer les fichiers infectés par des malwares.
Les fichiers en quarantaine sont stockés sous /usr/local/maldetect/quarantine/ avec des permissions définies à 000. Le chemin d'origine, le propriétaire, les permissions et l'heure de modification sont enregistrés dans /usr/local/maldetect/sess/quarantine.hist pour une restauration complète.```bash
maldet -q SCANID
maldet -s SCANID
maldet -s /usr/local/maldetect/quarantine/config.php.23754
maldet -n SCANID
**Nommage des fichiers en quarantaine :** `FILENAME.INODE` (p. ex., `config.php.23754`)
Pour les scans non-root (p. ex., l'analyse d'envoi de fichiers ModSecurity2), les données de quarantaine sont stockées sous `/usr/local/maldetect/pub/USERNAME/quar/`. Utilisez l'option `-U` pour interagir avec la quarantaine non-root :```bash
maldet -U nobody -s 112012-0032.13771
La fonction de nettoyage recherche des scripts nommés selon les signatures dans le répertoire clean/. Chaque script reçoit le chemin du fichier infecté comme argument et doit supprimer le contenu malveillant. Après le nettoyage, le fichier est analysé à nouveau — s'il déclenche toujours une détection, le nettoyage est marqué comme échoué.
Pour créer une règle de nettoyage pour la signature php.cmdshell.r57, ajoutez un fichier clean/php.cmdshell.r57 contenant une commande comme sed -i avec le motif approprié. Les nettoyages réussis restaurent le fichier à son chemin, propriétaire et permissions d'origine.
Le nettoyeur est une sous-fonction de la quarantaine — les fichiers doivent être mis en quarantaine (ou utiliser -n) pour que le nettoyage s'exécute.
API de hook de service pour ModSecurity, FTP, Exim et les intégrations personnalisées.
LMD fournit une analyse de fichiers en temps réel pour plusieurs services via l'API unifiée hookscan.sh. Un seul script gère l'aiguillage des modes pour ModSecurity, pure-ftpd, ProFTPD, Exim et les intégrations génériques (personnalisées).
Les détections de l'analyse par hook sont consignées dans un journal de détections tournant (hook.hits.log) plutôt que de créer des fichiers de session par analyse. Les détections sont incluses dans les alertes récapitulatives périodiques et peuvent être consultées via maldet --report hooks.
SecRequestBodyAccess On
SecTmpSaveUploadedFiles On # Required for ModSecurity >= 2.9
SecRule FILES_TMPNAMES "@inspectFile /usr/local/maldetect/hookscan.sh"
"id:1999999,phase:2,t:none,deny,log,auditlog,severity:2,
msg:'Malware upload blocked by LMD'"
Les téléversements malveillants sont rejetés avec une action de refus et consignés dans le journal d'audit ModSecurity. Aucun argument de mode n'est nécessaire — `hookscan.sh` utilise par défaut le mode ModSecurity pour la rétrocompatibilité. ModSecurity v2 et v3 (libmodsecurity) utilisent tous deux le même contrat `popen()`.
### 10.2 pure-ftpd```bash
# pure-ftpd.conf (or command-line flags):
CallUploadScript yes
# Start the upload-script daemon:
pure-uploadscript -r /usr/local/maldetect/hookscan.sh -B
Requiert pure-ftpd compilé avec --with-uploadscript. Le mode est détecté automatiquement via la variable d'environnement UPLOAD_VUSER. Les fichiers infectés sont mis en quarantaine après le téléversement (fire-and-forget — les téléversements ne peuvent pas être bloqués, seulement post-traités).
av_scanner = cmdline:
/usr/local/maldetect/hookscan.sh exim %s :
maldet: (.+):
maldet: (.+)
Les trois champs séparés par des deux-points sont : le modèle de commande, l'expression régulière de déclenchement et l'expression régulière de capture du nom. Lorsqu'un malware est détecté, Exim rejette le message en utilisant le nom de signature capturé.
### 10.5 API générique
Pour les intégrations personnalisées, l'analyse par lots et l'utilisation par des tiers :```bash
# Single file scan
hookscan.sh generic /path/to/file
# Exit: 0 = clean, 1 = error, 2 = infected
# Stdout: CLEAN: /path, INFECTED: signame /path, ERROR: reason
# Batch scan from a file list
hookscan.sh generic --list /tmp/filelist.txt
# Batch scan from stdin
find /uploads -newer /tmp/marker -type f | hookscan.sh generic --stdin
Batch output produces one STATUS: PATH line per file. Exit code is worst-result-wins.
Hook scan configuration is stored in conf.maldet.hookscan (optional — defaults are built into the script). The reference defaults are in conf.maldet.hookscan.default.
Key variables:
Run maldet --mkpubpaths after enabling to create per-user data directories for non-root scan operations.
Vérifiez que les canaux de livraison des alertes sont correctement configurés :```bash maldet --test-alert scan email # test per-scan email alert maldet --test-alert scan slack # test per-scan Slack alert maldet --test-alert digest email # test digest email alert maldet --test-alert digest telegram # test digest Telegram alert
Les alertes de test utilisent le pipeline de rendu réel avec des données synthétiques. La ligne d'objet est préfixée par `[TEST]`. L'isolation des canaux garantit que seul le canal spécifié se déclenche.
### 10.8 Digest des hooks
Les détections de hooks sont résumées via des alertes digest périodiques :```bash
# On-demand digest (reads all sources: monitor + hooks)
maldet --digest
# View hook scan activity
maldet --report hooks # last 24 hours
maldet --report hooks --last 7d # last 7 days
maldet --report hooks --mode modsec # filter by mode
La tâche cron quotidienne déclenche automatiquement un digest de hook lorsqu'il existe de nouvelles détections (contrôlé par cron_digest_hook=1 dans conf.maldet).
Pour les administrateurs remplaçant CXS par LMD :
Relier LMD à des outils externes, des pipelines d'automatisation et des scanners tiers.
Les signatures de LMD sont automatiquement liées par symlink aux répertoires de données de ClamAV par install.sh, offrant une couverture à double moteur. Définissez scan_clamscan=auto (par défaut) pour la détection automatique de ClamAV. Voir 3.8 Intégration de ClamAV pour la sélection du moteur et la validation des signatures.
Activez enable_statistic=1 avec elk_host, elk_port et elk_index pour diffuser les événements de scan vers Elasticsearch. Voir 3.10 Intégration ELK.
LMD prend en charge quatre canaux de livraison d'alertes en plus de l'e-mail : Slack (Block Kit), Telegram (MarkdownV2), Discord (embeds de webhook) et relais SMTP pour les environnements sans MTA local. Voir 3.2 Alertes pour la configuration.
Sortie de scan lisible par machine pour le CI/CD et l'automatisation :```bash maldet --format json -e SCANID # JSON report to stdout maldet --json-report list # list all scans as JSON
Voir `man maldet`(1) pour le schéma JSON v1.2 (forme uniforme `{schema_version, scanner, host, reports[]}` pour `-e SCANID` et `-e list`).
### Détection des panneaux d'hébergement
Le cron quotidien détecte automatiquement plus de 12 panneaux de contrôle d'hébergement et ajuste les chemins d'analyse. Voir [6. Cron quotidien](#6-cron-daily) pour la matrice complète des panneaux.
---
## Licence
LMD est développé et supporté à titre bénévole par Ryan MacDonald [[email protected]].
Linux Malware Detect (LMD) est distribué sous la GNU General Public License (GPL) v2
sans restrictions d'utilisation ou de redistribution. La déclaration de copyright et la GNU GPL
sont incluses dans le fichier `COPYING.GPL`. Le crédit doit être accordé aux œuvres dérivées comme
l'exige la GNU GPL.
---
## Support
Le dépôt source de LMD se trouve à l'adresse : https://github.com/rfxn/linux-malware-detect
Les bogues, les demandes de fonctionnalités et les questions générales peuvent être signalés via les issues GitHub ou envoyés à [email protected].
La page officielle du projet se trouve à l'adresse : https://www.rfxn.com/projects/linux-malware-detect/
| Variable | Fonction | Défaut |
|---|
quarantine_hits | Mettre automatiquement en quarantaine les logiciels malveillants détectés | 0 |
quarantine_clean | Tenter de nettoyer les logiciels malveillants des fichiers mis en quarantaine | 0 |
quarantine_suspend_user | Suspendre le compte cPanel ou révoquer le shell en cas de détection | 0 |
quarantine_suspend_user_minuid | UID minimal à suspendre (protège les comptes système) | 500 |
quarantine_on_error | Mettre en quarantaine les fichiers lorsque le moteur de scan renvoie une erreur | 1 |
| Variable | Fonction | Défaut |
|---|
default_monitor_mode | Mode de démarrage du moniteur (users ou chemin vers un fichier) ; vide = désactivé | "" |
inotify_base_watches | Nombre de base de surveillances de fichiers par chemin utilisateur | 16384 |
inotify_minuid | UID minimal pour la surveillance des répertoires personnels | 500 |
inotify_docroot | Sous-répertoires à surveiller dans les répertoires personnels | public_html,public_ftp |
inotify_sleep | Secondes entre les lots de scan | 15 |
inotify_reloadtime | Secondes entre les rechargements de configuration | 3600 |
inotify_cpunice | Priorité nice pour le processus de surveillance | 18 |
inotify_ionice | Priorité IO pour le processus de surveillance | 6 |
inotify_cpulimit | Limite CPU stricte pour le moniteur (0=désactivé) | 0 |
digest_interval | Intervalle entre les alertes récapitulatives digest : 24h, 30m, 7d, 0 (désactivé) | 24h |
digest_escalate_hits | Seuil de détection pour alerte d'escalade immédiate ; 0 = désactivé | 0 |
cron_digest_hook | Activer le balayage digest du hook cron.daily (déclenche le digest si de nouvelles détections de hook existent) | 1 |
monitor_paths_extra | Chemin vers un fichier de chemins de surveillance inotify supplémentaires, séparés par des lignes | /usr/local/maldetect/monitor_paths.extra |
monitor_scan_owner_filters | Appliquer les filtres de propriétaire scan_ignore_root/scan_ignore_user/scan_ignore_group en mode surveillance ; 0 (défaut) = désactivé — le moniteur scanne tous les fichiers quel que soit le propriétaire (rétablit la sémantique de 1.6.6, corrige le problème #485) ; 1 = activé — appliquer les filtres de propriétaire | 0 |
| Variable | Fonction | Défaut |
|---|
post_scan_hook | Chemin vers le script hook (appartenant à root, non inscriptible par tous). Ne peut pas être défini via -co | "" |
post_scan_hook_format | Niveau de sortie : args, file, json (cumulatif) | args |
post_scan_hook_exec | Mode d'exécution : async (non bloquant), sync (attente) | async |
post_scan_hook_timeout | Secondes avant SIGTERM (0=désactivé, min 5) | 60 |
post_scan_hook_on | Filtre de type de scan : all, cli, digest | all |
post_scan_hook_min_hits | Nombre minimum de détections pour déclencher (0=toujours) | 1 |
| Variable | Fonction | Défaut |
|---|
scan_clamd_remote | Utiliser un serveur clamd distant pour le scan | 0 |
remote_clamd_config | Chemin vers le fichier de configuration clamd distant | /etc/clamd.d/clamd.remote.conf |
remote_clamd_max_retry | Nombre maximal de tentatives en cas d'échec du clamd distant | 5 |
remote_clamd_retry_sleep | Secondes entre les tentatives | 3 |
| Variable | Fonction | Défaut |
|---|
enable_statistic | Activer la collecte de statistiques de la pile ELK | 0 |
elk_host | Hôte TCP pour l'entrée ELK | — |
elk_port | Port TCP pour l'entrée ELK | — |
elk_index | Nom de l'index Elasticsearch | — |
| Panneau | Chemin d'analyse |
|---|
| cPanel | /home?/?/public_html/ (+ racines de documents des addons/sous-domaines) |
| Plesk | /var/www/vhosts/?/ |
| DirectAdmin | /home?/?/domains/?/public_html/, /var/www/html/?/ |
| Ensim | /home/virtual/?/fst/var/www/html/ |
| ISPConfig | /var/www/clients/?/web?/web, …/subdomains, /var/www |
| Virtualmin | /home/?/public_html/, /home/?/domains/?/public_html/ |
| ISPmanager | /var/www/?/data/, /home/?/data/ |
| Froxlor | /var/customers/webs/ |
| Bitrix | /home/bitrix/www/, /home/bitrix/ext_www/?/ |
| VestaCP / HestiaCP | /home/?/web/?/public_html/ (+ public_shtml, tmp, private) |
| DTC | ${conf_hosting_path:-/var/www/sites}/?/?/subdomains/?/html/ |
| Type | Fichier | Format |
|---|
| MD5 personnalisé | sigs/custom.md5.dat | Identique à md5v2.dat |
| SHA-256 personnalisé | sigs/custom.sha256.dat | Identique à sha256v2.dat |
| HEX personnalisé | sigs/custom.hex.dat | Identique à hex.dat |
| CSIG personnalisé | sigs/custom.csig.dat | Identique à csig.dat |
| YARA personnalisé | sigs/custom.yara | Syntaxe de règle YARA |
| YARA personnalisé (drop-in) | sigs/custom.yara.d/*.yar | Fichiers de règles YARA |
| YARA compilé | sigs/compiled.yarc | Sortie de yarac (facultatif) |
| Variable | Description |
|---|
sig_import_md5_url | URL pour les signatures MD5 personnalisées |
sig_import_sha256_url | URL pour les signatures SHA-256 personnalisées |
sig_import_hex_url | URL pour les signatures HEX personnalisées |
sig_import_csig_url | URL pour les signatures composées personnalisées |
sig_import_yara_url | URL pour les règles YARA personnalisées |
| Variable | Défaut | Description |
|---|
hookscan_timeout | 30 | Délai d'analyse en secondes |
hookscan_fail_open | 1 | Autoriser le fichier en cas d'erreur d'analyse (0 = bloquer) |
hookscan_escalate_hits | 0 | Alerte immédiate à N correspondances hook/heure (0 = désactivé) |
hookscan_service_users | apache,nginx,... | UID de service exemptés de la restriction du répertoire personnel |
hookscan_user_rate_limit | 60 | Nombre maximal d'analyses/heure pour les appelants non-root |
hookscan_user_show_signames | 1 | Afficher les noms de signatures aux appelants non-root |
hookscan_list_max_bytes | 1048576 | Taille maximale du fichier de liste (1 MB) |
hookscan_list_max_entries | 10000 | Nombre maximal d'entrées dans la liste de fichiers |
| Composant CXS | Équivalent LMD |
|---|
cxscgi.sh | hookscan.sh modsec |
cxsftp.sh | hookscan.sh ftp |
| ProFTPD mod_exec vers cxs | hookscan.sh proftpd |
cxs --file | hookscan.sh generic |
cxswatch | maldet --monitor |
/etc/cxs/cxs.conf | conf.maldet.hookscan |