HIGH api rate abusehanamimutual tls

Api Rate Abuse in Hanami with Mutual Tls

Api Rate Abuse in Hanami with Mutual Tls — how this specific combination creates or exposes the vulnerability

Rate abuse in Hanami when mutual TLS is used involves two factors: the identity claims carried in client certificates and the application’s ability to enforce limits per identity. Mutual TLS authenticates each request with a client certificate, typically presenting the identity as a Subject Distinguished Name (DN), a Common Name (CN), or a SAN (e.g., email or URI). If the server maps these certificate fields to identities and applies rate limits per identity, the control is effective. However, if mapping is missing or inconsistent, the same client can present many different valid certificates, bypassing per-identity limits. This can surface as authentication bypass-like behavior where unauthenticated or elevated paths are reachable because the server fails to tie requests to a stable identity.

Another angle is that mutual TLS terminates at the reverse proxy or load balancer before reaching Hanami. If the proxy does not forward a stable identity header (e.g., SSL_CLIENT_S_DN or a mapped certificate serial) and Hanami only relies on IP-based limits, an attacker can rotate client certificates while keeping the source IP constant, evading IP-centric throttling. Additionally, certificate validity periods and lack of revocation checking can allow compromised or abused identities to persist across rate-limit windows. Inconsistent enforcement across endpoints (some routes verify client certs and apply limits, others do not) can create weak paths where abuse migrates. Attack patterns include certificate cycling, where a script rotates through a pool of valid certs to distribute requests, and identity spoofing, where a valid cert is used beyond intended scope.

When scanning an API with mutual TLS using middleBrick, findings may highlight missing identity mapping, missing revocation checks, or lack of per-identity rate limiting. Even though middleBrick tests unauthenticated attack surfaces, it can detect whether the API exposes inconsistent rate-limiting behaviors across endpoints and whether certificate-based identities are treated as first-class access controls. These checks align with the Authentication and Rate Limiting components of the 12 security checks, emphasizing the need to treat client certificate identity as a stable, authoritative factor rather than an implicit trust signal.

Mutual Tls-Specific Remediation in Hanami — concrete code fixes

Remediation centers on canonicalizing the client certificate into a stable identity and enforcing rate limits per identity across all relevant routes. In Hanami, you can use a Rack middleware or an endpoint-level before action to extract certificate fields, normalize them, and attach them to the request environment. Below is a Ruby example that extracts the Common Name (CN) from the client certificate and stores a canonical identity in env. This identity is then used by a rate-limiting rule.

require 'openssl'

class MutualTlsIdentity
  def initialize(app)
    @app = app
  end

  def call(env)
    if cert = env['ssl_client_cert']
      subject = cert.subject
      cn = extract_cn(subject)
      env['hanami.mtls.identity'] = cn
    else
      env['hanami.mtls.identity'] = 'anonymous'
    end
    @app.call(env)
  end

  private

  def extract_cn(subject)
    subject.to_a.find { |item| item.first == 'CN' }&.last
  end
end

# config/initializers/middleware.rb
Hanami.configure do
  config.middleware.insert_before 0, MutualTlsIdentity
end

With the identity in place, configure a rate limit that is keyed by this identity. Using rack-attack, you can define a throttle that uses env['hanami.mtls.identity'] as the key. This ensures that each certificate identity is limited independently, and cycling certificates does not bypass the limit.

# config/initializers/rack_attack.rb
class Rack::Attack
  throttle('requests/by_mtls_identity', limit: 30, period: 60) do |req|
    req.env['hanami.mtls.identity'] || req.ip
  end

  self.throttled_response = lambda do |env|
    [429, { 'Content-Type' => 'application/json' }, [{ error: 'rate limit exceeded' }.to_json]]
  end
end

In a Hanami controller, you can also enforce an additional application-level guard for critical endpoints, combining both Rack throttling and explicit checks. This is useful when you want to apply stricter limits to sensitive actions.

# apps/web/controllers/accounts_controller.rb
class AccountsController < Hanami::Action
  before :ensure_rate_limit

  private

  def ensure_rate_limit
    identity = env['hanami.mtls.identity']
    key = "rate_limit:#{identity}"
    current = $redis.get(key).to_i
    if current >= 30
      halt 429, { error: 'too many requests' }.to_json
    else
      $redis.multi do
        $redis.incr(key)
        $redis.expire(key, 60)
      end
    end
  end
end

On the infrastructure side, ensure that your reverse proxy or load balancer passes the extracted identity downstream. When terminating mutual TLS at the edge, set a header such as X-Client-Cert-CN that Hanami reads to rebuild the identity consistently. Avoid relying solely on IP when mutual TLS is used, and include certificate metadata in your logs for auditability. Periodically refresh certificate revocation information and validate that expired or revoked certificates are rejected at the TLS layer, preventing stale identities from influencing rate decisions.

Frequently Asked Questions

How does middleBrick handle mutual TLS during scans?
middleBrick tests the unauthenticated attack surface and can identify whether rate-limiting controls are present and whether certificate-based identities are consistently mapped. It does not test internal proxy configurations but flags inconsistencies in endpoint protection.
Can rate abuse still occur if I use mutual TLS without identity mapping?
Yes. Without mapping certificate fields to a stable identity and applying per-identity limits, attackers can rotate certificates to bypass rate controls. Always normalize certificate identity and enforce limits on that normalized value.