diff --git a/django/contrib/sessions/backends/file.py b/django/contrib/sessions/backends/file.py index 3f6350345fa0a..c3516ea328050 100644 --- a/django/contrib/sessions/backends/file.py +++ b/django/contrib/sessions/backends/file.py @@ -26,6 +26,8 @@ def __init__(self, session_key=None): 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 @@ def _key_to_file(self, session_key=None): # 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 f0a3c4ec8c4f7..01faab859cc3a 100644 --- a/django/contrib/sessions/tests.py +++ b/django/contrib/sessions/tests.py @@ -129,6 +129,17 @@ >>> file_session = FileSession(file_session.session_key) >>> file_session.save() +# Ensure we don't allow directory traversal +>>> FileSession("a/b/c").load() +Traceback (innermost last): + ... +SuspiciousOperation: Invalid characters in session key + +>>> FileSession("a\\b\\c").load() +Traceback (innermost last): + ... +SuspiciousOperation: Invalid characters in session key + # Make sure the file backend checks for a good storage dir >>> settings.SESSION_FILE_PATH = "/if/this/directory/exists/you/have/a/weird/computer" >>> FileSession()