summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMariusz Felisiak <felisiak.mariusz@gmail.com>2020-08-21 12:43:45 +0200
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2020-08-25 10:45:33 +0200
commitcdb367c92a0ba72ddc0cbd13ff42b0e6df709554 (patch)
tree738280ec978bd8b9d74e5d5e86f0de670c52e942
parent08892bffd275c79ee1f8f67639eb170aaaf1181e (diff)
[3.0.x] Fixed CVE-2020-24584 -- Fixed permission escalation in intermediate-level directories of the file system cache on Python 3.7+.
Backport of f56b57976133129b0b351a38bba4ac882badabf0 from master.
-rw-r--r--django/core/cache/backends/filebased.py8
-rw-r--r--docs/releases/2.2.16.txt9
-rw-r--r--docs/releases/3.0.10.txt9
-rw-r--r--tests/cache/tests.py26
4 files changed, 48 insertions, 4 deletions
diff --git a/django/core/cache/backends/filebased.py b/django/core/cache/backends/filebased.py
index 48b8df90ab..64cc175b18 100644
--- a/django/core/cache/backends/filebased.py
+++ b/django/core/cache/backends/filebased.py
@@ -113,7 +113,13 @@ class FileBasedCache(BaseCache):
self._delete(fname)
def _createdir(self):
- os.makedirs(self._dir, 0o700, exist_ok=True)
+ # Set the umask because os.makedirs() doesn't apply the "mode" argument
+ # to intermediate-level directories.
+ old_umask = os.umask(0o077)
+ try:
+ os.makedirs(self._dir, 0o700, exist_ok=True)
+ finally:
+ os.umask(old_umask)
def _key_to_file(self, key, version=None):
"""
diff --git a/docs/releases/2.2.16.txt b/docs/releases/2.2.16.txt
index f0c3ec894a..f531871d1a 100644
--- a/docs/releases/2.2.16.txt
+++ b/docs/releases/2.2.16.txt
@@ -4,7 +4,7 @@ Django 2.2.16 release notes
*Expected September 1, 2020*
-Django 2.2.16 fixes a security issue and two data loss bugs in 2.2.15.
+Django 2.2.16 fixes two security issues and two data loss bugs in 2.2.15.
CVE-2020-24583: Incorrect permissions on intermediate-level directories on Python 3.7+
======================================================================================
@@ -17,6 +17,13 @@ files and to intermediate-level collected static directories when using the
You should review and manually fix permissions on existing intermediate-level
directories.
+CVE-2020-24584: Permission escalation in intermediate-level directories of the file system cache on Python 3.7+
+===============================================================================================================
+
+On Python 3.7+, the intermediate-level directories of the file system cache had
+the system's standard umask rather than ``0o077`` (no group or others
+permissions).
+
Bugfixes
========
diff --git a/docs/releases/3.0.10.txt b/docs/releases/3.0.10.txt
index 4238a9fd71..ebc67d4725 100644
--- a/docs/releases/3.0.10.txt
+++ b/docs/releases/3.0.10.txt
@@ -4,7 +4,7 @@ Django 3.0.10 release notes
*Expected September 1, 2020*
-Django 3.0.10 fixes a security issue and two data loss bugs in 3.0.9.
+Django 3.0.10 fixes two security issues and two data loss bugs in 3.0.9.
CVE-2020-24583: Incorrect permissions on intermediate-level directories on Python 3.7+
======================================================================================
@@ -17,6 +17,13 @@ files and to intermediate-level collected static directories when using the
You should review and manually fix permissions on existing intermediate-level
directories.
+CVE-2020-24584: Permission escalation in intermediate-level directories of the file system cache on Python 3.7+
+===============================================================================================================
+
+On Python 3.7+, the intermediate-level directories of the file system cache had
+the system's standard umask rather than ``0o077`` (no group or others
+permissions).
+
Bugfixes
========
diff --git a/tests/cache/tests.py b/tests/cache/tests.py
index d8ea676875..c0f90b8326 100644
--- a/tests/cache/tests.py
+++ b/tests/cache/tests.py
@@ -6,11 +6,13 @@ import os
import pickle
import re
import shutil
+import sys
import tempfile
import threading
import time
import unittest
-from unittest import mock
+from pathlib import Path
+from unittest import mock, skipIf
from django.conf import settings
from django.core import management, signals
@@ -1443,6 +1445,28 @@ class FileBasedCacheTests(BaseCacheTests, TestCase):
# Returns the default instead of erroring.
self.assertEqual(cache.get('foo', 'baz'), 'baz')
+ @skipIf(
+ sys.platform == 'win32',
+ 'Windows only partially supports umasks and chmod.',
+ )
+ def test_cache_dir_permissions(self):
+ os.rmdir(self.dirname)
+ dir_path = Path(self.dirname) / 'nested' / 'filebasedcache'
+ for cache_params in settings.CACHES.values():
+ cache_params['LOCATION'] = dir_path
+ setting_changed.send(self.__class__, setting='CACHES', enter=False)
+ cache.set('foo', 'bar')
+ self.assertIs(dir_path.exists(), True)
+ tests = [
+ dir_path,
+ dir_path.parent,
+ dir_path.parent.parent,
+ ]
+ for directory in tests:
+ with self.subTest(directory=directory):
+ dir_mode = directory.stat().st_mode & 0o777
+ self.assertEqual(dir_mode, 0o700)
+
def test_get_does_not_ignore_non_filenotfound_exceptions(self):
with mock.patch('builtins.open', side_effect=OSError):
with self.assertRaises(OSError):