Brute Force Attack in Hapi with Api Keys
Brute Force Attack in Hapi with Api Keys — how this specific combination creates or exposes the vulnerability
A brute force attack against an Hapi API that relies solely on API keys as authentication can be effective when protections are absent or misconfigured. Without proper request-rate constraints, an attacker can systematically attempt many keys, or attempt to discover a valid key through high-volume requests. Since API keys are typically long-lived credentials stored and transmitted by clients, they become high-value targets. If an endpoint does not enforce per-key rate limits or account lockout, an attacker can iterate over many candidate keys or replay captured keys at high speed.
In Hapi, the risk is realized when routes that accept API keys lack server-side throttling and when authentication logic does not incorporate incremental delays or token invalidation after suspicious behavior. Attack patterns such as credential stuffing or online guessing are relevant here: the attacker uses previously known or generated keys and observes binary success/failure responses. Successful authentication responses confirm valid keys, enabling attackers to build a working set of credentials. This is especially dangerous when keys are embedded in JavaScript or mobile clients, making them easy to extract and reuse across requests.
Another vector specific to Hapi is the lack of per-route or per-consumer rate limits. By default, Hapi does not enforce global or key-specific request caps. An attacker can open many connections or use automated scripts to hammer authentication endpoints or resource endpoints guarded by API keys. Because the server treats each request independently, without shared state or sliding-window tracking, repeated attempts from the same IP or token may not be detected. The combination of a static key and an open route creates an authentication surface that can be explored at network speed.
Input validation and error handling amplify the problem. If an Hapi route reveals whether a key is valid through timing differences or distinct status codes (e.g., 401 vs 403), attackers can use timing attacks to infer correctness. SSRF or server-side request forgery weaknesses in plugins or route handlers may also allow attackers to pivot from a single compromised service to other internal APIs that also depend on static keys. The absence of mutual TLS or additional context (such as device fingerprinting) further weakens the posture when API keys are the primary credential.
To detect these issues, middleBrick performs unauthenticated black-box scans targeting Hapi endpoints that use API keys. It checks whether responses leak key validity, whether rate limiting is absent or inconsistent, and whether authentication logic can be exercised repeatedly without cost to the attacker. The scanner runs parallel checks including Authentication, Rate Limiting, Input Validation, and Unsafe Consumption to surface risky route configurations and missing controls.
Api Keys-Specific Remediation in Hapi — concrete code fixes
Remediation focuses on adding rate limiting tied to the API key value, standardizing error responses, and ensuring authentication logic does not leak information. Use a shared store (e.g., Redis) to track request counts per key and enforce a sliding window. Respond with a uniform error payload and consistent HTTP status to prevent attackers from distinguishing valid keys.
Example Hapi server with API key authentication and rate limiting using hapi-rate-limit:
const Hapi = require('@hapi/hapi');
const RateLimit = require('hapi-rate-limit');
const init = async () => {
const server = Hapi.server({ port: 4000, host: '0.0.0.0' });
// Rate limit by api_key query parameter or header
await server.register({
plugin: RateLimit,
options: {
limit: 100, // requests
timeWindow: 60, // seconds
keyExtractor: (request) => {
// Prefer header, fall back to query
return request.headers['x-api-key'] || request.query.api_key || 'unknown';
},
cache: {
cache: 'redis', // your Redis cache implementation
expiresIn: 60000
}
}
});
server.route({
method: 'GET',
path: '/resource',
options: {
handler: (request, h) => {
return { data: 'protected' };
},
auth: false // handled inside handler or via a custom auth strategy
}
});
server.route({
method: 'POST',
path('/login',
handler: (request, h) => {
const { api_key } = request.payload;
if (!isValidKey(api_key)) {
// Always same shape and timing
return h.response({ error: 'invalid_request' }).code(400);
}
return h.response({ ok: true });
})
});
const isValidKey = (key) => {
// constant-time comparison against stored keys
const valid = new Set([process.env.API_KEY_1, process.env.API_KEY_2]);
return valid.has(key);
};
await server.start();
};
init();
Key points: use a deterministic key extractor so the same API key is rate-limited across routes; keep error messages generic; avoid branching logic that reveals validity via status codes or response body; and store counts in a shared cache to coordinate limits across instances. middleBrick’s scans validate these controls by checking for missing rate limiting and inconsistent authentication responses.
For production, combine rate limiting with additional signals such as request origin and rotating key rotation. middleBrick’s dashboard can track your Hapi API’s security score over time, while the CLI allows you to test changes locally with middlebrick scan <url>. The Pro plan adds continuous monitoring and CI/CD integration so that regressions in authentication hardening can be caught before deployment.