CVE-2022-3741 (published 2022-10-28T13:15Z)

Impact varies for each individual vulnerability in the application. For generation of accounts, it may be possible, depending on the amount of system resources available, to create a DoS event in the server. These accounts still need to be activated; however, it is possible to identify the output Status Code to separate accounts that are generated and waiting for email verification. \\n\\nFor the sign in directories, it is possible to brute force login attempts to either login portal, which could lead to account compromise.

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

Weakness information:
cwe_id: CWE-307
cwe_name: Improper Restriction of Excessive Authentication Attempts
description: The product does not implement sufficient measures to prevent multiple failed authentication attempts within a short time frame, making it more susceptible to brute force attacks.
extended_description: 
            
            
            
         
         

Fix information:
repo_url: https://github.com/chatwoot/chatwoot
commit_details: repo_url: https://github.com/chatwoot/chatwoot
author: Sojan Jose
author_date: 2022-09-02 23:09:03+05:30
msg: chore: Improve rack-attack configuration (#5389)

fixes: https://github.com/chatwoot/product/issues/540
repository: repo_url: https://github.com/chatwoot/chatwoot
repo_name: chatwoot/chatwoot
description: Open-source live-chat, email support, omni-channel desk. An alternative to Intercom, Zendesk, Salesforce Service Cloud etc. 🔥💬
repo_language: Ruby
owner: chatwoot
file_changes: filename: rack_attack.rb
change_type: ModificationType.MODIFY
diff: @@ -24,6 +24,12 @@ class Rack::Attack
       allowed_ips = ['127.0.0.1', '::1']
       allowed_ips.include?(remote_ip)
     end
+
+    # Rails would allow requests to paths with extentions, so lets compare against the path with extention stripped
+    # example /auth & /auth.json would both work
+    def path_without_extentions
+      path[/^[^.]+/]
+    end
   end
 
   ### Throttle Spammy Clients ###
@@ -42,38 +48,29 @@ class Rack::Attack
 
   throttle('req/ip', limit: 300, period: 1.minute, &:ip)
 
-  ### Prevent Brute-Force Login Attacks ###
-  throttle('login/ip', limit: 5, period: 20.seconds) do |req|
-    req.ip if req.path == '/auth/sign_in' && req.post?
-  end
-
-  ## Prevent Brute-Force Signup Attacks ###
-  throttle('accounts/ip', limit: 5, period: 5.minutes) do |req|
-    req.ip if req.path == '/api/v1/accounts' && req.post?
-  end
-
-  ## Prevent Conversation Bombing on Widget APIs ###
-  throttle('api/v1/widget/conversations', limit: 6, period: 12.hours) do |req|
-    req.ip if req.path == '/api/v1/widget/conversations' && req.post?
+  ### Prevent Brute-Force Super Admin Login Attacks ###
+  throttle('super_admin_login/ip', limit: 5, period: 5.minutes) do |req|
+    req.ip if req.path_without_extentions == '/super_admin/sign_in' && req.post?
   end
 
-  ## Prevent Contact update Bombing in Widget API ###
-  throttle('api/v1/widget/contacts', limit: 60, period: 1.hour) do |req|
-    req.ip if req.path == '/api/v1/widget/contacts' && (req.patch? || req.put?)
-  end
-
-  # ref: https://github.com/rack/rack-attack/issues/399
-  throttle('login/email', limit: 20, period: 5.minutes) do |req|
-    if req.path == '/auth/sign_in' && req.post?
+  throttle('super_admin_login/email', limit: 5, period: 15.minutes) do |req|
+    if req.path_without_extentions == '/super_admin/sign_in' && req.post?
       # NOTE: This line used to throw ArgumentError /rails/action_mailbox/sendgrid/inbound_emails : invalid byte sequence in UTF-8
       # Hence placed in the if block
+      # ref: https://github.com/rack/rack-attack/issues/399
       email = req.params['email'].presence || ActionDispatch::Request.new(req.env).params['email'].presence
       email.to_s.downcase.gsub(/\s+/, '')
     end
   end
 
-  throttle('super_admin_login/email', limit: 20, period: 5.minutes) do |req|
-    if req.path == '/super_admin/sign_in' && req.post?
+  # ### Prevent Brute-Force Login Attacks ###
+  throttle('login/ip', limit: 5, period: 5.minutes) do |req|
+    req.ip if req.path_without_extentions == '/auth/sign_in' && req.post?
+  end
+
+  throttle('login/email', limit: 10, period: 15.minutes) do |req|
+    if req.path_without_extentions == '/auth/sign_in' && req.post?
+      # ref: https://github.com/rack/rack-attack/issues/399
       # NOTE: This line used to throw ArgumentError /rails/action_mailbox/sendgrid/inbound_emails : invalid byte sequence in UTF-8
       # Hence placed in the if block
       email = req.params['email'].presence || ActionDispatch::Request.new(req.env).params['email'].presence
@@ -81,12 +78,32 @@ class Rack::Attack
     end
   end
 
+  ## Reset password throttling
+  throttle('reset_password/ip', limit: 5, period: 30.minutes) do |req|
+    req.ip if req.path_without_extentions == '/auth/password' && req.post?
+  end
+
   throttle('reset_password/email', limit: 5, period: 1.hour) do |req|
-    if req.path == '/auth/password' && req.post?
+    if req.path_without_extentions == '/auth/password' && req.post?
       email = req.params['email'].presence || ActionDispatch::Request.new(req.env).params['email'].presence
       email.to_s.downcase.gsub(/\s+/, '')
     end
   end
+
+  ## Prevent Brute-Force Signup Attacks ###
+  throttle('accounts/ip', limit: 5, period: 30.minutes) do |req|
+    req.ip if req.path_without_extentions == '/api/v1/accounts' && req.post?
+  end
+
+  ## Prevent Conversation Bombing on Widget APIs ###
+  throttle('api/v1/widget/conversations', limit: 6, period: 12.hours) do |req|
+    req.ip if req.path_without_extentions == '/api/v1/widget/conversations' && req.post?
+  end
+
+  ## Prevent Contact update Bombing in Widget API ###
+  throttle('api/v1/widget/contacts', limit: 60, period: 1.hour) do |req|
+    req.ip if req.path_without_extentions == '/api/v1/widget/contacts' && (req.patch? || req.put?)
+  end
 end
 
 # Log blocked events

programming_language: Ruby