Dictionary Attack in Chi with Mutual Tls
Dictionary Attack in Chi with Mutual Tls — how this specific combination creates or exposes the vulnerability
A dictionary attack in a Chi application that uses mutual TLS (mTLS) can be particularly nuanced because the presence of mTLS shifts some assumptions about how authentication is validated. In Chi, mTLS is typically enforced at the transport layer via a TLS configuration that requests and verifies client certificates. The server uses the certificate presented by the client to extract identity information, often through subject fields or SANs, before authorizing access.
During a dictionary attack in this setup, an attacker does not need to brute-force a password if mTLS is improperly validated. Instead, they may attempt to send many different client certificates, or they may probe the server to understand how certificate validation maps to user identities. If the server uses certificate data to infer usernames or API keys, a dictionary attack can iterate over known identities and present a valid certificate for each guess. Even with mTLS, if the server does not strictly limit the rate of TLS handshakes or certificate checks, this can lead to account enumeration or unauthorized access.
Chi middleware that inspects peer certificates can inadvertently expose information through timing differences or error messages. For example, a route that checks a certificate fingerprint against a database may respond slightly faster for a non-existent entry versus a valid one. An attacker conducting a dictionary attack can use these timing signals to refine guesses. Additionally, if the server does not enforce strict certificate revocation checks, an attacker might use a revoked but previously trusted certificate to probe the system.
The combination of mTLS and dictionary-style probing shifts the attack surface from credential stuffing to identity guessing via certificate metadata. OWASP API Top 10 categories such as Broken Object Level Authorization (BOLA) and Improper Rate Limiting intersect here, because mTLS does not inherently prevent excessive requests tied to certificate identities. middleBrick scans detect these patterns by correlating TLS-level findings with API behavior, highlighting cases where unauthenticated or low-assurance access points exist despite mTLS being in place.
Without active validation controls, a Chi service that relies solely on mTLS for authentication may still leak information about valid identities during a dictionary attack. This is why layered checks—such as verifying certificate fields against an allowlist and enforcing request-level rate limits—are necessary. The presence of mTLS should not reduce scrutiny on how identity is mapped and how requests are throttled.
Mutual Tls-Specific Remediation in Chi — concrete code fixes
To harden a Chi application using mutual TLS, you should enforce strict certificate validation, avoid leaking identity information through timing or error messages, and apply rate limits at the connection or route level. Below are concrete code examples using the cheshire3 and buddy libraries in Clojure, along with configuration guidance.
1. Enforce client certificate validation and map to identities safely
Ensure that the server requests client certificates and validates them against a trusted CA. Do not rely on certificate presence alone; inspect relevant fields and map them to application identities in a way that does not expose timing differences.
(ns myapp.mtls
(:require [cheshire3.protocols :as p]
[cheshire3.certificate :as cert]))
(defn validate-client-cert
"Validate client certificate and extract a normalized identity."
[trusted-certs peer-cert]
(when-let [verified (some #(cert/verify peer-cert %)
trusted-certs)]
;; Use a constant-time comparison for mapping certificate to user
(let [subject (cert/subject-dn peer-cert)
username (extract-username-from-subject subject)]
(when (some? username)
{:user username :verified verified}))))
(defn extract-username-from-subject
"Extract username from subject DN in a constant-time manner."
[subject]
;; Use a fixed lookup and avoid branching on presence to prevent timing leaks
(get subject "CN"))
2. Apply rate limiting at the connection level in Chi routes
Use middleware to limit the number of requests per client certificate within a time window, preventing dictionary-style probing regardless of TLS layer enforcement.
(ns myapp.routes
(:require [cheshire3.middleware :refer [wrap-rate-limit]]
[compojure.core :refer [defroutes GET]]))
(def rate-limiter
(atom {})) ; In production, use a shared store like Redis
(defn build-rate-limit-middleware
[limit window-ms]
(wrap-rate-limit rate-limiter limit window-ms))
(defroutes app-routes
(build-rate-limit-middleware
(GET /api/protected []
{:status 200 :body "OK"})
10 ; limit
60000)) ; window in ms
3. Consistent error handling to avoid information leakage
Ensure that error responses for failed certificate validation are uniform and do not reveal whether a certificate was malformed, untrusted, or missing.
(defn safe-certificate-response
"Return a generic response for any certificate validation failure."
[status-map]
(if (:valid status-map)
{:status 200 :body (:body status-map)}
{:status 403 :body "Forbidden"})) ; Uniform response
(defn handle-tls-request
[request]
(let [peer-cert (:client-cert request)
trusted-certs (:trusted-certs request)]
(safe-certificate-response
(validate-client-cert trusted-certs peer-cert))))
4. Use middleware to enforce mTLS across all routes
Apply a global middleware that ensures client certificates are present and valid before routing proceeds.
(defn enforce-mtls
"Middleware to require and validate client certificates."
[handler]
(fn [request]
(if (cert/has-valid-client-cert? request)
(handler request)
{:status 400 :body "Bad Request"})))
(def app
(-> app-routes
enforce-mtls
(build-rate-limit-middleware 10 60000)))
These examples focus on making certificate validation deterministic, applying rate limits independent of TLS success, and standardizing responses. middleBrick can be used to verify that these controls are correctly applied by scanning the Chi endpoints and checking for unauthenticated paths or weak rate-limiting configurations.