vsftpd 3.0.5 - Hoch - Remote - Privilege leftover - FTPS data akzeptiert jedes fortgesetzte Ticket
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · vsftpd-ssl-data-any-ticket
Klasse: Privilegien-Überrest Reichweite: Remote
vsftpd 3.0.5 (Chris Evans) – offizielles Tarball SHA-256 26b602ae454b0ba6d99ef44a09b6b9e0dfa7f67228106736df1f278c70bc91d3. Distro-FTPS kompiliert #define VSF_BUILD_SSL (Stock-Tarball #undef) und Betreiber setzen ssl_enable=YES. Standalone listen=YES ist der kompilierte und Beispiel-Standard.
ssl_accept (ssl.c:494-501) ist der Data-Channel-Bind. Er prüft nur SSL_session_reused(). Es gibt keinen SSL_SESSION-Vergleich gegen das Control-SSL. Data-SSL hat kein FTP USER/PASS. Standalone ssl_init läuft im Listener vor fork (main.c:147-150), sodass Kinder ein SSL_CTX erben. SSL_CTX_set_timeout(INT_MAX) (ssl.c:182-186). Kein SSL_OP_NO_TICKET. SSL_session_reused()==1 bedeutet, dass dieses ClientHello ein Ticket trug, das dieser Prozess entschlüsseln kann, nicht dass es Alices Control-Session ist.
Die Manpage für require_ssl_reuse besagt, dass Reuse dasselbe Master Secret wie der Control-Channel beweist. Der C-Code tut das nicht. Unterscheidet sich vom 3.0.3 Tim Kosse Kill-on-Reuse-Fail (ftpdataio.c:184-187), der einen frischen Handshake weiterhin mit 522 beantwortet und Mallory nicht daran hindert, ein auf einem anderen Control gemünztes Ticket fortzusetzen.
Dieser Überrest ist ein FTPS-Transfer. Er ist kein USER/PASS-Skip, keine Shell und kein Chroot-Ausbruch.
| ID | noch keine CVE |
| Klasse | Privilegien-Überrest (FTPS-Data akzeptiert jedes fortgesetzte Ticket) |
| Reichweite | Remote (Same-IP PASV; geteiltes NAT ist AC:H) |
| CWE | CWE-345, CWE-287 |
| CVSS | High: 7.4 CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N |
| Produkt | vsftpd (Chris Evans) |
| Betroffen | 3.0.5 mit VSF_BUILD_SSL und ssl_enable=YES. require_ssl_reuse=YES (Standard). require_cert=NO (Standard) |
| Auth | Mallory: nur AUTH TLS (kein USER/PASS). Alice: anonymes PBSZ/PROT P |
| Lizenz | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1:18700 Control, PASV 18701-18708. Compose vsftpd-ssl-data-any-ticket |
Wer: ein anderer FTPS-Client (oder On-Path), der Alices Quell-IP teilt. PASV accept erfordert weiterhin die Control-Peer-IP (privops.c:212-218), außer bei pasv_promiscuous. Geteiltes NAT ist der übliche FTPS-Fall, für den require_ssl_reuse hinzugefügt wurde. Mallory meldet sich nie an.
| Methode + Sink | Privileg |
|---|---|
Mallory nur AUTH TLS, TLS 1.2 ALPN ftp, behält das Session-Ticket vom Listener SSL_CTX. Alice anonym PBSZ/PROT P, PASV, RETR secret.txt blockiert in get_remote_transfer_fd bis accept. Mallory Same-IP PASV, setzt sein Ticket fort (session_reused=True) | Entschlüsselt diesen einen RETR. Lab: Data-Socket 35 Bytes VSFTPD-SSL-DATA-ANY-TICKET-WITNESS. Alice 150 dann 226. Control-TLS und Passwort bleiben Alices. Kein Verzeichnisdurchlauf über diesen Transfer hinaus. |
ssl_accept-Gate; Lab war RETR-Steal)| Methode + Sink | Privileg |
|---|---|
Gleiches Ticket-Resume während Alice STOR / APPE | Alices benannte Datei wird aus Mallorys TLS-Klartext geschrieben, als Alices uid / anonyme ftp-uid, innerhalb des bestehenden Chroot |
| Methode + Sink | Privileg |
|---|---|
Frischer Data-Handshake (reused=False) | 522 session reuse required (3.0.3 Kill). Dieser Transfer stirbt. Control bleibt Alices |
privops.c:212-218)require_cert=YES plus präsentiertes Zertifikat bindet SHA-256-DigestsPROT C für lokale Benutzer (force_local_data_ssl Standard YES)ssl_init-Vererbung)ftp (vsftpd FATALs)Ich habe das offizielle vsftpd 3.0.5 Tarball gepinnt statt eines GitHub-Mirrors oder eines Debian/Fedora-Baums. Neunzehn Source-Hunts. Die SSL-Hunt stoppte bei ssl_accept: Reuse ist ein Boolean, keine Bindung an dieses Control-SSL_SESSION. Listener-SSL_CTX plus INT_MAX-Ticket-Lebensdauer ist der Rest.
Irrwege: ALPN muss ftp sein, sonst FATALt vsftpd (3.0.4 ALPACA-Überrest ist bereits geschlossen). Arm64-Link brauchte explizit -lpam -lcap; Stock-vsf_findlibs.sh probt nur x86_64-Pfade. Den 3.0.3 Tim Kosse Kill als diesen Bug zu behandeln: er beantwortet einen frischen Handshake auf Alices Data-fd mit 522 und stoppt kein auf einem anderen Control gemünztes Ticket.
cd lab
./run.sh
Offizielles 3.0.5 mit #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. Loopback-Docker. Zwei Same-IP-Clients. TLS 1.2 Tickets. ALPN ftp. Control 127.0.0.1:18700, PASV 18701-18708. Compose vsftpd-ssl-data-any-ticket. Witness VSFTPD-SSL-DATA-ANY-TICKET-WITNESS. Letzte Zeile:
SUCCESS vsftpd-ssl-data-any-ticket reused-ticket=yes fresh-handshake=522 VSFTPD-SSL-DATA-ANY-TICKET-WITNESS
Binde die Data-SSL_SESSION an die Control-SSL_SESSION (Session-IDs / Master Secret vergleichen). Begrenze die Ticket-Lebensdauer auf die Control-Verbindung. Oder SSL_OP_NO_TICKET plus ein Session-Cache, der nach Control geschlüsselt ist. ProFTPD 1.3.9d vergleicht Sessions.
Vendor-Intake ist [email protected] (security.appspot.com/vsftpd.html). Öffne kein öffentliches GitHub-Issue auf irgendeinem vsftpd-Mirror.
Abraxas Labs - abraxaslabs.tech - github.com/abraxas - @abraxas_null - [email protected]