CVE-2019-15107
Patch now. It under exploitation confirmed by CISA and has a working public exploit.
Apply updates per vendor instructions.
Summary
O parâmetro old de password_change.cgi no Webmin é passado sem sanitização para uma chamada de shell, permitindo injeção de comandos remota e não autenticada com privilégios de root. A origem não é um erro de programação comum: é um backdoor inserido por um atacante desconhecido na infraestrutura de build do projeto, presente apenas nos pacotes distribuídos via SourceForge — o código-fonte no GitHub nunca foi afetado. Está no catálogo KEV da CISA com exploração ativa confirmada, tem módulo Metasploit e PoC pública, mas a explorabilidade real depende de uma configuração específica não-padrão na maioria das versões.
Technical detail
A falha está em password_change.cgi, que envia a senha antiga informada pelo usuário para a função encrypt_password em acl/acl-lib.pl, que por sua vez chama unix_crypt para validar a senha atual contra o /etc/shadow. Nessa validação, o valor do parâmetro old é usado numa construção que executa comandos via shell sem escapar caracteres especiais — um caractere pipe (|) no valor de old é interpretado como separador de comando, caracterizando CWE-78 (OS Command Injection). O servidor nem chega a validar se o usuário ou a senha antiga estão corretos antes de processar o payload: o comando injetado é executado independentemente do resultado da autenticação.
A raiz do problema não foi um bug de código-fonte revisável, mas um comprometimento de supply chain: segundo o pesquisador que divulgou a falha (AkkuS, publicada na DEFCON AppSec Village), um atacante desconhecido inseriu instruções Perl (qx) no servidor de build do Webmin em duas ocasiões — abril de 2018, introduzindo o backdoor na release 1.890, e julho de 2018, reintroduzindo-o nas releases 1.900 a 1.920 (o desenvolvedor do módulo Metasploit cita a faixa 1.890–1.920). Somente os pacotes disponibilizados no SourceForge foram adulterados; os repositórios oficiais no GitHub do projeto não contêm o código malicioso.
O gatilho real da exploração depende do parâmetro miniserv{'passwd_mode'} em /etc/webmin/miniserv.conf. Quando esse valor é 2, o código correspondente a 'Prompt users with expired passwords to enter a new one' (Webmin Configuration > Authentication) está ativo e o fluxo vulnerável em password_change.cgi fica acessível sem autenticação prévia. Na versão 1.890 esse recurso já vem habilitado por padrão; nas versões 1.900 a 1.920 é preciso que o administrador tenha ativado essa opção manualmente — configuração que, segundo o próprio autor da descoberta, é usada por muitos administradores de Webmin.
How it’s exploited
O vetor é uma requisição HTTP POST não autenticada para password_change.cgi, contendo no campo old um valor com um caractere pipe seguido do comando a executar (ex.: usuário|comando). O servidor processa esse valor na rotina de validação da senha antiga e executa o comando com os privilégios do processo Webmin, tipicamente root, antes mesmo de reportar falha de autenticação. Não é necessário conhecer usuário, senha ou token de sessão válidos — a exploração é pré-autenticação e de baixa complexidade, o que justifica CVSS 9.8.
A única pré-condição real, ausente na manchete e essencial para avaliar o risco, é o miniserv.conf com passwd_mode=2 habilitado (ou a instalação ser especificamente a versão 1.890, vulnerável por padrão). Ambientes com a troca de senha expirada desabilitada — que é a configuração padrão a partir da 1.900 — não são explorável por este vetor, mesmo rodando versão nominalmente listada como afetada.
Existe módulo Metasploit público (rank Excellent) e exploit no Exploit-DB (EDB-ID 47230) que automatizam a verificação de vulnerabilidade e a entrega de payload via cmd/unix/reverse_python, além de PoCs adicionais catalogadas no Packet Storm. A presença no catálogo KEV da CISA confirma exploração ativa em campo, o que torna esta CVE um alvo recorrente de varredura massiva contra instâncias Webmin expostas à internet.
Versions
How to protect
A correção definitiva é atualizar para Webmin 1.930 ou versão posterior, que remove o código do backdoor. Segundo o próprio fornecedor, a atualização é fortemente recomendada independentemente da configuração de troca de senha estar habilitada ou não.
Se a atualização imediata não for possível em instalações nas versões 1.900 a 1.920, o fornecedor orienta editar /etc/webmin/miniserv.conf e remover/desabilitar a diretiva que ativa o passwd_mode=2 (correspondente à opção 'Prompt users with expired passwords to enter a new one' em Webmin Configuration > Authentication), eliminando o caminho de código vulnerável sem precisar substituir o binário. Esse paliativo tem custo funcional: usuários com senha expirada deixam de poder trocá-la pela própria interface web até a atualização ser aplicada. Para a versão 1.890, que vem vulnerável por padrão, não há paliativo de configuração equivalente documentado — a única mitigação efetiva é a atualização.
Restringir acesso de rede à porta do Webmin (por padrão 10000) para IPs confiáveis reduz a superfície de ataque, mas não elimina a vulnerabilidade nem substitui a atualização ou a correção de configuração — não deve ser tratado como mitigação suficiente isoladamente.
How to detect
Em logs de acesso do Webmin/miniserv, procurar requisições POST para password_change.cgi originadas sem sessão autenticada válida, especialmente com o campo old contendo caracteres de shell como pipe (|), ponto e vírgula ou backticks — o valor esperado nesse campo é apenas a senha antiga em texto simples. Requisições repetidas com parâmetros user=root e expired=2 são um padrão característico dos exploits públicos conhecidos.
Como o vetor é pré-autenticação e o Metasploit inclui uma rotina de 'check' que envia um payload de teste (dir) antes da exploração real, tentativas de varredura tendem a gerar duas requisições sequenciais ao mesmo endpoint em curto intervalo. Ainda assim, não há assinatura de tráfego universalmente confiável além de inspecionar o conteúdo do parâmetro old — organizações sem WAF ou proxy inspecionando corpo de requisição HTTPS interna ao Webmin não terão visibilidade central desse tráfego.