HIGH brute force attackhanamiapi keys

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.

Frequently Asked Questions

Why does returning the same HTTP status for invalid and valid API keys help prevent brute force attacks?
Returning the same status code and generic error body prevents attackers from inferring whether a guessed key is valid. Without this uniformity, attackers can use response differences to perform enumeration and prioritize guesses, increasing brute force success risk.
Can rate limiting alone stop brute force attacks on API keys in Hanami?
Rate limiting significantly raises the effort required for brute forcing, but it should be combined with key format validation and consistent error responses. Rate limiting reduces request volume, while uniform responses and strict validation remove signals that attackers could exploit to refine guesses.