Explorar el Código

Prevent unsafe usernames
If an attacker is able to create an account with a username like "user/calendar.ics", he can access collections of other users.

Unrud hace 9 años
padre
commit
da1a693620
Se han modificado 3 ficheros con 20 adiciones y 1 borrados
  1. 6 1
      radicale/__init__.py
  2. 5 0
      radicale/rights.py
  3. 9 0
      radicale/storage.py

+ 6 - 1
radicale/__init__.py

@@ -311,7 +311,12 @@ class Application:
                 headers = {"Location": redirect}
             return response(status, headers)
 
-        is_authenticated = self.is_authenticated(user, password)
+        if user and not storage.is_safe_path_component(user):
+            # Prevent usernames like "user/calendar.ics"
+            self.logger.info("Refused unsafe username: %s", user)
+            is_authenticated = False
+        else:
+            is_authenticated = self.is_authenticated(user, password)
         is_valid_user = is_authenticated or not user
 
         # Get content

+ 5 - 0
radicale/rights.py

@@ -43,6 +43,8 @@ from configparser import ConfigParser
 from importlib import import_module
 from io import StringIO
 
+from . import storage
+
 
 def load(configuration, logger):
     """Load the rights manager chosen in configuration."""
@@ -103,6 +105,9 @@ class Rights(BaseRights):
 
     def authorized(self, user, collection, permission):
         user = user or ''
+        if user and not storage.is_safe_path_component(user):
+            # Prevent usernames like "user/calendar.ics"
+            raise ValueError("Unsafe username")
         collection_url = collection.path.rstrip("/") or "/"
         if collection_url in (".well-known/carddav", ".well-known/caldav"):
             return permission == "r"

+ 9 - 0
radicale/storage.py

@@ -103,6 +103,15 @@ def get_etag(text):
     return '"%s"' % etag.hexdigest()
 
 
+def is_safe_path_component(path):
+    """Check if path is a single component of a path.
+
+    Check that the path is safe to join too.
+
+    """
+    return path and "/" not in path and path not in (".", "..")
+
+
 def sanitize_path(path):
     """Make path absolute with leading slash to prevent access to other data.