CVE-2023-5289: Allocation of Resources Without Limits or Throttling (CWE-770)
value: Allocation of Resources Without Limits or Throttling in GitHub repository ikus060/rdiffweb prior to 2.8.4.
CWE description: The product allocates a reusable resource or group of resources on behalf of an actor without imposing any restrictions on the size or number of resources that can be allocated, in violation of the intended security policy for that actor.
CVSS v3 base score: 8.8
Published: 2023-09-29T14:15Z
Repository: https://github.com/ikus060/rdiffweb
Language: Python
Files changed: rdiffweb/controller/page_admin_users.py, rdiffweb/controller/page_pref_sshkeys.py, rdiffweb/controller/page_pref_tokens.py
Commit date: 2023-09-29 08:25:11 -0400
Commit message: Add ratelimit to AccessToken, SSH Keys, User creation

Diff: diff --git a/rdiffweb/controller/page_admin_users.py b/rdiffweb/controller/page_admin_users.py
index 3a2be42ac..fe399480d 100644
--- a/rdiffweb/controller/page_admin_users.py
+++ b/rdiffweb/controller/page_admin_users.py
@@ -263,11 +263,12 @@ class AdminUsersPage(Controller):
             form=form,
             users=UserObject.query.all(),
             ldap_enabled=self.app.cfg.ldap_uri,
         )
 
-    @cherrypy.expose()
+    @cherrypy.expose
+    @cherrypy.tools.ratelimit(methods=['POST'])
     def new(self, **kwargs):
         form = UserForm()
         if form.is_submitted():
             if form.validate():
                 try:
@@ -280,11 +281,11 @@ class AdminUsersPage(Controller):
                         raise cherrypy.HTTPRedirect(url_for('admin', 'users'))
             else:
                 flash(form.error_message, level='error')
         return self._compile_template("admin_user_new.html", form=form)
 
-    @cherrypy.expose()
+    @cherrypy.expose
     def edit(self, username_vpath, **kwargs):
         user = UserObject.get_user(username_vpath)
         if not user:
             raise cherrypy.HTTPError(400, _("User %s doesn't exists") % username_vpath)
         form = EditUserForm(obj=user)
@@ -295,11 +296,11 @@ class AdminUsersPage(Controller):
                     raise cherrypy.HTTPRedirect(url_for('admin', 'users'))
             else:
                 flash(form.error_message, level='error')
         return self._compile_template("admin_user_edit.html", form=form)
 
-    @cherrypy.expose()
+    @cherrypy.expose
     def delete(self, username=None, **kwargs):
         # Validate form method.
         form = DeleteUserForm()
         if not form.is_submitted():
             raise cherrypy.HTTPError(405)
@@ -318,8 +319,5 @@ class AdminUsersPage(Controller):
                 user.rollback()
                 flash(str(e), level='error')
         else:
             flash(form.error_message, level='error')
         raise cherrypy.HTTPRedirect(url_for('admin', 'users'))
-
-
-# TODO Allow configuration of notification settigns
diff --git a/rdiffweb/controller/page_pref_sshkeys.py b/rdiffweb/controller/page_pref_sshkeys.py
index 221f9f3ce..4633af340 100644
--- a/rdiffweb/controller/page_pref_sshkeys.py
+++ b/rdiffweb/controller/page_pref_sshkeys.py
@@ -113,10 +113,11 @@ class DeleteSshForm(CherryForm):
             return False
 
 
 class PagePrefSshKeys(Controller):
     @cherrypy.expose
+    @cherrypy.tools.ratelimit(methods=['POST'])
     def default(self, **kwargs):
         # Handle action
         add_form = SshForm()
         delete_form = DeleteSshForm()
         if not self.app.cfg.disable_ssh_keys:
diff --git a/rdiffweb/controller/page_pref_tokens.py b/rdiffweb/controller/page_pref_tokens.py
index 2d72cfeea..183ea00f1 100644
--- a/rdiffweb/controller/page_pref_tokens.py
+++ b/rdiffweb/controller/page_pref_tokens.py
@@ -117,10 +117,11 @@ class DeleteTokenForm(CherryForm):
             return False
 
 
 class PagePrefTokens(Controller):
     @cherrypy.expose
+    @cherrypy.tools.ratelimit(methods=['POST'])
     def default(self, **kwargs):
         form = TokenForm()
         delete_form = DeleteTokenForm()
         if form.is_submitted():
             if form.validate():

Vulnerable code:     @cherrypy.expose()
    @cherrypy.expose()
    @cherrypy.expose()


# TODO Allow configuration of notification settigns
Fixed code:     @cherrypy.expose
    @cherrypy.tools.ratelimit(methods=['POST'])
    @cherrypy.expose
    @cherrypy.expose
    @cherrypy.tools.ratelimit(methods=['POST'])
    @cherrypy.tools.ratelimit(methods=['POST'])