
ProFTPD 1.3.9d - Élevé - À distance - Résidu de privilèges / Écriture de fichier - SITE COPY dest suit un lien symbolique
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · proftpd-site-copy-dest-follow
Classe : Reliquat de privilège / Écriture de fichier Portée : Distante
ProFTPD 1.3.9d (f59f248) - proftpd.org
Le contrib mod_copy SITE COPY vérifie la limite de la destination avec dir_canonical_vpath (non résolu). pr_fs_copy_file2 fait ensuite un open de la destination sans O_NOFOLLOW, donc un lien symbolique de destination est suivi. FTP STOR vérifie la limite sur un chemin résolu (dir_realpath / dir_best_path). La destination de SITE COPY, non.
Un utilisateur FTP authentifié écrase un fichier dont l'écriture est refusée en pointant un lien symbolique de destination vers celui-ci et en émettant SITE COPY. STOR direct et SITE COPY vers la victime restent 550. STOR / SITE RMDIR / RMD du lien restent 550. DELE supprime uniquement le nœud du lien. Pas de shell. Le DAC Unix s'applique toujours.
C'est l'inverse de l'Issue 2095 publique (contournement de lecture de la source SITE COPY). C'est distinct de l'Issue 2256 publique (suivi de lien symbolique RNTO EXDEV). Ce reliquat concerne la destination de SITE COPY à chaque copie, pas seulement en EXDEV.
| ID | pas encore de CVE |
| Classe | Reliquat de privilège / Écriture de fichier |
| Portée | Distante (FTP authentifié) |
| CWE | CWE-59, CWE-863 |
| CVSS | Élevé : 7.1 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N |
| Produit | ProFTPD |
| Affecté | 1.3.9d tag v1.3.9d (f59f248e26bdfa514443e42bf72a145641df635d) contrib mod_copy |
| Auth | FTP authentifié (mod_copy chargé, CopyEngine activé par défaut). La plantation de SITE SYMLINK nécessite aussi le contrib mod_site_misc sauf si le lien existe déjà |
| Licence | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1 uniquement |
Qui : un utilisateur FTP authentifié. mod_copy chargé. Un lien symbolique de destination dans un répertoire autorisé en écriture (SITE SYMLINK, ou un lien préexistant). SITE SYMLINK src utilise dir_check_canon G_READ, donc planter un lien vers le fichier victime nécessite la lecture de ce fichier. La séparation est lecture autorisée, écriture refusée. L'UID de session doit toujours pouvoir écrire la cible au niveau Unix.
| Méthode | Point de chute | Privilège |
|---|---|---|
| SITE SYMLINK (ou lien existant) dans un répertoire autorisé en écriture dont la cible est un fichier dont l'écriture est refusée et que l'UID peut écrire au niveau Unix ; SITE COPY d'une source lisible vers ce lien | pr_fsio_open de la destination suit | Intégrité (prouvé en lab) : tronquer/écraser le fichier refusé par la limite en tant qu'UID de session. Lab : /secret/victim est passé de ORIGINAL au témoin après SITE COPY /readable/src.txt /upload/link. SITE COPY direct vers /secret/victim est resté 550. |
| SITE RMDIR de ce même lien | dir_check_canon -> dir_best_path | Fermé (prouvé en lab) : 550 RMDIR /upload/link: Operation not permitted. Victime intacte. |
| RMD du cœur sur ce même lien | dir_best_path + WRITE | Fermé (prouvé en lab) : 550 Permission denied. Victime intacte. |
| STOR du lien de destination | dir_best_path + WRITE | Fermé (prouvé en lab) : STOR /upload/link -> 550. Victime intacte. |
| DELE du lien de destination | unlink du nœud du lien | Fermé pour la victime (prouvé en lab) : DELE a supprimé le lien uniquement ; la victime contenait toujours le témoin. |
Jail DefaultRoot vers l'hôte /etc | chroot | Fermé. Le DAC Unix s'applique toujours. Pas de non-authentifié. Pas de shell. |
Prouvé en lab vs déduit : l'écrasement via un lien symbolique de destination non résolu, les STOR/RMDIR/RMD refusés, et le DELE-du-lien-uniquement sont prouvés en lab. Le non-authentifié et le DAC Unix restent déduits du modèle auth/chroot.
J'ai épinglé proftpd/proftpd v1.3.9d (f59f248). Le cœur FTP par défaut avec l'exemple basic.conf n'avait pas de Crit/High non publié. Le contrib mod_copy était le suivant.
copy_copy (contrib/mod_copy.c) construit la destination avec dir_canonical_vpath puis dir_check(..., G_WRITE, to) sur cette chaîne non résolue. pr_fs_copy_file2 (src/fsio.c) commente que stat/open suivent le lien symbolique de destination, puis pr_fsio_open(dst, O_WRONLY|O_CREAT|O_NONBLOCK) sans O_NOFOLLOW.
L'Issue 2095 publique est un contournement de lecture de la source sur SITE COPY. Ignorez ce bug exact. L'Issue 2256 publique est un suivi RNTO EXDEV. Ce reliquat concerne la destination de SITE COPY à chaque copie.
Le suivi récursif de SITE RMDIR était une fausse piste parente : SITE RMDIR utilise dir_check_canon / dir_best_path, qui résout le lien symbolique avant la limite. Le lab a confirmé que SITE RMDIR et le RMD du cœur sur le lien de destination restent refusés.
Fausses pistes déjà consignées : traiter la limite de destination comme résolue parce que STOR l'est ; traiter l'Issue 2256 comme ce reliquat ; prétendre que SITE RMDIR parcourt la victime. Théâtre : un reverse shell. L'oracle est /secret/victim contenant le témoin après SITE COPY via /upload/link, avec STOR du lien toujours à 550.
python3 proftpd-site-copy-dest-follow-Abraxas-Labs.py
ou :
cd lab
./run.sh
FTP loopback 127.0.0.1:18720, passif 18721-18730. Projet Compose proftpd-site-copy-dest-follow. Témoin PROFTPD-SITE-COPY-DEST-FOLLOW-WITNESS. Dernière ligne :
SUCCESS PROFTPD-SITE-COPY-DEST-FOLLOW victim-has-witness=yes stor-secret=denied stor-link=denied site-rmdir-walk=no rmd-walk=no dele-victim=intact PROFTPD-SITE-COPY-DEST-FOLLOW-WITNESS
Vérifier la limite sur la destination résolue (dir_realpath / dir_best_path), ou ouvrir la destination avec O_NOFOLLOW. STOR vérifie déjà la limite sur un chemin résolu.
Le canal de réception du fournisseur est [email protected]. N'ouvrez pas d'issue GitHub publique sur proftpd/proftpd.
f59f248e26bdfa514443e42bf72a145641df635d)contrib/mod_copy.c copy_copysrc/fsio.c pr_fs_copy_file2<Limit READ>