Dns Rebinding with Basic Auth
How Dns Rebinding Manifests in Basic Auth
Dns Rebinding attacks exploit the trust relationship between a client and server when Basic Auth credentials are cached or reused across different origins. In Basic Auth, credentials are sent with every request to the matching origin, and browsers cache these credentials based on the host and port. An attacker can leverage this by registering a domain they control, setting a short TTL on its DNS record, and running a malicious server on a private IP address.
The attack sequence begins when a victim visits a malicious website that includes a script attempting to access a URL using the target's Basic Auth credentials. The browser resolves the attacker's domain to the attacker's public IP, receives a 401 Unauthorized response with a Basic Auth challenge, and prompts the user. The user enters their credentials, which the browser caches for that origin.
The attacker then changes the DNS record to point to a private IP address (like 192.168.1.1) before the browser's DNS cache expires. When the victim's browser automatically retries the request (due to the cached credentials), it now sends the Basic Auth header to the private IP address. This allows the attacker to capture credentials or access internal APIs that trust the Basic Auth authentication.
Consider this vulnerable pattern in a Node.js application:
app.get('/api/internal', (req, res) => {
const authHeader = req.headers.authorization;
if (!authHeader) {
return res.status(401).set('WWW-Authenticate', 'Basic').send('Unauthorized');
}
const [username, password] = Buffer.from(authHeader.split(' ')[1], 'base64').toString().split(':');
if (username === 'admin' && password === 'secret') {
return res.json({ data: 'Internal resource' });
}
res.status(401).send('Unauthorized');
});The vulnerability lies in the server's blind trust of any Basic Auth credentials without validating the request's origin or implementing additional protections. The browser's credential caching mechanism becomes the attack vector.
Basic Auth-Specific Detection
Detecting Dns Rebinding vulnerabilities in Basic Auth requires both static analysis and runtime testing. For static analysis, examine your authentication middleware for patterns that blindly trust Basic Auth credentials without additional context validation.
Look for these red flags in your code:
// Vulnerable pattern - no origin validation
app.use((req, res, next) => {
const authHeader = req.headers.authorization;
if (!authHeader) return next();
const credentials = Buffer.from(authHeader.split(' ')[1], 'base64').toString();
const [username, password] = credentials.split(':');
// No validation of request origin or additional factors
if (validateBasicAuth(username, password)) {
req.user = { username };
return next();
}
res.status(401).send('Unauthorized');
});Dynamic detection with middleBrick specifically tests Basic Auth endpoints by attempting to access them from controlled DNS environments. The scanner sets up test scenarios where DNS records are rapidly changed between public and private IP addresses while monitoring for credential leakage.
middleBrick's Basic Auth-specific checks include:
- Detection of endpoints that accept Basic Auth without additional origin validation
- Testing for credential reuse across different network contexts
- Identification of endpoints that expose sensitive data when accessed with valid Basic Auth credentials
- Analysis of authentication flow for timing-based DNS rebinding vulnerabilities
The scanner also examines OpenAPI specifications for Basic Auth definitions and cross-references them with runtime findings to identify inconsistencies between documented and actual behavior.
Basic Auth-Specific Remediation
Remediating Dns Rebinding in Basic Auth requires architectural changes that go beyond simple credential validation. The most effective approach is to implement origin binding for Basic Auth sessions.
Here's a robust Node.js implementation using session-based origin binding:
const sessions = new Map();
function validateBasicAuthWithOrigin(req, res, next) {
const authHeader = req.headers.authorization;
if (!authHeader) {
return res.status(401).set('WWW-Authenticate', 'Basic realm="Secure Area"').send('Authorization required');
}
const credentials = Buffer.from(authHeader.split(' ')[1], 'base64').toString();
const [username, password] = credentials.split(':');
if (!validateCredentials(username, password)) {
return res.status(401).send('Invalid credentials');
}
// Create or validate session with origin binding
const origin = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
const sessionId = req.cookies.sessionId;
if (sessionId) {
const session = sessions.get(sessionId);
if (session && session.username === username && session.origin === origin) {
session.lastActivity = Date.now();
req.user = { username };
return next();
}
}
// New session
const newSessionId = crypto.randomBytes(16).toString('hex');
sessions.set(newSessionId, {
username,
origin,
lastActivity: Date.now(),
createdAt: Date.now()
});
res.cookie('sessionId', newSessionId, { httpOnly: true, secure: true });
req.user = { username };
next();
}
function validateCredentials(username, password) {
// Implement your validation logic
return username === 'admin' && password === 'strong-password-123';
}Additional protections include implementing IP-based rate limiting specifically for Basic Auth endpoints, using HTTP Strict Transport Security (HSTS) to prevent protocol downgrade attacks, and adding CSRF tokens to state-changing operations even with Basic Auth.
For microservices architectures, consider implementing service mesh authentication that provides per-request validation rather than relying on cached Basic Auth credentials across service boundaries.