Auth Bypass in Restify with Mutual Tls
Auth Bypass in Restify with Mutual Tls — how this specific combination creates or exposes the vulnerability
Mutual Transport Layer Security (mTLS) requires both the client and the server to present valid certificates during the TLS handshake. In Restify, developers often configure mTLS to enforce client certificate verification, assuming this alone is sufficient for strong authentication. However, if the application does not additionally validate the client certificate against an authorization context (e.g., mapping the certificate to a user or role), an authentication bypass can occur.
Consider a Restify service that enables mTLS via requestCert and rejectUnauthorized but does not inspect the certificate details before granting access to protected routes. An attacker who can supply any valid, trusted client certificate (for example, a low-privilege certificate issued for testing) will be accepted by the server as authenticated. Because Restify’s route handlers rely only on the presence of a successful TLS handshake, the attacker can access resources intended for other users or roles, effectively bypassing application-level authorization.
This scenario is an Auth Bypass / IDOR pattern: the server conflates transport-layer identity (certificate presented) with application-layer identity (user/role permissions). The mTLS configuration ensures the connection is encrypted and the client possesses a valid certificate, but it does not enforce authorization checks. If the server skips or weakly implements authorization logic (for example, failing to verify certificate serial numbers, subject alternative names, or mapped roles), the unauthenticated attack surface includes any client with access to a trusted certificate.
In a black-box scan, middleBrick tests this combination by probing endpoints that require mTLS while supplying valid but low-privilege certificates. It checks whether access is granted based solely on the TLS handshake and whether authorization checks (such as scope or role validation) are missing. Findings typically highlight missing authorization on mTLS-protected routes, referencing common misconfigurations aligned with OWASP API Top 10 and relevant compliance mappings.
Mutual Tls-Specific Remediation in Restify — concrete code fixes
To securely implement mTLS in Restify, you must combine transport-layer verification with explicit application-level authorization. The following example demonstrates a hardened configuration and route-level checks.
const fs = require('fs');
const restify = require('restify');
const server = restify.createServer({
key: fs.readFileSync('server-key.pem'),
cert: fs.readFileSync('server-cert.pem'),
ca: fs.readFileSync('ca-cert.pem'),
requestCert: true,
rejectUnauthorized: true
});
// Map certificate fields to application identities/roles
const certificateToRole = (cert) => {
const subject = cert.subject;
const altNames = cert.subjectaltname ? cert.subjectaltname.split(', ').filter(Boolean) : [];
// Example: map by SAN or CN
if (altNames.includes('[email protected]') || subject.CN === 'admin') {
return 'admin';
}
if (altNames.includes('[email protected]') || subject.CN === 'user') {
return 'user';
}
return 'guest';
};
server.pre((req, res, next) => {
if (req.client.authorized) {
const cert = req.client.authorized ? req.connection.getPeerCertificate() : null;
if (!cert || !cert.subject) {
return res.send(401, { error: 'Invalid client certificate' });
}
req.identity = {
role: certificateToRole(cert),
subject: cert.subject,
serialNumber: cert.serialNumber,
san: cert.subjectaltname
};
} else {
return res.send(401, { error: 'Certificate verification failed' });
}
return next();
});
server.get('/admin', (req, res, next) => {
if (req.identity.role !== 'admin') {
return res.send(403, { error: 'Insufficient scope/role' });
}
res.send(200, { data: 'Admin resource' });
return next();
});
server.get('/user', (req, res, next) => {
if (!['admin', 'user'].includes(req.identity.role)) {
return res.send(403, { error: 'Insufficient scope/role' });
}
res.send(200, { data: 'User resource' });
return next();
});
server.listen(8080, () => {
console.log('Secure mTLS server listening on port 8080');
});
Key points in this remediation:
requestCert: trueandrejectUnauthorized: trueenforce that clients must present a certificate signed by a trusted CA.- The
prehook extracts certificate details and maps them to application roles, ensuring that the identity derived from TLS is explicitly attached to the request object. - Each route validates
req.identity.role(or scopes) before allowing access, implementing proper authorization checks that are independent of the TLS layer. - The server rejects requests with missing or invalid client certificates with a clear 401 response, avoiding silent acceptance of unverified connections.
By combining strict mTLS configuration with explicit role-based checks, you eliminate the gap where a valid certificate alone could bypass authorization. This approach ensures that even when a client certificate is trusted, access is still governed by application-level policies, reducing the risk of Auth Bypass and IDOR in Restify APIs.
Related CWEs: authentication
| CWE ID | Name | Severity |
|---|---|---|
| CWE-287 | Improper Authentication | CRITICAL |
| CWE-306 | Missing Authentication for Critical Function | CRITICAL |
| CWE-307 | Brute Force | HIGH |
| CWE-308 | Single-Factor Authentication | MEDIUM |
| CWE-309 | Use of Password System for Primary Authentication | MEDIUM |
| CWE-347 | Improper Verification of Cryptographic Signature | HIGH |
| CWE-384 | Session Fixation | HIGH |
| CWE-521 | Weak Password Requirements | MEDIUM |
| CWE-613 | Insufficient Session Expiration | MEDIUM |
| CWE-640 | Weak Password Recovery | HIGH |