Implementation of a robust and secure mechanism to prevent brute force attacks on promotional codes.
class PromoCodesController < ApplicationController
def validate_code
code = params[:code]
promo_code = PromoCode.find_by(code: code)
if promo_code
render json: { valid: true, discount: promo_code.discount }
else
render json: { valid: false }
end
end
end
In the above code, there is a
validate_code
method in the
PromoCodesController
which is used to validate if the provided promotional code is valid or not. The method takes a
code
parameter from the request, and then it tries to find a promotional code in the database that matches the provided code.
If a matching promotional code is found, the method responds with a JSON object indicating that the code is valid and also includes the discount associated with the code. If no matching code is found, the method responds with a JSON object indicating that the code is invalid.
The vulnerability here is that there are no protections in place against brute force attacks. An attacker could potentially automate requests to this endpoint with different codes until they find a valid one. There are no rate limiting or captcha mechanisms in place to prevent or slow down such automated attacks.
class PromoCodesController < ApplicationController
before_action :check_rate_limit, only: [:validate_code]
def validate_code
code = params[:code]
promo_code = PromoCode.find_by(code: code)
if promo_code
render json: { valid: true, discount: promo_code.discount }
else
render json: { valid: false }
end
end
private
def check_rate_limit
client_ip = request.remote_ip
limit = 5
period = 60
count = Rails.cache.fetch("promo_code/#{client_ip}", expires_in: period.seconds) do
0
end
if count >= limit
render json: { error: 'Too many requests' }, status: :too_many_requests
else
Rails.cache.write("promo_code/#{client_ip}", count + 1, expires_in: period.seconds)
end
end
end
The updated code now includes a
before_action
filter that checks the rate limit before the
validate_code
action is executed. This filter is defined in the
check_rate_limit
private method.
In the
check_rate_limit
method, we first get the client's IP address. We then define a limit for the number of requests (5 requests) and a period for the limit (60 seconds).
We use Rails' caching mechanism to store the number of requests from each IP address. If the cache for the IP address does not exist, we initialize it with 0.
If the number of requests from the IP address has reached the limit, we return a 'Too many requests' error with a 429 status code (Too Many Requests). If the limit has not been reached, we increment the count in the cache.
This way, we limit the number of requests to the
validate_code
action from each IP address to 5 requests per minute, effectively preventing brute force attacks.