From 27d91aa2eb521d2553408988bbd4fa0ade4aa09e Mon Sep 17 00:00:00 2001 From: John Pinto Date: Tue, 24 Sep 2024 16:50:19 +0100 Subject: [PATCH] Updated Rack Attack configuration to address vulnerabilities in password updates. Changes: The fix involves adding a new Rack Attack rule "profile_updates/ip" and rewriting the body of the rules "password_resets/ip" and "logins/ip" so the the request ip is returned if the rule is triggered. --- CHANGELOG.md | 2 ++ Gemfile | 1 + config/initializers/rack_attack.rb | 26 ++++++++++++++++++++------ 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3aeeb4e2f3..7dbc6d0e3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # Changelog +- Updated Rack Attack configuration to address vulnerabilities in password updates. + ## v4.2.0 **Note this upgrade is mainly a migration from Bootstrap 3 to Bootstrap 5.** diff --git a/Gemfile b/Gemfile index ba04ab6fa4..0ba6704a94 100644 --- a/Gemfile +++ b/Gemfile @@ -109,6 +109,7 @@ gem 'jwt' gem 'pundit' # Gem for throttling malicious attacks +gem 'dalli', '~> 3.2', '>= 3.2.8' gem 'rack-attack', '~> 6.6', '>= 6.6.1' # ========== # diff --git a/config/initializers/rack_attack.rb b/config/initializers/rack_attack.rb index c8ca0f574c..c79af5b631 100644 --- a/config/initializers/rack_attack.rb +++ b/config/initializers/rack_attack.rb @@ -6,7 +6,10 @@ Rack::Attack.enabled = true # Cache store required to work. -Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new # defaults to Rails.cache +# Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new # defaults to Rails.cache + +Rack::Attack.cache.store = ActiveSupport::Cache::MemCacheStore.new +# Rack::Attack.cache.store = ActiveSupport::Cache::FileStore.new("/tmp/cache") # Throttle should send a 429 Error responsec code and display public/429.html Rack::Attack.throttled_responder = lambda do |_env| @@ -14,13 +17,24 @@ [429, { 'Content-Type' => 'text/html' }, [html]] end -# Throttle attempts to a particular path. 2 POSTs to /users/password every 30 seconds -Rack::Attack.throttle "password_resets/ip", limit: 2, period: 30.seconds do |req| - req.post? && req.path == "/users/password" && req.ip -end +# # Throttle attempts to a particular path. 2 POSTs to /users/password every 30 seconds +# Rack::Attack.throttle "password_resets/ip", limit: 2, period: 30.seconds do |req| +# req.ip if req.post? && req.path == "/users/password" +# end # Throttle attempts to a particular path. 4 POSTs to /users/sign_in every 30 seconds Rack::Attack.throttle "logins/ip", limit: 4, period: 30.seconds do |req| # Don't apply sign-in rate-limiting to test environment - req.post? && req.path == "/users/sign_in" && req.ip unless Rails.env.test? + (req.ip if req.post? && req.path == "/users/sign_in") unless Rails.env.test? +end + +# Throttle attempts to a particular path. 3 POST or PUTS to /users every 20 seconds +# This includes password updates. This is to prevent brute force attacks on user.accept_terms. +# This replaces the previous throttle on /users/password and is extended to other profile update. +# Exclude test environment. +Rack::Attack.throttle "profile_updates", limit: 3, period: 20.seconds do |req| + if !Rails.env.test? && req.path != "/users/sign_in" && (req.put? || req.post?) && req.path.start_with?("/users") + puts "Throttling #{req.ip} for #{req.path}" + req.ip + end end