Bleichenbacher Attack in Fiber with Basic Auth
Bleichenbacher Attack in Fiber with Basic Auth — how this specific combination creates or exposes the vulnerability
A Bleichenbacher attack is a cryptographic padding oracle attack originally described against PKCS#1 v1.5–based RSA encryption. In the context of an HTTP API built with Fiber and protected by HTTP Basic Authentication, the term describes a timing-based oracle that arises when the server’s authentication logic exposes distinct response behaviors based on whether a provided Base64-encoded credentials string has valid padding before a full credential check is performed.
In Fiber, a typical Basic Auth setup might decode the Authorization header and immediately attempt to split the decoded value into username and password. If the decoding or initial validation step triggers a padding error (for example, when a malformed Base64 string or a ciphertext-like token is supplied and the decoder throws an exception), the server can respond with a 400 or a different timing path than when the format is syntactically valid but the credentials are wrong. An attacker who can make many requests and measure timing differences can iteratively adapt ciphertexts to recover the effective secret or session token, emulating the iterative byte-by-byte recovery that makes Bleichenbacher-style attacks practical.
When such an endpoint also relies on a bearer token or cookie that is cryptographically sensitive (e.g., a session identifier encrypted under a server-side key), a misconfigured middleware stack in Fiber can amplify the risk: the authentication check may short-circuit on format errors, and downstream routes may still process requests that have passed the initial parsing. Because the scan categories in middleBrick include Authentication, BOLA/IDOR, and Unsafe Consumption, findings can highlight timing anomalies and unauthenticated endpoint exposure that are consistent with oracle-assisted attacks, even when the scanner does not perform active exploitation.
For example, consider an endpoint that decodes Basic credentials and then passes a token to an LLM-integrated handler. If the handler’s token validation is implemented naively and the server returns 500 errors for malformed padding while returning 401 only for invalid credentials, middleBrick’s Authentication and Unsafe Consumption checks can surface the inconsistent error behavior. This does not imply that middleBrick breaks or fixes the flow; it detects and reports conditions that may aid an attacker in refining an adaptive attack chain.
Concrete Fiber code that can exhibit this behavior is shown below. Note that the first handler decodes the header and, on a decoding error, writes a 400 response. The second handler assumes valid syntax implies correct authorization and proceeds, creating a path where timing and status code distinctions can be observed by an external scanner:
const Fiber = require('fiber');
const auth = require('basic-auth');
const app = new Fiber();
app.all('/api/protected', (req, res) => {
const c = auth(req);
if (!c) {
res.status(401).send('Auth required');
return;
}
// Simulate token validation that may involve cryptographic checks
if (c.name !== 'admin' || c.pass !== 's3cr3t') {
res.status(403).send('Forbidden');
return;
}
res.status(200).send('OK');
});
// A second route with different error handling can create timing differences
app.all('/api/token', (req, res) => {
const header = req.get('Authorization');
if (!header || !header.startsWith('Basic ')) {
res.status(400).send('Bad request');
return;
}
try {
const token = Buffer.from(header.slice(6), 'base64').toString('utf8');
// If token parsing fails with malformed input, timing may differ
const [user, pass] = token.split(':');
if (user !== 'admin' || pass !== 's3cr3t') {
res.status(403).send('Forbidden');
return;
}
res.status(200).send('OK');
} catch (e) {
res.status(400).send('Invalid format');
}
});
app.listen(3000);
In this example, an attacker supplying invalid Base64 input to /api/token may observe a 400 response with one timing profile, while valid Base64 but wrong credentials yields a 403 with a slightly different processing path. Repeated measurements and adaptive chosen-ciphertext techniques could, in theory, be used to refine guesses, especially if downstream components introduce additional branching. middleBrick’s parallel checks for Authentication and Unsafe Consumption are designed to surface such inconsistencies so they can be reviewed and hardened.
Basic Auth-Specific Remediation in Fiber — concrete code fixes
Remediation focuses on making authentication paths consistent in timing and response behavior, regardless of whether the supplied credentials are malformed, missing, or incorrect. In Fiber, avoid branching on the format of the Authorization header before validating credentials, and ensure that all failure paths return the same status code and similar processing overhead.
One effective approach is to centralize credential parsing and validation, returning a generic failure response for any invalid input. Use a constant-time comparison for credentials when feasible, and avoid throwing exceptions on Base64 decoding errors that could alter timing. Below is a hardened implementation that demonstrates these principles:
const Fiber = require('fiber');
const auth = require('basic-auth');
const app = new Fiber();
function safeBasicAuth(req) {
const c = auth(req);
// Return a normalized invalid result for any parsing or missing credentials
if (!c) {
return { user: null, pass: null };
}
return c;
}
app.all('/api/protected', (req, res) => {
const creds = safeBasicAuth(req);
// Constant-time style check: always perform the same number of operations
const userOk = (creds.user === 'admin');
const passOk = (creds.pass === 's3cr3t');
if (!userOk || !passOk) {
// Always respond with 401 for any invalid credentials or malformed header
res.status(401).send('Unauthorized');
return;
}
res.status(200).send('OK');
});
// Example using token parsing without exposing format errors
app.all('/api/token', (req, res) => {
const header = req.get('Authorization');
let user = null;
let pass = null;
if (header && header.startsWith('Basic ')) {
try {
const token = Buffer.from(header.slice(6), 'base64').toString('utf8');
const parts = token.split(':');
if (parts.length === 2) {
[user, pass] = parts;
}
} catch (e) {
// swallow errors to keep flow consistent
}
}
const userOk = (user === 'admin');
const passOk = (pass === 's3cr3t');
if (!userOk || !passOk) {
res.status(401).send('Unauthorized');
return;
}
res.status(200).send('OK');
});
app.listen(3000);
These patterns reduce the risk of timing discrepancies by ensuring that malformed inputs do not trigger early, distinguishable responses. For deployments that integrate with middleware or API gateways, pairing this approach with rate limiting and monitoring can further mitigate automated probing. middleBrick’s CLI tool allows you to scan from terminal with middlebrick scan <url> to verify that your authentication endpoints no longer expose status-differentiating behavior, while the GitHub Action can add API security checks to your CI/CD pipeline to fail builds if risk scores degrade.
For teams managing many services, the Pro plan supports continuous monitoring and can integrate Slack or Teams alerts, providing ongoing visibility into authentication-related findings. The MCP Server enables scanning APIs directly from your AI coding assistant, helping to catch regressions before they reach production.