chore: Improve rack-attack configuration (#5389)
fixes: https://github.com/chatwoot/product/issues/540
This commit is contained in:
parent
d47a0ae461
commit
9525d4f034
1 changed files with 50 additions and 33 deletions
|
@ -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,50 +48,61 @@ 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?
|
||||
### 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
|
||||
|
||||
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
|
||||
|
||||
# ### 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
|
||||
email.to_s.downcase.gsub(/\s+/, '')
|
||||
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_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: 5.minutes) do |req|
|
||||
req.ip if req.path == '/api/v1/accounts' && req.post?
|
||||
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 == '/api/v1/widget/conversations' && req.post?
|
||||
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 == '/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?
|
||||
# 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
|
||||
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?
|
||||
# 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
|
||||
email.to_s.downcase.gsub(/\s+/, '')
|
||||
end
|
||||
end
|
||||
|
||||
throttle('reset_password/email', limit: 5, period: 1.hour) do |req|
|
||||
if req.path == '/auth/password' && req.post?
|
||||
email = req.params['email'].presence || ActionDispatch::Request.new(req.env).params['email'].presence
|
||||
email.to_s.downcase.gsub(/\s+/, '')
|
||||
end
|
||||
req.ip if req.path_without_extentions == '/api/v1/widget/contacts' && (req.patch? || req.put?)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue