mirror of
https://github.com/django/django.git
synced 2025-10-05 12:59:10 +00:00
Fixed CVE-2025-59682 -- Fixed potential partial directory-traversal via archive.extract().
Thanks stackered for the report. Follow up to 05413afa8c18cdb978fcdf470e09f7a12b234a23.
This commit is contained in:
parent
41b43c74bd
commit
924a0c092e
@ -145,7 +145,11 @@ class BaseArchive:
|
|||||||
def target_filename(self, to_path, name):
|
def target_filename(self, to_path, name):
|
||||||
target_path = os.path.abspath(to_path)
|
target_path = os.path.abspath(to_path)
|
||||||
filename = os.path.abspath(os.path.join(target_path, name))
|
filename = os.path.abspath(os.path.join(target_path, name))
|
||||||
if not filename.startswith(target_path):
|
try:
|
||||||
|
if os.path.commonpath([target_path, filename]) != target_path:
|
||||||
|
raise SuspiciousOperation("Archive contains invalid path: '%s'" % name)
|
||||||
|
except ValueError:
|
||||||
|
# Different drives on Windows raises ValueError.
|
||||||
raise SuspiciousOperation("Archive contains invalid path: '%s'" % name)
|
raise SuspiciousOperation("Archive contains invalid path: '%s'" % name)
|
||||||
return filename
|
return filename
|
||||||
|
|
||||||
|
@ -15,3 +15,11 @@ CVE-2025-59681: Potential SQL injection in ``QuerySet.annotate()``, ``alias()``,
|
|||||||
to SQL injection in column aliases, using a suitably crafted dictionary, with
|
to SQL injection in column aliases, using a suitably crafted dictionary, with
|
||||||
dictionary expansion, as the ``**kwargs`` passed to these methods (follow up to
|
dictionary expansion, as the ``**kwargs`` passed to these methods (follow up to
|
||||||
:cve:`2022-28346`).
|
:cve:`2022-28346`).
|
||||||
|
|
||||||
|
CVE-2025-59682: Potential partial directory-traversal via ``archive.extract()``
|
||||||
|
===============================================================================
|
||||||
|
|
||||||
|
The ``django.utils.archive.extract()`` function, used by
|
||||||
|
:option:`startapp --template` and :option:`startproject --template`, allowed
|
||||||
|
partial directory-traversal via an archive with file paths sharing a common
|
||||||
|
prefix with the target directory (follow up to :cve:`2021-3281`).
|
||||||
|
@ -15,3 +15,11 @@ CVE-2025-59681: Potential SQL injection in ``QuerySet.annotate()``, ``alias()``,
|
|||||||
to SQL injection in column aliases, using a suitably crafted dictionary, with
|
to SQL injection in column aliases, using a suitably crafted dictionary, with
|
||||||
dictionary expansion, as the ``**kwargs`` passed to these methods (follow up to
|
dictionary expansion, as the ``**kwargs`` passed to these methods (follow up to
|
||||||
:cve:`2022-28346`).
|
:cve:`2022-28346`).
|
||||||
|
|
||||||
|
CVE-2025-59682: Potential partial directory-traversal via ``archive.extract()``
|
||||||
|
===============================================================================
|
||||||
|
|
||||||
|
The ``django.utils.archive.extract()`` function, used by
|
||||||
|
:option:`startapp --template` and :option:`startproject --template`, allowed
|
||||||
|
partial directory-traversal via an archive with file paths sharing a common
|
||||||
|
prefix with the target directory (follow up to :cve:`2021-3281`).
|
||||||
|
@ -17,6 +17,14 @@ to SQL injection in column aliases, using a suitably crafted dictionary, with
|
|||||||
dictionary expansion, as the ``**kwargs`` passed to these methods (follow up to
|
dictionary expansion, as the ``**kwargs`` passed to these methods (follow up to
|
||||||
:cve:`2022-28346`).
|
:cve:`2022-28346`).
|
||||||
|
|
||||||
|
CVE-2025-59682: Potential partial directory-traversal via ``archive.extract()``
|
||||||
|
===============================================================================
|
||||||
|
|
||||||
|
The ``django.utils.archive.extract()`` function, used by
|
||||||
|
:option:`startapp --template` and :option:`startproject --template`, allowed
|
||||||
|
partial directory-traversal via an archive with file paths sharing a common
|
||||||
|
prefix with the target directory (follow up to :cve:`2021-3281`).
|
||||||
|
|
||||||
Bugfixes
|
Bugfixes
|
||||||
========
|
========
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ import stat
|
|||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
|
import zipfile
|
||||||
|
|
||||||
from django.core.exceptions import SuspiciousOperation
|
from django.core.exceptions import SuspiciousOperation
|
||||||
from django.test import SimpleTestCase
|
from django.test import SimpleTestCase
|
||||||
@ -94,3 +95,21 @@ class TestArchiveInvalid(SimpleTestCase):
|
|||||||
with self.subTest(entry), tempfile.TemporaryDirectory() as tmpdir:
|
with self.subTest(entry), tempfile.TemporaryDirectory() as tmpdir:
|
||||||
with self.assertRaisesMessage(SuspiciousOperation, msg % invalid_path):
|
with self.assertRaisesMessage(SuspiciousOperation, msg % invalid_path):
|
||||||
archive.extract(os.path.join(archives_dir, entry), tmpdir)
|
archive.extract(os.path.join(archives_dir, entry), tmpdir)
|
||||||
|
|
||||||
|
def test_extract_function_traversal_startswith(self):
|
||||||
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
|
base = os.path.abspath(tmpdir)
|
||||||
|
tarfile_handle = tempfile.NamedTemporaryFile(suffix=".zip", delete=False)
|
||||||
|
tar_path = tarfile_handle.name
|
||||||
|
tarfile_handle.close()
|
||||||
|
self.addCleanup(os.remove, tar_path)
|
||||||
|
|
||||||
|
malicious_member = os.path.join(base + "abc", "evil.txt")
|
||||||
|
with zipfile.ZipFile(tar_path, "w") as zf:
|
||||||
|
zf.writestr(malicious_member, "evil\n")
|
||||||
|
zf.writestr("test.txt", "data\n")
|
||||||
|
|
||||||
|
with self.assertRaisesMessage(
|
||||||
|
SuspiciousOperation, "Archive contains invalid path"
|
||||||
|
):
|
||||||
|
archive.extract(tar_path, base)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user