Brute Force Attack in Hanami with Api Keys
Brute Force Attack in Hanami with Api Keys — how this specific combination creates or exposes the vulnerability
A brute force attack against an API that uses API keys often arises when the server does not enforce sufficient rate limiting or account lockout. In a Hanami application, if API key validation is performed but the endpoint does not limit the number of attempts per key or per client, an attacker can systematically guess valid keys or iterate over requests to infer key validity.
Consider a Hanami API that expects an Authorization header formatted as Bearer <api_key>. If the server responds with distinct statuses—such as 200 OK for a valid key and 401 Unauthorized for an invalid key—an attacker can learn which keys are valid and then focus attempts on those. Even when the endpoint requires a key, the absence of per-key rate limiting or exponential backoff allows an attacker to make many rapid requests, increasing the likelihood of a successful key discovery or token collision.
This pattern is relevant to the BFLA/Privilege Escalation and Authentication checks in middleBrick’s 12 security checks. For example, an unauthenticated scan might detect that an endpoint accepts API keys but does not enforce sufficient attempt throttling, making it easier to guess valid keys over time. The scanner flags this as a finding and maps it to OWASP API Top 10:2023 — Broken Object Level Authorization and Authentication, and relevant compliance frameworks such as PCI-DSS and SOC2 controls around access management.
In a real-world scenario, an attacker could use a script to send numerous requests with different key values to an endpoint like /v1/account. If responses differ significantly between invalid and valid keys, or if the server leaks timing differences, the attacker gains information that can be used to compromise the API. middleBrick’s scan would surface the absence of rate limiting and inconsistent response behavior as findings, providing severity ratings and remediation guidance to help developers tighten access controls.
Api Keys-Specific Remediation in Hanami — concrete code fixes
To mitigate brute force risks when using API keys in Hanami, apply rate limiting per key, enforce strict request validation, and standardize error responses to avoid leaking key validity. Below are concrete examples showing how to implement these controls.
1. Rate limiting with a key-based store
Use a cache store (e.g., Redis) to track request counts per API key. This example defines a Hanami action that checks and increments a counter, rejecting requests that exceed the threshold.
require "redis"
class Account::Show
include Hanami::Action
REDIS = Redis.new(url: ENV.fetch("REDIS_URL", "redis://localhost:6379/0"))
RATE_LIMIT = 60 # requests
WINDOW = 60 # per second
def call(params)
api_key = params.fetch("HTTP_AUTHORIZATION", "").to_s.gsub(/^Bearer\s+/, "")
return halt(401, { error: "Unauthorized" }.to_json) if api_key.empty?
current = REDIS.get("rate_limit:#{api_key}")&.to_i || 0
if current >= RATE_LIMIT
return halt(429, { error: "Too many requests" }.to_json)
end
REDIS.multi do
REDIS.incr("rate_limit:#{api_key}")
REDIS.expire("rate_limit:#{api_key}", WINDOW)
end
# proceed with authenticated logic
account = AccountRepository.new.find_by(api_key: api_key)
if account
Response.new(200, {}, AccountSerializer.new(account).render)
else
halt(401, { error: "Unauthorized" }.to_json)
end
end
end
2. Standardized error responses
Return the same status code and generic message for invalid keys to prevent attackers from distinguishing valid from invalid keys. Avoid including details that could aid enumeration.
class Application::Action
include Hanami::Action
def call(params)
api_key = params.fetch("HTTP_AUTHORIZATION", "").to_s.gsub(/^Bearer\s+/, "")
# Validate format first (e.g., length, charset)
unless api_key.match?(/\A[a-zA-Z0-9\-_]{20,40}\z/)
return halt(401, { error: "Unauthorized" }.to_json)
end
account = AccountRepository.new.find_by(api_key: api_key)
if account
Response.new(200, {}, AccountSerializer.new(account).render)
else
# Always return the same status and body shape
halt(401, { error: "Unauthorized" }.to_json)
end
end
end
3. Enforce HTTPS and rotate keys
Ensure all API traffic uses TLS to prevent key interception, and rotate keys periodically. These practices reduce the window for successful brute force attempts even if rate limiting fails temporarily.
4. Use middleBrick to validate your implementation
Run a scan with the middleBrick CLI to confirm that your endpoints now enforce rate limiting and return consistent responses:
middlebrick scan https://api.yourdomain.com/v1/account
In the dashboard, review the Authentication and Rate Limiting findings, and iterate based on the provided remediation guidance. For teams that require continuous assurance, the Pro plan adds scheduled scans and GitHub Action integration to fail builds if score thresholds are not met.