
Scanner de malware Linux com múltiplos mecanismos e cinco estágios de detecção (MD5, padrão HEX, YARA, ClamAV, estatístico), monitoramento inotify em tempo real, quarentena e alertas multicanal.
Scanner de malware para Linux — detecção de ameaças em múltiplos estágios (MD5, SHA-256, HEX, YARA, análise estatística), integração com ClamAV, monitoramento inotify em tempo real, operações de quarentena/limpeza/restauração e alertas em múltiplos canais (email, Slack, Telegram, Discord).
(C) 2002-2026, R-fx Networks <[email protected]>
(C) 2026, Ryan MacDonald <[email protected]>
Licenciado sob GNU GPL v2
Mecanismo de varredura nativo 43x mais rápido — o pipeline de varredura nativo foi completamente reescrito com processamento paralelo em lote. Benchmark do mundo real em ~10.000 arquivos:
| Versão | Tempo de Execução | Arquivos | Detecções |
|---|---|---|---|
| v1.6.6 | 1.217s | 9.931 | 35 |
| v2.0.1 | 28s | 9.931 | 35 |
A correspondência de assinaturas MD5 e HEX agora usa grep em lote com workers paralelos Aho-Corasick, eliminando a sobrecarga de compilação de padrões por arquivo e ~500.000 forks de subprocessos por varredura. Configure o número de workers paralelos com scan_workers (padrão: auto).
Outros destaques: gerenciamento do ciclo de vida da varredura (--kill, --pause, --stop/--continue, -L), varredura de hash SHA-256 com detecção automática de hardware de CPU (scan_hashtype), varredura nativa YARA (scan_yara=1), alertas via webhook do Discord, correções nos alertas do Slack/Telegram, suporte a curingas hex do ClamAV no mecanismo nativo e mais de 200 correções de bugs em todo o código.
Consulte CHANGELOG para obter todos os detalhes.
./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. Introdução
Arquitetura do LMD, estágios de detecção e plataformas suportadas.
O Linux Malware Detect (LMD) é um scanner de malware para Linux lançado sob a licença GNU GPLv2, projetado em torno das ameaças enfrentadas em ambientes de hospedagem compartilhada. Ele utiliza dados de ameaças de sistemas de detecção de intrusão na borda da rede para extrair malware que está sendo ativamente usado em ataques e gera assinaturas para detecção. Além disso, os dados de ameaças são derivados de envios de usuários com o recurso checkout do LMD e de recursos da comunidade de malware.
O LMD concentra-se nas classes de malware que os produtos tradicionais de antivírus frequentemente não detectam: shells PHP, injetores JavaScript, backdoors codificados em base64, bots de IRC e outras ameaças na camada de aplicação web que visam contas de usuários de hospedagem compartilhada em vez de componentes internos do sistema operacional.
**Estágios de Detecção**
- Correspondência de hash de arquivo MD5 para identificação exata de ameaças
- Correspondência de padrões HEX por meio do mecanismo nativo de grep em lote com workers paralelos
- Varredura de assinatura composta (csig) com lógica booleana de múltiplos padrões (AND/OR/limiar), correspondência sem diferenciar maiúsculas/minúsculas, correspondência ampla (UTF-16LE) e curingas com lacunas limitadas
- Varredura nativa de regras YARA com suporte completo a módulos e regras personalizadas
- Análise estatística de comprimento de strings para detectar ameaças ofuscadas (base64, gzinflate)
- Integração com ClamAV para cobertura estendida com assinaturas ClamAV mantidas pelo LMD
**Varredura e Monitoramento**
- Varrer todos os arquivos, arquivos modificados recentemente ou arquivos de uma lista
- Monitoramento de arquivos em tempo real via inotify do kernel (eventos create/modify/move)
- Varredura de uploads HTTP por meio do hook `inspectFile` do ModSecurity2
- Varredura em segundo plano para operações de grande escala sem supervisão
- Filtragem por regex de inclusão/exclusão por varredura
**Quarentena e Resposta**
- Fila de quarentena com armazenamento de arquivos sem permissões
- Quarentena/restauração em lote por ID de varredura
- Regras de limpeza específicas por assinatura para remoção de malware
- Restauração completa de arquivos (conteúdo, proprietário, permissões, mtime)
**Alertas e Relatórios**
- Alertas por e-mail em HTML + texto com design rfxn unificado (marca azul-petróleo, entradas em cartão)
- Suporte a relay SMTP (TLS/SSL) para ambientes sem MTA local
- Alertas por entrada no Slack Block Kit, Telegram MarkdownV2 e Discord embed
- Modelos de alerta personalizáveis por meio de overrides em `alert/custom.d/`
- Relatórios de varredura com detalhes de detecções por arquivo, tipos de detecção codificados por cores
**Infraestrutura**
- Vinculação automática de assinaturas ClamAV para cobertura de motor duplo
- Cron diário com detecção automática de mais de 12 painéis de controle de hospedagem
- Controle de recursos de CPU/IO (nice, ionice, cpulimit)
- Atualizações automáticas de assinaturas e versão
- Suporte a unit de serviço systemd e script init SysV
### Plataformas Suportadas
O LMD roda em qualquer distribuição Linux com bash e utilitários GNU padrão. Plataformas testadas:
| Plataforma | Sistema Init | Caminho de Configuração do Pacote |
|----------|-------------|---------------------|
| 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 | — | — (parcial; sem inotify) |
---
## 2. Instalação
Instalando, atualizando e removendo o LMD de um sistema.
O script `install.sh` incluído realiza todas as tarefas de instalação. Instalações anteriores são automaticamente copiadas em backup.```bash
./install.sh
O instalador:
/usr/local/maldetectmaldet em /usr/local/sbin//etc/cron.daily/maldetconf.maldet), assinaturas personalizadas e arquivos de ignorados entre atualizaçõesInstalações anteriores são salvas em /usr/local/maldetect.bk{PID} com um symlink maldetect.last para o backup mais recente.
Caminhos padrão:
/usr/local/maldetect/usr/local/sbin/maldet/etc/cron.daily/maldet/usr/lib/systemd/system/maldet.serviceTodas as configurações voltadas ao usuário e seus padrões. Consulte man maldet(1) para a referência completa.
O arquivo de configuração principal é /usr/local/maldetect/conf.maldet. Todas as opções estão comentadas para facilitar a configuração. As opções usam 0/1 para desativar/ativar, salvo indicação em contrário.
A configuração também pode ser sobrescrita em tempo de execução usando a flag -co:```bash
maldet -co quarantine_hits=1,email_addr=[email protected] -a /home
### 3.1 Opções Gerais
| Variável | Finalidade | Padrão |
|----------|---------|---------|
| `autoupdate_signatures` | Atualizar assinaturas automaticamente diariamente via cron | `1` |
| `autoupdate_version` | Atualizar automaticamente a versão do LMD diariamente via cron | `1` |
| `autoupdate_version_hashed` | Verificar o hash SHA-256 do executável LMD em relação ao upstream (usa MD5 como fallback) | `1` |
| `sigup_interval` | Horas entre verificações automáticas de atualização de assinaturas via job cron independente (`/etc/cron.d/maldet-sigup`); 0 = desativado | `6` |
| `cron_prune_days` | Dias para reter dados de quarentena/sessão/temporários | `21` |
| `cron_daily_scan` | Habilitar verificação automática diária via cron | `1` |
| `scan_days` | Dias para buscar arquivos modificados em verificações cron diárias | `1` |
| `import_config_url` | URL para baixar substituição de configuração remota | — |
| `import_config_expire` | Expiração de cache da configuração importada (segundos) | `43200` |
| `sig_import_md5_url` | URL para baixar assinaturas MD5 personalizadas | — |
| `sig_import_hex_url` | URL para baixar assinaturas HEX personalizadas | — |
| `sig_import_yara_url` | URL para baixar regras YARA personalizadas | — |
| `sig_import_sha256_url` | URL para baixar assinaturas SHA-256 personalizadas | — |
| `sig_import_csig_url` | URL para baixar assinaturas compostas personalizadas | — |
| `session_legacy_compat` | Gerar arquivos de sessão legados em texto puro juntamente com TSV: `auto` (detectar sessões de formato antigo), `1` (sempre), `0` (apenas TSV) | `auto` |
### 3.2 Alertas
| Variável | Finalidade | Padrão |
|----------|---------|---------|
| `email_alert` | Habilitar alertas por e-mail após verificações | `0` |
| `email_addr` | Endereço do destinatário do alerta | `[email protected]` |
| `email_subj` | Modelo de linha de assunto do e-mail | `maldet alert from $(hostname)` |
| `email_ignore_clean` | Suprimir alertas quando todas as detecções foram limpas | `1` |
| `email_panel_user_alerts` | Enviar alertas de usuário do painel na detecção de ameaças | `0` |
| `email_panel_from` | Cabeçalho From para alertas de usuário do painel | `[email protected]` |
| `email_panel_replyto` | Cabeçalho Reply-To para alertas de usuário do painel | `[email protected]` |
| `email_panel_alert_subj` | Linha de assunto para alertas de usuário do painel | `maldet alert from $(hostname)` |
| `email_format` | Formato do e-mail: `text`, `html` ou `both` | `html` |
| `smtp_relay` | URL do relay SMTP (ex.: `smtps://smtp.gmail.com:465`) | — |
| `smtp_from` | Endereço do remetente para entrega via relay SMTP | — |
| `smtp_user` | Nome de usuário de autenticação SMTP | — |
| `smtp_pass` | Senha de autenticação SMTP | — |
| `slack_alert` | Habilitar alertas de upload de arquivos no Slack | `0` |
| `slack_subj` | Nome do arquivo para upload no Slack | `maldet alert from $(hostname)` |
| `slack_token` | Token da API do Slack Bot (escopos: `files:write`, `files:read`) | — |
| `slack_channels` | Lista separada por vírgulas de nomes ou IDs de canais | `maldetreports` |
| `telegram_alert` | Habilitar alertas no Telegram | `0` |
| `telegram_bot_token` | Token da API do Bot do Telegram | — |
| `telegram_channel_id` | ID do chat ou grupo do Telegram | — |
| `discord_alert` | Habilitar alertas via webhook do Discord | `0` |
| `discord_webhook_url` | URL do webhook do Discord para envio de alertas | — |
### 3.3 Opções de Varredura
| Variável | Finalidade | Padrão |
|----------|---------|---------|
| `scan_hashtype` | Algoritmo de hash para o estágio 1: `auto`, `sha256`, `md5`, `both` | `auto` |
| `scan_max_depth` | Profundidade máxima de diretórios para o find | `15` |
| `scan_min_filesize` | Tamanho mínimo de arquivo para verificar | `24` bytes |
| `scan_max_filesize` | Tamanho máximo de arquivo para verificar | `2048k` |
| `scan_hexdepth` | Profundidade em bytes para correspondência de assinaturas HEX | `262144` |
| `scan_hex_chunk_size` | Arquivos por micro-lote na varredura HEX+CSIG (intervalo: 1024-20480) | `10240` |
| `scan_csig` | Habilitar varredura de assinatura composta (csig) (somente modo nativo) | `1` |
| `scan_workers` | Workers paralelos para as passagens de varredura MD5, SHA-256, HEX e CSIG | `auto` |
| `scan_cpunice` | Prioridade nice para o processo de varredura (-19 a 19) | `19` |
| `scan_ionice` | Prioridade da classe de agendamento de E/S (0-7) | `6` |
| `scan_cpulimit` | Limite rígido de porcentagem de CPU (0=desativado) | `0` |
| `scan_ignore_root` | Ignorar arquivos de propriedade do root nas varreduras (não aplicado no modo monitor por padrão; consulte `monitor_scan_owner_filters`) | `1` |
| `scan_ignore_user` | Ignorar arquivos pertencentes a usuários específicos | — |
| `scan_ignore_group` | Ignorar arquivos pertencentes a grupos específicos | — |
| `scan_user_access` | Permitir que usuários não root executem varreduras | `0` |
| `scan_user_access_minuid` | UID mínimo para criação de diretórios de usuário via --mkpubpaths | `100` |
| `scan_find_timeout` | Tempo limite para geração da lista de arquivos via find (0=desativado, mínimo 60s, 14400=4h recomendado) | `0` |
| `scan_export_filelist` | Salvar resultados do find em tmp/find_results.last | `0` |
| `scan_tmpdir_paths` | Caminhos temporários com escrita global incluídos nas varreduras -a/-r | `/tmp /var/tmp /dev/shm /var/fcgi_ipc` |
| `string_length_scan` | Habilitar análise estatística de comprimento de strings | `0` |
| `string_length` | Comprimento mínimo suspeito de string | `150000` |
| `scan_progress_log_interval` | Segundos entre checkpoints do log de progresso durante varreduras em segundo plano (0=desativado) | `60` |
| `scan_meta_cleanup_age` | Horas para reter arquivos de metadados de varreduras concluídas/encerradas (0=desativado) | `48` |
| `maint_compress_age` | Dias antes que arquivos de sessão concluídos sejam compactados com gzip (0=desativado) | `30` |
| `maint_archive_age` | Dias antes que sessões compactadas sejam agrupadas em arquivos mensais (0=desativado) | `90` |
### 3.4 Varredura YARA
A varredura YARA nativa invoca o binário `yara` (ou `yr` do YARA-X) independentemente do ClamAV, suportando módulos YARA completos, regras compiladas e arquivos de regras personalizados que o subconjunto limitado de YARA do ClamAV não consegue processar. Quando ambos estão disponíveis, `yr` (YARA-X) é preferido. Quando definido como `auto`, o YARA nativo é habilitado apenas quando o ClamAV não está disponível e um binário yara/yr é encontrado, evitando avaliação duplicada de regras.
| Variável | Finalidade | Padrão |
|----------|---------|---------|
| `scan_yara` | Habilitar o estágio de varredura YARA nativo: `auto` (detectar binário, fallback para ClamAV), `0` (desativado), `1` (ativado) | `auto` |
| `scan_yara_timeout` | Tempo limite em segundos (0=sem tempo limite) | `300` |
| `scan_yara_scope` | Escopo das regras quando o ClamAV também está ativo: `all` (varredura nativa completa) ou `custom` (somente regras personalizadas nativamente, ClamAV processa rfxn.yara) | `custom` |
| `sig_import_yara_url` | URL para baixar regras YARA personalizadas na atualização de assinaturas | — |
**Regras YARA personalizadas** podem ser colocadas em dois locais, ambos preservados entre atualizações:
- `sigs/custom.yara` — regras de arquivo único
- `sigs/custom.yara.d/` — diretório drop-in para arquivos de regras `.yar` e `.yara`
Compatível com conjuntos de regras de terceiros, como [YARA Forge](https://yarahq.github.io/) e [Signature Base](https://github.com/Neo23x0/signature-base). Regras compiladas (saída do `yarac`) também são suportadas via `sigs/compiled.yarc`.
**Varredura em lote:** YARA 4.0+ e todas as versões do YARA-X usam `--scan-list` para varredura eficiente de arquivos em lote. Versões mais antigas do YARA recorrem automaticamente à varredura arquivo por arquivo.
Habilite em tempo de execução sem editar a configuração:```bash
maldet -co scan_yara=1 -a /home/?/public_html
| Variável | Finalidade | Padrão |
|---|---|---|
quarantine_hits | Colocar malware detectado em quarentena automaticamente | 0 |
quarantine_clean | Tentar limpar malware de arquivos em quarentena | 0 |
quarantine_suspend_user | Suspender conta cPanel ou revogar shell em caso de detecção | 0 |
quarantine_suspend_user_minuid | UID mínimo para suspensão (protege contas do sistema) | 500 |
quarantine_on_error | Colocar arquivos em quarentena quando o mecanismo de varredura retornar erro | 1 |
| Variável | Finalidade | Padrão |
|---|---|---|
default_monitor_mode | Modo de inicialização do monitor (users ou caminho para arquivo); vazio = desativado | "" |
inotify_base_watches | Número base de monitoramentos de arquivos por caminho de usuário | 16384 |
inotify_minuid | UID mínimo para monitoramento dos diretórios pessoais dos usuários | 500 |
inotify_docroot | Subdiretórios a monitorar nos diretórios pessoais dos usuários | public_html,public_ftp |
inotify_sleep | Segundos entre lotes de varredura | 15 |
inotify_reloadtime | Segundos entre recargas de configuração | 3600 |
inotify_cpunice | Prioridade nice para o processo do monitor | 18 |
inotify_ionice | Prioridade de I/O para o processo do monitor | 6 |
inotify_cpulimit | Limite rígido de CPU para o monitor (0=desativado) | 0 |
digest_interval | Intervalo entre alertas periódicos de resumo digest: 24h, 30m, 7d, 0 (desativado) | 24h |
digest_escalate_hits | Limite de detecções para alerta de escalonamento imediato; 0 = desativado | 0 |
cron_digest_hook | Ativar varredura digest do hook cron.daily (dispara o digest se houver novas detecções do hook) | 1 |
monitor_paths_extra | Caminho para um arquivo com caminhos adicionais de monitoramento inotify, um por linha | /usr/local/maldetect/monitor_paths.extra |
Um script de hook configurável pode ser invocado após a conclusão da varredura, recebendo os resultados via argumentos posicionais, variáveis de ambiente LMD_* e, opcionalmente, JSON na stdin. O hook nunca interrompe a varredura — falhas são registradas em log, não são fatais. Consulte maldet(1) para o contrato completo do hook.
| Variável | Finalidade | Padrão |
|---|---|---|
post_scan_hook | Caminho para o script de hook (de propriedade do root, não gravável por todos). Não pode ser definido via -co | "" |
post_scan_hook_format | Nível de saída: args, file, json (cumulativo) | args |
post_scan_hook_exec | Modo de execução: async (não bloqueante), sync (aguardar) | async |
post_scan_hook_timeout | Segundos antes do SIGTERM (0=desativado, mínimo 5) | 60 |
post_scan_hook_on | Filtro de tipo de varredura: all, cli, digest | all |
post_scan_hook_min_hits | Número mínimo de detecções para disparar (0=sempre) | 1 |
Quando a varredura ClamAV está ativada (scan_clamscan=1 ou auto com um binário detectado), o LMD seleciona o melhor mecanismo ClamAV disponível em ordem de prioridade:
clamdscan remoto (se scan_clamd_remote=1 e o arquivo de configuração existir)clamd local executando como rootclamd local executando como não-root (com --fdpass)clamscan (fallback, mais lento)As assinaturas do LMD são vinculadas automaticamente por symlink aos diretórios de dados do ClamAV pelo install.sh, dando ao ClamAV acesso às assinaturas MD5 (rfxn.hdb), HEX (rfxn.ndb) e YARA (rfxn.yara) do LMD.
Etapa de validação de assinaturas: Antes de implantar assinaturas atualizadas nos diretórios de dados do ClamAV, o LMD as valida via clamscan -d contra um diretório de preparação (staging). Se a validação falhar, as assinaturas existentes do LMD são removidas do caminho do ClamAV para evitar que bancos de dados malformados quebrem o ClamAV. O sinal de recarga SIGUSR2 para o clamd só é enviado quando pelo menos um diretório de dados do ClamAV passa na validação (issue #467).
| Variável | Finalidade | Padrão |
|---|---|---|
scan_clamscan | Ativar o ClamAV como mecanismo de varredura: auto (detectar binário em tempo de execução), 0 (desativado), 1 (ativado) | auto |
| Variável | Finalidade | Padrão |
|---|---|---|
scan_clamd_remote | Usar um servidor clamd remoto para varredura | 0 |
remote_clamd_config | Caminho para o arquivo de configuração do clamd remoto | /etc/clamd.d/clamd.remote.conf |
remote_clamd_max_retry | Máximo de tentativas em falha do clamd remoto | 5 |
remote_clamd_retry_sleep | Segundos entre tentativas | 3 |
| Variável | Finalidade | Padrão |
|---|---|---|
enable_statistic | Ativar coleta de estatísticas da stack ELK | 0 |
elk_host | Host TCP para entrada ELK | — |
elk_port | Porta TCP para entrada ELK | — |
elk_index | Nome do índice Elasticsearch | — |
Fontes posteriores sobrescrevem valores anteriores:
internals/internals.conf — caminhos internos, descoberta de binários, definições de URLconf.maldet — configuração voltada ao usuáriointernals/compat.conf — mapeamentos de variáveis obsoletas/etc/sysconfig/maldet ou /etc/default/maldet — substituições do sistema-co|--config-option — substituições em tempo de execuçãoInterface de linha de comando, códigos de saída e exemplos comuns. Consulte man maldet(1) para a referência completa de opções.```
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 Códigos de Saída
| Código | Significado |
|------|---------|
| `0` | Sucesso, sem detecções de malware |
| `1` | Erro ou todos os caminhos de digitalização inexistentes |
| `2` | Detecções de malware encontradas |
**Exemplos:**```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
Saída JSON: Use --format json -e ou --json-report para gerar JSON estruturado
(esquema v1.2) com metadados do scanner, detalhes da verificação (caminho, tempos, contagens de arquivos), entradas
por detecção com nome da assinatura, caminho do arquivo, tipo de detecção, proprietário, permissões e status
de quarentena, além de um resumo com detalhamentos por tipo. Sessões TSV e texto simples legadas são
suportadas; sessões legadas incluem "source": "legacy" e exibem campos enriquecidos indisponíveis
(hash, tamanho, proprietário, etc.) como null.
Verificações de longa duração em sistemas de arquivos grandes (1M+ arquivos) podem ser controladas sem 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
**Retomada de checkpoint:** `--stop` grava um arquivo de checkpoint registrando o estágio da varredura, contagem de detecções, opções de configuração e progresso por worker. `--continue` valida o checkpoint, avisa se as assinaturas mudaram, reconstrói a lista de arquivos a partir do estado atual do sistema de arquivos, restaura detecções anteriores e retoma a varredura a partir do estágio interrompido. Os workers HEX retomam na granularidade de chunk (~30s de trabalho perdido por worker).
**Suporte a engine:** A engine nativa (workers HEX/CSIG/hash) e o `clamscan` autônomo suportam todas as operações de ciclo de vida. O ClamAV baseado em daemon (`clamdscan`/`clamd`) suporta apenas `--kill` — `--pause` e `--stop` são rejeitados com uma mensagem de erro porque o estado de I/O do daemon é opaco e compartilhado com outros clientes.
---
## 5. Opções de Ignorar
Excluindo caminhos, tipos de arquivo e assinaturas de varreduras e monitoramento.
Quatro arquivos de ignorar controlam o que é excluído da varredura:
| Arquivo | Formato | Finalidade |
|------|--------|---------|
| `ignore_paths` | Caminhos separados por linha | Excluir diretórios ou arquivos de varreduras |
| `ignore_file_ext` | Extensões separadas por linha | Excluir extensões de arquivo (`.js`, `.css`) |
| `ignore_sigs` | Padrões separados por linha | Ignorar assinaturas correspondentes (regex, correspondência de substring) |
| `ignore_inotify` | Caminhos literais separados por linha | Excluir eventos de monitoramento inotify |
Todos os arquivos de ignorar estão localizados em `/usr/local/maldetect/`.
**Exemplos:**```
# 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.
Nota: As entradas ignore_sigs são tratadas como padrões de regex estendidos e correspondem como substrings. Uma entrada php.shell suprimirá php.shell, php.shell.v2, {YARA}php.shell.backdoor, etc. Use ^php\.shell$ para uma correspondência exata. O caractere . corresponde a qualquer caractere em regex; escape-o como \. para um ponto literal.
Varredura diária automatizada, limpeza de dados e atualizações de assinaturas.
A tarefa cron instalada em /etc/cron.daily/maldet executa três tarefas:
cron_prune_days dias (padrão: 21)autoupdate_signatures e autoupdate_version estiverem habilitados)scan_days dias, padrão: 1)A varredura diária detecta automaticamente os painéis de controle instalados e ajusta os caminhos de varredura de acordo:
| Painel | Caminho de Varredura |
|---|---|
| cPanel | /home?/?/public_html/ (+ docroots de addon/subdomínio) |
| 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/ |
Se o modo de monitoramento estiver ativo, as varreduras diárias são ignoradas e um relatório diário dos eventos de monitoramento é emitido em seu lugar.
Para caminhos de varredura personalizados, use o arquivo de hook /usr/local/maldetect/cron/custom.cron. Para substituições de configuração específicas do cron, use /etc/sysconfig/maldet (RHEL) ou /etc/default/maldet (Debian) ou /usr/local/maldetect/cron/conf.maldet.cron.
Um script de watchdog semanal (/etc/cron.weekly/maldet-watchdog) fornece atualizações independentes de assinaturas de fallback quando o cron principal está quebrado ou desatualizado.
Monitoramento de arquivos em tempo real com inotify do kernel, alertas de digest e gerenciamento por supervisor.
O monitoramento de arquivos em tempo real usa o subsistema inotify do kernel para detectar eventos de criação, modificação e movimentação de arquivos. Requer um kernel com CONFIG_INOTIFY_USER (padrão em todos os kernels modernos).```bash
maldet -m users
maldet -b -m users
maldet -m /home/mike,/home/ashton
maldet -m /root/monitor_paths
maldet -k
**Como funciona:**
`maldet -m` executa um processo supervisor em primeiro plano por padrão. O supervisor gerencia um filho `inotifywait` e lida com recuperação de falhas, recarregamentos de configuração e alertas de resumo. Use `-b` para daemonizar o supervisor e retornar imediatamente.
1. `monitor_init()` configura observações inotify em todos os arquivos sob os caminhos monitorados
2. Os eventos de arquivo são enfileirados e varridos em lote a cada `inotify_sleep` segundos (padrão: 15)
3. A configuração é recarregada a cada `inotify_reloadtime` segundos (padrão: 3600)
4. Os limites do kernel `max_user_watches` e `max_user_instances` são ajustados automaticamente para desempenho ideal
5. Se `inotifywait` falhar, o supervisor o reinicia com backoff exponencial (2, 4, 8, 16, 32 segundos); após 3 falhas consecutivas, o supervisor é encerrado
**Alertas de resumo** são enviados periodicamente no intervalo definido por `digest_interval` (padrão: `24h`). Se a contagem de detecções desde o último resumo exceder `digest_escalate_hits`, um alerta de escalonamento imediato é enviado (padrão: `0`, desabilitado).
**Caminhos aditivos:** Para observar caminhos adicionais sem editar `conf.maldet`, adicione-os um por linha ao arquivo referenciado por `monitor_paths_extra` (padrão: `/usr/local/maldetect/monitor_paths.extra`). Eles são mesclados à lista de observação principal a cada recarga de configuração.
Ao usar o modo `users`, apenas subdiretórios que correspondem a `inotify_docroot` (padrão: `public_html,public_ftp`) são monitorados, além dos diretórios temporários do sistema `/tmp`, `/var/tmp` e `/dev/shm`.
**Arquivos de ignorar (inotify):** As exclusões do monitor unem dois arquivos — o `ignore_inotify` de propriedade do usuário e o `ignore_inotify.defaults` gerenciado pelo LMD em `/usr/local/maldetect/internals/ignore_inotify.defaults`. Ambos são separados por linhas e suportam comentários `#` + linhas em branco. O `ignore_inotify` de propriedade do usuário aceita POSIX ERE (regex estendido) por padrão — âncoras (`^`, `$`) e curingas (`.*`, `.+`) funcionam. Para excluir um caminho literal contendo metacaracteres de regex, prefixe a entrada com `literal:` (ex.: `literal:/tmp/app.cache`). O `ignore_inotify.defaults` gerenciado pelo LMD é tratado como substrings literais — suas entradas selecionadas são escapadas automaticamente no momento do carregamento. O arquivo de padrões é sobrescrito a cada atualização do LMD; adicione exclusões específicas do site apenas ao `ignore_inotify`.
---
## 8. Sistema de Assinaturas
Tipos de assinatura, convenções de nomenclatura, atualizações e arquivos de regras personalizados.
O LMD é fornecido com cinco tipos de assinatura:
| Tipo | Arquivo | Formato | Contagem |
|------|---------|---------|---------|
| Hashes MD5 | `sigs/md5v2.dat` | `HASH:SIZE:{MD5}sig.name.N` | ~14.801 |
| Hashes SHA-256 | `sigs/sha256v2.dat` | `HASH:SIZE:{SHA256}sig.name.N` | CDN |
| Padrões HEX | `sigs/hex.dat` | `HEXSTRING:{HEX}sig.name.N` | ~2.054 |
| Assinaturas compostas | `sigs/csig.dat` | `SUBSIG1\|\|SUBSIG2:signame` | CDN |
| Regras YARA | `sigs/rfxn.yara` | sintaxe YARA | ~783 regras |
| YARA compilada | `sigs/compiled.yarc` | saída do `yarac` | opcional |
Assinaturas compatíveis com ClamAV também são mantidas:
- `sigs/rfxn.hdb` — formato MD5 ClamAV
- `sigs/rfxn.ndb` — formato HEX ClamAV
- `sigs/rfxn.hsb` — formato SHA-256 ClamAV (requer ClamAV >= 0.97)
**Convenção de nomenclatura de assinaturas:** `{TYPE}category.name.variant_number`
As categorias incluem: `bin.` (binário), `c.` (linguagem C), `exp.` (exploit), `php.` (PHP), `js.` (JavaScript), `perl.` (Perl), `html.` (phishing), `base64.inject.`, `gzbase64.`
**Prefixos de detecção nos relatórios de varredura:**
| Prefixo | Origem |
|---------|--------|
| `{MD5}` | correspondência de hash MD5 (estágio 1) |
| `{SHA256}` | correspondência de hash SHA-256 (estágio 1) |
| `{HEX}` | correspondência de padrão HEX (estágio 2) |
| `{CSIG}` | correspondência de assinatura composta (estágio 2.5) |
| `{SA}` | análise estatística (comprimento da string) |
| `{YARA}` | varredura YARA nativa (`scan_yara=1`) |
| `{CAV}` | mecanismo ClamAV (clamd/clamscan) |
### 8.1 Atualizações de Assinaturas
As assinaturas são atualizadas diariamente por meio do cron job ou manualmente:```bash
maldet -u # update signatures
maldet -u --force # force update even if current
Assinaturas personalizadas podem ser adicionadas em três formatos, todos preservados entre atualizações:
| Tipo | Arquivo | Formato |
|---|---|---|
| MD5 personalizada | sigs/custom.md5.dat | Igual a md5v2.dat |
| SHA-256 personalizada | sigs/custom.sha256.dat | Igual a sha256v2.dat |
| HEX personalizada | sigs/custom.hex.dat | Igual a hex.dat |
| CSIG personalizada | sigs/custom.csig.dat | Igual a csig.dat |
| YARA personalizada | sigs/custom.yara | Sintaxe de regras YARA |
| YARA personalizada (drop-in) | sigs/custom.yara.d/*.yar | Arquivos de regras YARA |
| YARA compilada | sigs/compiled.yarc | Saída do yarac (opcional) |
URLs de importação remota podem ser configuradas para download automático durante as atualizações de assinaturas:
| Variável | Finalidade |
|---|---|
sig_import_md5_url | URL para assinaturas MD5 personalizadas |
sig_import_sha256_url | URL para assinaturas SHA-256 personalizadas |
sig_import_hex_url | URL para assinaturas HEX personalizadas |
sig_import_csig_url | URL para assinaturas compostas personalizadas |
sig_import_yara_url | URL para regras YARA personalizadas |
Isolar, restaurar e limpar arquivos infectados por malware.
Os arquivos em quarentena são armazenados em /usr/local/maldetect/quarantine/ com permissões definidas como 000. O caminho original, proprietário, permissões e horário de modificação são registrados em /usr/local/maldetect/sess/quarantine.hist para restauração completa.```bash
maldet -q SCANID
maldet -s SCANID
maldet -s /usr/local/maldetect/quarantine/config.php.23754
maldet -n SCANID
**Nomeação de arquivos em quarentena:** `FILENAME.INODE` (por exemplo, `config.php.23754`)
Para varreduras não-root (por exemplo, verificação de upload do ModSecurity2), os dados de quarentena são armazenados em `/usr/local/maldetect/pub/USERNAME/quar/`. Use a flag `-U` para interagir com a quarentena não-root:```bash
maldet -U nobody -s 112012-0032.13771
A função cleaner procura scripts nomeados por assinatura no diretório clean/. Cada script recebe o caminho do arquivo infectado como argumento e deve remover o conteúdo malicioso. Após a limpeza, o arquivo é verificado novamente — se ainda acionar uma detecção, a limpeza é marcada como FAILED.
Para criar uma regra de limpeza para a assinatura php.cmdshell.r57, adicione um arquivo clean/php.cmdshell.r57 contendo um comando como sed -i com o padrão apropriado. Limpezas bem-sucedidas restauram o arquivo para seu caminho original, proprietário e permissões.
O cleaner é uma subfunção da quarentena — os arquivos devem ser colocados em quarentena (ou usar -n) para que a limpeza seja executada.
API de hook de serviço para ModSecurity, FTP, Exim e integrações personalizadas.
O LMD fornece varredura de arquivos em tempo real para vários serviços por meio da API unificada hookscan.sh. Um único script gerencia o despacho de modos para ModSecurity, pure-ftpd, ProFTPD, Exim e integrações genéricas (personalizadas).
Detecções de varredura por hook são registradas em um log de detecções rotativo (hook.hits.log) em vez de criar arquivos de sessão por varredura. As detecções são incluídas em alertas periódicos de resumo e podem ser visualizadas 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'"
Envios maliciosos são rejeitados com uma ação de negação e registrados no log de auditoria do ModSecurity. Nenhum argumento de modo é necessário — `hookscan.sh` usa o modo ModSecurity por padrão para compatibilidade retroativa. Tanto o ModSecurity v2 quanto o v3 (libmodsecurity) usam o mesmo contrato `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
Requer o pure-ftpd compilado com --with-uploadscript. O modo é detectado automaticamente por meio da variável de ambiente UPLOAD_VUSER. Arquivos infectados são colocados em quarentena após o upload (dispare-e-esqueça — os uploads não podem ser bloqueados, apenas pós-processados).
av_scanner = cmdline:
/usr/local/maldetect/hookscan.sh exim %s :
maldet: (.+):
maldet: (.+)
Os três campos separados por dois-pontos são: modelo de comando, regex de acionamento e regex de captura de nome. Quando malware é detectado, o Exim rejeita a mensagem usando o nome da assinatura capturado.
### 10.5 API Genérica
Para integrações personalizadas, varredura em lote e uso por terceiros:```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
A saída em lote produz uma linha STATUS: PATH por arquivo. O código de saída é definido pelo pior resultado.
A configuração do hook scan é armazenada em conf.maldet.hookscan (opcional — os padrões estão embutidos no script). Os padrões de referência estão em conf.maldet.hookscan.default.
Variáveis-chave:
| Variável | Padrão | Descrição |
|---|---|---|
hookscan_timeout | 30 | Tempo limite do scan em segundos |
hookscan_fail_open | 1 | Permitir o arquivo em caso de erro de scan (0 = bloquear) |
hookscan_escalate_hits | 0 | Alerta imediato a N ocorrências de hook/hora (0 = desativado) |
hookscan_service_users | apache,nginx,... | UIDs de serviço isentos da restrição de diretório home |
hookscan_user_rate_limit | 60 | Máximo de scans/hora para chamadores não root |
hookscan_user_show_signames | 1 | Mostrar nomes de assinaturas para chamadores não root |
hookscan_list_max_bytes | 1048576 | Tamanho máximo do arquivo de lista (1 MB) |
hookscan_list_max_entries | 10000 | Máximo de entradas na lista de arquivos |
Execute maldet --mkpubpaths após a ativação para criar diretórios de dados por usuário para operações de scan não root.
Verifique se os canais de entrega de alertas estão configurados corretamente:```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
Os alertas de teste usam o pipeline de renderização real com dados sintéticos. A linha de assunto é prefixada com `[TEST]`. O isolamento de canal garante que apenas o canal especificado seja acionado.
### 10.8 Resumo de Hooks
As detecções de hooks são resumidas por meio de alertas de resumo periódicos:```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
A tarefa diária do cron dispara automaticamente um digest de hook quando existem novas detecções (controlado por cron_digest_hook=1 no conf.maldet).
Para administradores que estejam substituindo o CXS pelo LMD:
| Componente CXS | Equivalente LMD |
|---|---|
cxscgi.sh | hookscan.sh modsec |
cxsftp.sh | hookscan.sh ftp |
| ProFTPD mod_exec para cxs | hookscan.sh proftpd |
cxs --file | hookscan.sh generic |
cxswatch | maldet --monitor |
/etc/cxs/cxs.conf | conf.maldet.hookscan |
Conectando o LMD a ferramentas externas, pipelines de automação e scanners de terceiros.
As assinaturas do LMD são automaticamente vinculadas por symlink aos diretórios de dados do ClamAV pelo install.sh, proporcionando cobertura de dois motores. Defina scan_clamscan=auto (padrão) para detecção automática do ClamAV. Consulte 3.8 Integração com ClamAV para seleção do motor e validação de assinaturas.
Habilite enable_statistic=1 com elk_host, elk_port e elk_index para transmitir eventos de varredura para o Elasticsearch. Consulte 3.10 Integração com ELK.
O LMD suporta quatro canais de entrega de alertas além do e-mail: Slack (Block Kit), Telegram (MarkdownV2), Discord (embeds de webhook) e relay SMTP para ambientes sem um MTA local. Consulte 3.2 Alertas para configuração.
Saída de varredura legível por máquina para CI/CD e automação:```bash maldet --format json -e SCANID # JSON report to stdout maldet --json-report list # list all scans as JSON
Consulte `man maldet`(1) para o esquema JSON v1.2 (formato uniforme `{schema_version, scanner, host, reports[]}` tanto em `-e SCANID` quanto em `-e list`).
### Detecção de Painel de Hospedagem
O cron diário detecta automaticamente 12+ painéis de controle de hospedagem e ajusta os caminhos de varredura. Consulte [6. Cron Diário](#6-cron-daily) para a matriz completa de painéis.
---
## Licença
LMD é desenvolvido e suportado de forma voluntária por Ryan MacDonald [[email protected]].
O Linux Malware Detect (LMD) é distribuído sob a GNU General Public License (GPL) v2
sem restrições de uso ou redistribuição. A declaração de direitos autorais e a GNU GPL
estão incluídas no arquivo `COPYING.GPL`. Crédito deve ser dado para trabalhos derivados,
conforme exigido pela GNU GPL.
---
## Suporte
O repositório de código-fonte do LMD está em: https://github.com/rfxn/linux-malware-detect
Bugs, solicitações de funcionalidades e dúvidas gerais podem ser registrados como issues no GitHub ou enviados para [email protected].
A página oficial do projeto está em: https://www.rfxn.com/projects/linux-malware-detect/
monitor_scan_owner_filters | Aplicar filtros de propriedade scan_ignore_root/scan_ignore_user/scan_ignore_group no modo monitor; 0 (padrão) = desativado — o monitor varre todos os arquivos independentemente do proprietário (restaura a semântica da 1.6.6, corrige o issue #485); 1 = ativado — aplicar filtros de propriedade | 0 |