vsftpd 3.0.5 - Alta - Remoto - Privilégio remanescente - FTPS data aceita qualquer ticket retomado
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · vsftpd-ssl-data-any-ticket
Classe: Privilégio residual Alcance: Remoto
vsftpd 3.0.5 (Chris Evans) - tarball oficial SHA-256 26b602ae454b0ba6d99ef44a09b6b9e0dfa7f67228106736df1f278c70bc91d3. Compilações FTPS de distro definem #define VSF_BUILD_SSL (o tarball original tem #undef) e os operadores configuram ssl_enable=YES. O modo standalone listen=YES é o padrão compilado e de exemplo.
ssl_accept (ssl.c:494-501) é o bind do canal de dados. Ele verifica apenas SSL_session_reused(). Não há comparação de SSL_SESSION com o SSL de controle. O SSL de dados não tem FTP USER/PASS. O ssl_init standalone roda no listener antes do fork (main.c:147-150), então os filhos herdam um único SSL_CTX. SSL_CTX_set_timeout(INT_MAX) (ssl.c:182-186). Sem SSL_OP_NO_TICKET. SSL_session_reused()==1 significa que este ClientHello carregava um ticket que este processo consegue descriptografar, não que seja a sessão de controle da Alice.
A man page de require_ssl_reuse diz que o reuse prova o mesmo master secret do canal de controle. O código C não faz isso. Diferente do kill-on-reuse-fail do Tim Kosse na 3.0.3 (ftpdataio.c:184-187), que ainda responde 522 a um handshake novo e não impede o Mallory de retomar um ticket emitido em outro controle.
Este resíduo é uma transferência FTPS. Não é um bypass de USER/PASS, não é um shell e não é uma fuga de chroot.
| ID | sem CVE ainda |
| Classe | Privilégio residual (dados FTPS aceitam qualquer ticket retomado) |
| Alcance | Remoto (PASV do mesmo IP; NAT compartilhado é AC:H) |
| CWE | CWE-345, CWE-287 |
| CVSS | Alto: 7.4 CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N |
| Produto | vsftpd (Chris Evans) |
| Afetado | 3.0.5 com VSF_BUILD_SSL e ssl_enable=YES. require_ssl_reuse=YES (padrão). require_cert=NO (padrão) |
| Autenticação | Mallory: apenas AUTH TLS (sem USER/PASS). Alice: PBSZ/PROT P anônimo |
| Licença | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1:18700 controle, PASV 18701-18708. Compose vsftpd-ssl-data-any-ticket |
Quem: outro cliente FTPS (ou on-path) que compartilha o IP de origem da Alice. O accept do PASV ainda exige o IP do peer de controle (privops.c:212-218) a menos que pasv_promiscuous. NAT compartilhado é o caso comum de FTPS que o require_ssl_reuse foi criado para impedir. O Mallory nunca faz login.
| Método + sink | Privilégio |
|---|---|
Mallory apenas AUTH TLS, TLS 1.2 ALPN ftp, mantém o session ticket do SSL_CTX do listener. Alice anônima PBSZ/PROT P, PASV, RETR secret.txt bloqueado em get_remote_transfer_fd até o accept. Mallory PASV do mesmo IP, retoma o ticket dele (session_reused=True) | Descriptografa aquele RETR. Lab: socket de dados 35 bytes VSFTPD-SSL-DATA-ANY-TICKET-WITNESS. Alice 150 depois 226. O TLS de controle e a senha continuam sendo da Alice. Sem varredura de diretório além daquela transferência. |
ssl_accept; o lab foi roubo de RETR)| Método + sink | Privilégio |
|---|---|
Mesma retomada de ticket enquanto Alice faz STOR / APPE | O arquivo nomeado da Alice é escrito a partir do texto claro TLS do Mallory, como uid da Alice / uid ftp anônimo, dentro do chroot existente |
| Método + sink | Privilégio |
|---|---|
Handshake de dados novo (reused=False) | 522 session reuse required (kill da 3.0.3). Essa transferência morre. O controle continua sendo da Alice |
privops.c:212-218)require_cert=YES mais um certificado apresentado vincula digests SHA-256PROT C em texto claro para usuários locais (force_local_data_ssl padrão YES)ssl_init do listener)ftp (vsftpd gera FATAL)Eu fixei o tarball oficial do vsftpd 3.0.5 em vez de um espelho no GitHub ou uma árvore Debian/Fedora. Dezenove caçadas no código-fonte. A caçada ao SSL parou em ssl_accept: o reuse é um booleano, não um vínculo com este SSL_SESSION de controle. O SSL_CTX do listener mais o tempo de vida de ticket INT_MAX é o resto.
Caminhos errados: o ALPN precisa ser ftp ou o vsftpd gera FATAL (o resíduo ALPACA da 3.0.4 já está fechado). O link para Arm64 precisou de -lpam -lcap explícitos; o vsf_findlibs.sh original só sonda caminhos x86_64. Tratar o kill do Tim Kosse na 3.0.3 como este bug: ele responde 522 a um handshake novo no fd de dados da Alice e não impede um ticket emitido em outro controle.
cd lab
./run.sh
3.0.5 oficial com #define VSF_BUILD_SSL. Conf: ssl_enable=YES, allow_anon_ssl=YES, force_anon_logins_ssl=YES, force_anon_data_ssl=YES, require_ssl_reuse=YES, require_cert=NO. Docker em loopback. Dois clientes do mesmo IP. Tickets TLS 1.2. ALPN ftp. Controle 127.0.0.1:18700, PASV 18701-18708. Compose vsftpd-ssl-data-any-ticket. Witness VSFTPD-SSL-DATA-ANY-TICKET-WITNESS. Última linha:
SUCCESS vsftpd-ssl-data-any-ticket reused-ticket=yes fresh-handshake=522 VSFTPD-SSL-DATA-ANY-TICKET-WITNESS
Vincular o SSL_SESSION de dados ao SSL_SESSION de controle (comparar session ids / master secret). Limitar o tempo de vida do ticket à conexão de controle. Ou SSL_OP_NO_TICKET mais um cache de sessão indexado pelo controle. O ProFTPD 1.3.9d compara sessões.
O canal de recebimento do fornecedor é [email protected] (security.appspot.com/vsftpd.html). Não abra uma issue pública no GitHub em nenhum espelho do vsftpd.
Abraxas Labs - abraxaslabs.tech - github.com/abraxas - @abraxas_null - [email protected]