Open Redirect with Basic Auth
How Open Redirect Manifests in Basic Auth
Open redirect vulnerabilities in Basic Auth contexts exploit the authentication flow's redirect mechanisms. When Basic Auth credentials are rejected, servers typically redirect users to error pages or login forms. Attackers can manipulate these redirects to send authenticated users to malicious sites.
The most common Basic Auth open redirect pattern occurs in the WWW-Authenticate header processing. When a client receives a 401 Unauthorized response with a Basic realm, browsers automatically prompt for credentials. However, if the server includes a redirect URL in the authentication challenge, attackers can specify arbitrary destinations.
// Vulnerable Basic Auth redirect handling
const express = require('express');
const app = express();
app.get('/auth', (req, res) => {
const redirectUrl = req.query.redirect || '/';
// DANGEROUS: Unvalidated redirect parameter
res.setHeader('WWW-Authenticate', `Basic realm="Secure Area", redirect="${redirectUrl}"`);
res.status(401).send('Unauthorized');
});
This creates a vulnerability where attackers can craft URLs like:
https://example.com/auth?redirect=https://evil.com/phish
Another Basic Auth-specific variant appears in proxy authentication scenarios. When a reverse proxy requires Basic Auth, it often includes the original target URL in the authentication challenge. If this URL isn't properly validated, attackers can inject malicious redirects.
// Vulnerable proxy authentication
app.use((req, res, next) => {
if (!req.headers.authorization) {
const originalUrl = req.originalUrl; // DANGEROUS: Direct use of user input
res.setHeader('Proxy-Authenticate', `Basic realm="Proxy", original-url="${originalUrl}"`);
res.status(407).send('Proxy Authentication Required');
return;
}
next();
});
Basic Auth's stateless nature makes these vulnerabilities particularly dangerous. Unlike session-based auth, Basic Auth credentials travel with every request, so once redirected, the malicious site receives authenticated requests automatically.
Basic Auth-Specific Detection
Detecting open redirects in Basic Auth contexts requires examining authentication flow handling. The key is to identify where redirect URLs are processed and whether they're properly validated.
Manual testing involves sending requests with crafted authentication challenges. For example, test if a server accepts redirect parameters in the WWW-Authenticate header:
GET /protected HTTP/1.1
Host: example.com
// Server response with crafted challenge:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="Test", redirect="https://evil.com"
Automated scanning tools like middleBrick specifically check Basic Auth endpoints for open redirect vulnerabilities. The scanner examines authentication responses for redirect parameters and tests whether they accept arbitrary URLs.
middleBrick's Basic Auth open redirect detection includes:
| Check Type | Method | Target |
|---|---|---|
| WWW-Authenticate Header | Parameter extraction | redirect, original-url |
| Authentication Challenge | URL injection testing | realm parameters |
| Proxy Authentication | 407 response analysis | Proxy-Authenticate header |
The scanner tests multiple URL schemes (http, https, ftp, javascript) to identify unrestricted redirects. It also checks for Basic Auth-specific patterns like realm parameters that might contain URLs.
Code review for Basic Auth open redirects should focus on:
- Authentication middleware that constructs WWW-Authenticate headers
- Proxy authentication handlers
- Any code that includes user input in authentication challenges
- Redirect logic after authentication failures
middleBrick's CLI provides direct Basic Auth scanning:
npx middlebrick scan https://api.example.com --auth-type basic
This scans the endpoint for Basic Auth-specific vulnerabilities including open redirects, credential exposure, and authentication bypass.
Basic Auth-Specific Remediation
Fixing open redirects in Basic Auth contexts requires strict URL validation and avoiding dynamic redirect parameters in authentication challenges. The safest approach is to eliminate redirect parameters entirely from authentication flows.
Here's a secure Basic Auth implementation:
const express = require('express');
const url = require('url');
const { URL } = require('url');
const app = express();
// Whitelist of allowed domains for redirects
const ALLOWED_DOMAINS = ['https://example.com', 'https://app.example.com'];
function validateRedirectUrl(redirectUrl) {
try {
const parsedUrl = new URL(redirectUrl);
// Check if domain is in whitelist
if (!ALLOWED_DOMAINS.includes(parsedUrl.origin)) {
return false;
}
// Additional security checks
if (parsedUrl.protocol !== 'https:') {
return false;
}
return true;
} catch (e) {
return false;
}
}
app.get('/auth', (req, res) => {
const redirectUrl = req.query.redirect;
if (redirectUrl && validateRedirectUrl(redirectUrl)) {
// Store validated redirect for post-auth use
req.session.returnTo = redirectUrl;
}
// No redirect parameter in authentication challenge
res.setHeader('WWW-Authenticate', 'Basic realm="Secure Area"');
res.status(401).send('Unauthorized');
});
For proxy authentication scenarios, implement similar validation:
app.use((req, res, next) => {
if (!req.headers.authorization) {
// Remove any URL parameters from authentication
res.setHeader('Proxy-Authenticate', 'Basic realm="Proxy"');
res.status(407).send('Proxy Authentication Required');
return;
}
next();
});
Key remediation principles for Basic Auth open redirects:
- Never include user-controlled URLs in WWW-Authenticate or Proxy-Authenticate headers
- Implement strict URL validation with domain whitelisting
- Use HTTPS-only redirects
- Avoid client-side redirect logic based on authentication parameters
- Log and monitor authentication failures that include suspicious parameters
For applications that must support post-authentication redirects, implement a secure token-based system:
// Generate secure redirect token
function generateRedirectToken(url) {
const token = crypto.randomBytes(32).toString('hex');
const expires = Date.now() + 15 * 60 * 1000; // 15 minutes
// Store token with URL in server-side store
redirectStore.set(token, { url, expires });
return token;
}
// Validate redirect token
function validateRedirectToken(token) {
const data = redirectStore.get(token);
if (!data || data.expires < Date.now()) {
return null;
}
// Remove token after use
redirectStore.delete(token);
return data.url;
}
This approach eliminates direct URL manipulation while maintaining user experience. The token system ensures only pre-validated URLs can be used for redirects, preventing open redirect attacks in Basic Auth contexts.