diff --git a/django/contrib/sessions/backends/file.py b/django/contrib/sessions/backends/file.py index 843edca9cf..2c4e40dbc7 100644 --- a/django/contrib/sessions/backends/file.py +++ b/django/contrib/sessions/backends/file.py @@ -26,6 +26,8 @@ class SessionStore(SessionBase): self.file_prefix = settings.SESSION_COOKIE_NAME super(SessionStore, self).__init__(session_key) + VALID_KEY_CHARS = set("abcdef0123456789") + def _key_to_file(self, session_key=None): """ Get the file associated with this session key. @@ -36,9 +38,9 @@ class SessionStore(SessionBase): # Make sure we're not vulnerable to directory traversal. Session keys # should always be md5s, so they should never contain directory # components. - if os.path.sep in session_key: + if not set(session_key).issubset(self.VALID_KEY_CHARS): raise SuspiciousOperation( - "Invalid characters (directory components) in session key") + "Invalid characters in session key") return os.path.join(self.storage_path, self.file_prefix + session_key) diff --git a/django/contrib/sessions/tests.py b/django/contrib/sessions/tests.py index 941c7e811b..afdb761816 100644 --- a/django/contrib/sessions/tests.py +++ b/django/contrib/sessions/tests.py @@ -11,7 +11,7 @@ from django.contrib.sessions.backends.cached_db import SessionStore as CacheDBSe from django.contrib.sessions.backends.file import SessionStore as FileSession from django.contrib.sessions.models import Session from django.contrib.sessions.middleware import SessionMiddleware -from django.core.exceptions import ImproperlyConfigured +from django.core.exceptions import ImproperlyConfigured, SuspiciousOperation from django.http import HttpResponse from django.test import TestCase, RequestFactory from django.utils import unittest @@ -322,6 +322,16 @@ class FileSessionTests(SessionTestsMixin, unittest.TestCase): settings.SESSION_FILE_PATH = "/if/this/directory/exists/you/have/a/weird/computer" self.assertRaises(ImproperlyConfigured, self.backend) + def test_invalid_key_backslash(self): + # Ensure we don't allow directory-traversal + self.assertRaises(SuspiciousOperation, + self.backend("a\\b\\c").load) + + def test_invalid_key_forwardslash(self): + # Ensure we don't allow directory-traversal + self.assertRaises(SuspiciousOperation, + self.backend("a/b/c").load) + class CacheSessionTests(SessionTestsMixin, unittest.TestCase):