CVE-2023-2227 (published 2023-04-21T13:15Z)

Improper Authorization in GitHub repository modoboa/modoboa prior to 2.1.0.

CVSS v3 base score: 9.1, CRITICAL (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N)

Weakness information:
cwe_id: CWE-285
cwe_name: Improper Authorization
description: The product does not perform or incorrectly performs an authorization check when an actor attempts to access a resource or perform an action.
extended_description: 
            Assuming a user with a given identity, authorization is the process of determining whether that user can access a given resource, based on the user's privileges and any permissions or other access-control specifications that apply to the resource.
            When access control checks are not applied consistently - or not at all - users are able to access data or perform actions that they should not be allowed to perform. This can lead to a wide range of problems, including information exposures, denial of service, and arbitrary code execution.
         
         

Fix information:
repo_url: https://github.com/modoboa/modoboa
commit_details: repo_url: https://github.com/modoboa/modoboa
author: Antoine Nguyen
author_date: 2023-02-27 11:12:21+01:00
msg: Added missing permissions on API endpoints
repository: repo_url: https://github.com/modoboa/modoboa
repo_name: modoboa/modoboa
description: Mail hosting made simple
repo_language: Python
owner: modoboa
file_changes: filename: viewsets.py
change_type: ModificationType.MODIFY
diff: @@ -93,7 +93,6 @@ class AccountViewSet(GetThrottleViewsetMixin, lib_viewsets.RevisionModelMixin, v
         throttles = super().get_throttles()
         if self.action == "reset_password":
             throttles.append(PasswordResetRequestThrottle())
-        
         return throttles
 
     def get_serializer_class(self):

programming_language: Python
filename: views.py
change_type: ModificationType.MODIFY
diff: @@ -9,7 +9,7 @@ from django.utils.datastructures import MultiValueDictKeyError
 from django.contrib.auth import login
 
 from drf_spectacular.utils import extend_schema
-from rest_framework import response, status
+from rest_framework import permissions, response, status
 from rest_framework.exceptions import AuthenticationFailed
 from rest_framework_simplejwt import views as jwt_views
 from rest_framework_simplejwt.exceptions import InvalidToken
@@ -17,7 +17,11 @@ from rest_framework.views import APIView
 
 from modoboa.core.password_hashers import get_password_hasher
 from modoboa.core.utils import check_for_updates
-from modoboa.lib.throttle import UserLesserDdosUser, LoginThrottle, PasswordResetApplyThrottle, PasswordResetRequestThrottle, PasswordResetTotpThrottle
+from modoboa.lib.permissions import IsSuperUser
+from modoboa.lib.throttle import (
+    UserLesserDdosUser, LoginThrottle, PasswordResetApplyThrottle,
+    PasswordResetRequestThrottle, PasswordResetTotpThrottle
+)
 from modoboa.parameters import tools as param_tools
 
 from smtplib import SMTPException
@@ -192,6 +196,7 @@ class PasswordResetConfirmView(APIView):
 class ComponentsInformationAPIView(APIView):
     """Retrieve information about installed components."""
 
+    permission_classes = [permissions.IsAuthenticated, IsSuperUser]
     throttle_classes = [UserLesserDdosUser]
 
     @extend_schema(responses=serializers.ModoboaComponentSerializer(many=True))

programming_language: Python
filename: permissions.py
change_type: ModificationType.MODIFY
diff: @@ -3,6 +3,8 @@
 from django.contrib.auth.models import Group, Permission
 from django.contrib.contenttypes.models import ContentType
 
+from rest_framework import permissions
+
 from modoboa.core import constants as core_constants, signals as core_signals
 from modoboa.core.models import ObjectAccess, User
 
@@ -150,3 +152,10 @@ def add_permissions_to_group(group, permissions):
         group.permissions.add(
             Permission.objects.get(content_type=ct, codename=permname)
         )
+
+
+class IsSuperUser(permissions.BasePermission):
+    """Permission class to allow only super users."""
+
+    def has_permission(self, request, view):
+        return request.user.is_superuser

programming_language: Python
filename: viewsets.py
change_type: ModificationType.MODIFY
diff: @@ -1,9 +1,10 @@
 """Parameters viewsets."""
 
 from drf_spectacular.utils import extend_schema, OpenApiParameter
-from rest_framework import response, viewsets
+from rest_framework import permissions, response, viewsets
 from rest_framework.decorators import action
 
+from modoboa.lib.permissions import IsSuperUser
 from modoboa.lib.throttle import GetThrottleViewsetMixin
 
 from . import serializers
@@ -14,6 +15,7 @@ class ParametersViewSet(GetThrottleViewsetMixin, viewsets.ViewSet):
     """Parameter viewset."""
 
     lookup_value_regex = r"\w+"
+    permission_classes = [permissions.IsAuthenticated, IsSuperUser]
     serializer_class = None
 
     @extend_schema(responses=serializers.ApplicationSerializer(many=True))

programming_language: Python