vsftpd 3.0.5 - Alta - Remoto - Privilegio residuo - brace deny_file manca .private/secret
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · vsftpd-deny-file-brace-child
Classe: Privilegio residuo Raggiungibilità: Remota
vsftpd 3.0.5 - Chris Evans
L'esempio nel man page (vsftpd.conf.5) è deny_file={*.mp3,*.mov,.private}. I nomi corrispondenti "non dovrebbero essere accessibili in alcun modo", inclusi "download, cambio di directory, effetto su qualcosa all'interno della directory". vsf_access_check_file (access.c:16-43) chiama vsf_filename_passes_filter sul percorso del client così come fornito, poi str_locate_str dell'intero tunable con graffe. Il filtro corrisponde all'ultimo componente / prefisso; il residuo /secret fallisce; la sottostringa di {*.mp3,*.mov,.private} non trova corrispondenza.
CWD .private è negato (il basename corrisponde). RETR .private/secret e RETR dir/.private riescono. Quel "all'interno della directory" è ciò che questo residuo infrange.
CVE-2015-1419 è una patch pubblica di distro per realpath/basename. La 3.0.5 ufficiale non l'ha mai adottata. Il ramo con graffe di Debian corrisponde comunque al percorso completo, quindi questo child walk rimane anche sui pacchetti distro patchati. Non ri-segnalare 2015-1419.
Questo residuo è una mancata corrispondenza di deny-list condizionata dalla configurazione. Non è una RCE non autenticata, non è un escape dal chroot, e non è una lettura di /etc dell'host.
| ID | nessuna CVE al momento |
| Classe | Privilegio residuo |
| Raggiungibilità | Remota (FTP autenticato) |
| CWE | CWE-863, CWE-22 |
| CVSS | Alto: 7.5 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N |
| Prodotto | vsftpd (Chris Evans) |
| Affetto | vsftpd 3.0.5 tarball ufficiale SHA-256 26b602ae454b0ba6d99ef44a09b6b9e0dfa7f67228106736df1f278c70bc91d3 |
| Auth | FTP autenticato USER/PASS (anonimo nel lab). deny_file impostato a una lista con graffe (default non impostato) |
| Licenza | GNU Affero GPL v3.0 |
| Lab | solo 127.0.0.1. Anonimo in sola lettura. File testimone. |
Chi: un utente FTP autenticato (anonimo ftp nel lab). UID di sessione dopo il solito drop di vsftpd. deny_file è la policy extra che avrebbe dovuto togliere capacità a quell'UID. Le ricette per utenti virtuali citate nel man page condividono guest_username, quindi il DAC Unix non le separa. La 3.0.5 stock con tunable_deny_file NULL non è questo residuo.
| Metodo + sink | Privilegio |
|---|---|
RETR .private/secret con il documentato deny_file={*.mp3,*.mov,.private} con graffe | handle_retr str_open di un file il cui nome di directory è nella deny list, come uid di sessione. Lab: 150/226, 37 byte, corpo VSFTPD-DENY-FILE-BRACE-CHILD-WITNESS |
RETR dir/.private | stesso sink. Un file chiamato .private sotto un'altra directory (must_match_at_current_pos rifiuta una corrispondenza all'indice > 0). Lab: 150/226, corpo DIRDOT-VSFTPD-DENY-FILE-BRACE-CHILD-WITNESS |
vsf_access_check_file; il lab era in sola lettura)| Metodo + sink | Privilegio |
|---|---|
STOR / APPE dello stesso percorso quando write_enable=YES | handle_upload_common crea / sovrascrive come uid di sessione |
DELE / RNTO dello stesso percorso | str_unlink / rename di un nome che la denylist doveva fermare |
| Metodo + sink | Privilegio |
|---|---|
LIST .private/x (o LIST dentro l'albero negato) | handle_dir_common esegue l'access-check sull'argomento completo (manca), poi str_opendir del prefisso .private dopo la divisione sullo slash. Solo nomi. Il DAC Unix si applica comunque |
| Metodo + sink | Risultato |
|---|---|
CWD .private | 550 Permission denied. Il basename .private corrisponde alle graffe |
RETR song.mp3 | 550. *.mp3 è un pattern sull'ultimo componente e corrisponde |
CWD .private stesso (il basename corrisponde)hide_file (basename da readdir; il RETR di un nome nascosto è documentato come intenzionale)/etc dell'host da un chroothttp_enable default off; la GET in modalità FTP uccide la sessione)deny_file=.private senza graffe è salvato dal fallback sulla sottostringa (str_locate_str di .private in .private/secret)Ho fissato la vsftpd ufficiale 3.0.5 (SHA-256 26b602ae...c91d3) invece di un mirror GitHub o un albero Debian/Fedora. Diciannove ricerche nel sorgente. Il daemon compilato di default non ha residui Critici/Alti non pubblicati. Questo richiede che l'operatore copi l'esempio con graffe dal man page.
vsf_filename_passes_filter (ls.c) corrisponde a * / ? / {,} non annidati e fa lavoro utile solo su un pattern dell'ultimo componente. Per il nome .private/secret contro {*.mp3,*.mov,.private}:
*.mp3, *.mov, .private vengono confrontate all'inizio di .private/secret. Il residuo /secret fallisce a meno che il token non fosse *.{*.mp3,*.mov,.private} e non trova nulla.Falsa pista già pubblica: CVE-2015-1419 è solo il realpath della distro. Il Changelog ufficiale non ha tale fix. Persino il ramo con graffe di Debian copia il percorso normalizzato completo, quindi i figli vengono comunque percorsi.
cd lab
./run.sh
Controllo loopback 127.0.0.1:18710, PASV 18711-18718. Progetto Compose vsftpd-deny-file-brace-child. Tarball ufficiale 3.0.5, anonimo in sola lettura, deny_file={*.mp3,*.mov,.private}. Testimone VSFTPD-DENY-FILE-BRACE-CHILD-WITNESS. Ultima riga:
SUCCESS vsftpd-deny-file-brace-child cwd-dotprivate=550 retr-child=yes retr-dir-dotprivate=yes mp3=550 VSFTPD-DENY-FILE-BRACE-CHILD-WITNESS
Confrontare le alternative con graffe contro ogni componente del percorso, oppure realpath / basename prima del filtro (con le solite avvertenze sui symlink). L'esempio documentato dovrebbe effettivamente negare i figli.
L'intake del vendor è [email protected] (vsftpd). Non aprire una issue pubblica su GitHub su alcun mirror di vsftpd.
Abraxas Labs - abraxaslabs.tech - github.com/abraxas - @abraxas_null - [email protected]