
ProFTPD 1.3.9d - Alta - Remoto - Crash - RewriteMap int:utf8trans estouro de BSS
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · proftpd-rewrite-utf8trans
Classe: Crash Alcance: Remoto
ProFTPD 1.3.9d (f59f248) - ProFTPD (proftpd.org)
O contrib mod_rewrite inclui RewriteMap int:utf8trans. Esse builtin copia um argumento FTP do cliente (até CommandBufferSize, 512 KiB) para dois buffers BSS de 1024 slots sem limite de destino. Um nome STOR ASCII longo é um global-buffer-overflow WRITE de tamanho 8 no ASan. O processo filho da sessão aborta. O daemon permanece ativo. Classe Crash. Não é RCE.
| ID | ainda sem CVE |
| Classe | Crash |
| Alcance | Remoto (argumento FTP enviado para int:utf8trans) |
| CWE | CWE-120 |
| CVSS | Alto: 7.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H se a RewriteRule for pré-autenticação. O laboratório usou STOR após login, então PR:L é honesto para essa execução (AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H). |
| Produto | ProFTPD |
| Afetado | 1.3.9d (f59f248e26bdfa514443e42bf72a145641df635d) contrib mod_rewrite |
| Autenticação | o laboratório usa STOR autenticado. Uma RewriteRule pré-autenticação em USER ou similar seria PR:N. |
| Licença | GNU Affero GPL v3.0 |
| Laboratório | apenas 127.0.0.1 |
RewriteEngine fica desativado até ser configurado. O padrão documentado é RewriteRule (.*) ${map:$1}. Assim que uma RewriteRule envia o argumento do cliente através de int:utf8trans, uma chave maior que 1024 bytes estoura dois buffers estáticos no processo filho da sessão.
| Método | Sink | Privilégio |
|---|---|---|
| Comando FTP cujo argumento é a chave do mapa utf8trans, comprimento > 1024 | rewrite_utf8_to_ucs4 depois utf8_val[i] = ucs4_longs[i] | Disponibilidade (comprovado em laboratório): derruba o processo filho da sessão. ASan: global-buffer-overflow WRITE of size 8, depois ABORTING. Prefork: um novo login ainda funcionou; o daemon permaneceu ativo. Um STOR curto de 200 bytes ASCII sobreviveu. A integridade do BSS de rewrite próximo é inferida e depende do layout do compilador. |
| RIP / execução de código | nada alegado | Descartado. Sem payload. Classe Crash. Não é RCE. |
Plantio de RewriteMap via .ftpaccess | CONF_DYNDIR | Descartado. RewriteMap não é permitido em .ftpaccess. |
shell prg: | não existe esse tipo de mapa | Descartado. FIFO é I/O por linha. |
Comprovado em laboratório vs inferido: WRITE de tamanho 8 no ASan, aborto do processo filho da sessão, controle com argumento curto sobrevivendo e login após o gatilho são comprovados em laboratório. RIP/RCE não é alegado.
A Issue 2173 corrigiu o OOB de um byte em int:unescape nesse pin. Este resíduo é o int:utf8trans. Builtin diferente. Bug diferente.
Fixe no tag v1.3.9d do proftpd/proftpd. A safra de CVEs de 2026 e as issues públicas do GitHub ainda presentes nesse tarball (2170, 2173, 2175, 2180, 2095, 2256, 2286, 2319, 2330, 2301) foram a lista de exclusão. O core FTP padrão com o basic.conf de exemplo não me deu um Crit/High não publicado. O contrib rewrite deu.
rewrite_map_int_utf8trans (contrib/mod_rewrite.c) tem:
static unsigned char utf8_val[PR_TUNABLE_BUFFER_SIZE]; /* 1024 */
static unsigned long ucs4_longs[PR_TUNABLE_BUFFER_SIZE]; /* 1024 */
ucs4strlen = rewrite_utf8_to_ucs4(ucs4_longs, strlen(key), (unsigned char *) key);
rewrite_utf8_to_ucs4 escreve um unsigned long por byte ASCII sem limite. PR_TUNABLE_CMD_BUFFER_SIZE é 512 KiB. A issue 2173 já corrigiu o unescape. Este mapa não estava nessa correção.
Caminhos errados: tratar a 2173 como este bug; alegar RIP porque o ASan disse WRITE of size 8; esperar que .ftpaccess pudesse plantar RewriteMap. O primeiro é uma função diferente. O segundo ainda é Crash. O terceiro é CONF_DYNDIR.
ASan mais a libcrypt padrão causam SIGSEGV no PASS antes do sink de rewrite. O laboratório pré-carrega um pequeno stub de crypt(3) para que o login funcione. Esse stub não é um exploit.
python3 proftpd-rewrite-utf8trans-Abraxas-Labs.py
ou:
cd lab
./run.sh
Loopback 127.0.0.1:18740 mais passivo 18741-18750. Projeto Compose proftpd-rewrite-utf8trans. Witness PROFTPD-REWRITE-UTF8TRANS-WITNESS. A imagem é um build ASan do 1.3.9d mod_rewrite. O STOR de controle de 200 bytes ASCII tem sucesso. O STOR de 2048 bytes ASCII é global-buffer-overflow WRITE of size 8 no ASan e o processo filho da sessão aborta. Um novo login após o gatilho ainda funciona.
SUCCESS PROFTPD-REWRITE-UTF8TRANS asan=global-buffer-overflow write=yes child-dead=yes PROFTPD-REWRITE-UTF8TRANS-WITNESS
Limitar o comprimento de destino de rewrite_utf8_to_ucs4 a PR_TUNABLE_BUFFER_SIZE-1. Parar de escrever além de ucs4_longs / utf8_val. Rejeitar ou truncar uma chave de mapa que não caiba.
f59f248e26bdfa514443e42bf72a145641df635d)contrib/mod_rewrite.c rewrite_utf8_to_ucs4 / rewrite_map_int_utf8transint:unescapeGNU Affero GPL v3.0. Veja LICENSE. Apenas laboratório em loopback. Sem garantia.