diff --git a/CHANGELOG.md b/CHANGELOG.md index b64a2b09ad..7f95230bd0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,12 @@ # Changelog -### Added +### Added - Added CHANGELOG.md and Danger Github Action [#3257](https://github.com/DMPRoadmap/roadmap/issues/3257) + - Added rack-attack version 6.6.1 gem. https://rubygems.org/gems/rack-attack/versions/6.6.1 + ### Fixed +- Using Rack-attack address vulnerabilities pointed out in password reset and login: there was no request rate limit.[#3214](https://github.com/DMPRoadmap/roadmap/issues/3214) ### Changed diff --git a/Gemfile b/Gemfile index b700dace31..197d98843a 100644 --- a/Gemfile +++ b/Gemfile @@ -119,6 +119,9 @@ gem 'jwt' # OO authorization for Rails (https://github.com/elabs/pundit) gem 'pundit' +# Gem for throttling malicious attacks +gem 'rack-attack', '~> 6.6', '>= 6.6.1' + # ========== # # UI / VIEWS # # ========== # diff --git a/config/initializers/rack_attack.rb b/config/initializers/rack_attack.rb new file mode 100644 index 0000000000..712315de9b --- /dev/null +++ b/config/initializers/rack_attack.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +# NB: `req` is a Rack::Request object (basically an env hash with friendly accessor methods) + +# Enable/disable Rack::Attack +Rack::Attack.enabled = true + +# Cache store required to work. +Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new # defaults to Rails.cache + +# Throttle should send a 429 Error responsec code and display public/429.html +Rack::Attack.throttled_responder = lambda do |env| + html = ActionView::Base.empty.render(file: 'public/429.html') + [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. 4 POSTs to /users/sign_in every 30 seconds +Rack::Attack.throttle "logins/ip", limit: 4, period: 30.seconds do |req| + req.post? && req.path == "/users/sign_in" && req.ip +end diff --git a/public/429.html b/public/429.html new file mode 100644 index 0000000000..33324d5b6b --- /dev/null +++ b/public/429.html @@ -0,0 +1,29 @@ + + + + We're sorry, but something went wrong (500) + + + + + +
+

Too Many Requests

+ +

You have exceeded the number of requests for this resource. For security reasons access is limited to a fixed number in a given period. Retry later.

+ + +
+ +