Token Leakage with Basic Auth
How Token Leakage Manifests in Basic Auth
Token leakage in Basic Auth occurs when Base64-encoded credentials are inadvertently exposed through logging, error messages, browser storage, or network traffic. Unlike modern token-based authentication where tokens can be rotated and have limited lifespans, Basic Auth credentials are often static and provide full account access when compromised.
The most common leakage vectors include:
- Server logs containing full Authorization headers before authentication validation
- Stack traces that include request headers
- Browser developer tools capturing network requests
- Client-side JavaScript storing credentials in localStorage or sessionStorage
- API responses that echo back Authorization headers
- Proxy servers or CDNs logging full request headers
Consider this vulnerable Node.js Express implementation:
app.post('/api/login', (req, res) => {
const { username, password } = req.body;
const authHeader = req.headers.authorization;
// Vulnerable: logs full Authorization header with Base64 credentials
console.log(`Auth header: ${authHeader}`);
if (!authHeader || !authHeader.startsWith('Basic ')) {
return res.status(401).json({ error: 'Missing Basic Auth' });
}
const base64Credentials = authHeader.split(' ')[1];
const credentials = Buffer.from(base64Credentials, 'base64').toString('ascii');
const [usernameFromHeader, passwordFromHeader] = credentials.split(':');
// Authentication logic continues...
});An attacker with server log access can extract credentials from logs like:
Auth header: Basic dXNlcm5hbWU6cGFzc3dvcmQ=Decoding this Base64 string reveals: username:password
Another common pattern is credential exposure through error responses:
app.get('/api/protected', (req, res) => {
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Basic ')) {
// Vulnerable: doesn't sanitize response
return res.status(401).json({
error: 'Authentication required',
details: { authHeader }
});
}
// Processing continues...
});The response includes the full Authorization header, allowing client-side scripts or network monitoring tools to capture credentials.
Basic Auth-Specific Detection
Detecting token leakage in Basic Auth requires examining multiple layers of the authentication flow. Here's how to systematically identify these vulnerabilities:
1. Log Analysis
Search server logs for patterns containing 'Basic ' followed by Base64 characters. Use regex patterns like:
/(?:Basic )([A-Za-z0-9+/=]{4,})/Scan for occurrences in:
- Application server logs
- Reverse proxy logs
- Load balancer access logs
- Database query logs
- Monitoring and alerting systems
2. HTTP Response Inspection
Examine API responses for Authorization header leakage. Tools like curl can help:
curl -v -X POST http://api.example.com/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"secret"}' 2>&1 | grep -A 10 AuthorizationLook for responses that include:
- Full Authorization headers in JSON responses
- Error messages containing credential information
- Debug information with authentication details
3. Network Traffic Analysis
Capture and analyze network traffic to identify where credentials appear:
tcpdump -A -s 0 'port 80 or port 443' | grep -B 5 -A 5 Basic4. Automated Scanning with middleBrick
middleBrick's Basic Auth-specific checks include:
- Authorization header exposure detection in responses
- Log file analysis for credential leakage patterns
- Client-side credential storage detection
- Cross-site request forgery (CSRF) vulnerability assessment for Basic Auth endpoints
Run a scan using the CLI:
npx middlebrick scan https://api.example.com --auth basic --user admin --password secretOr integrate into CI/CD:
name: API Security Scan
on: [push, pull_request]
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run middleBrick Scan
run: |
npx middlebrick scan https://api.example.com \
--auth basic \
--user ${{ secrets.API_USER }} \
--password ${{ secrets.API_PASSWORD }} \
--threshold B5. Browser Developer Tools Inspection
Open browser DevTools and monitor network requests to Basic Auth endpoints. Look for:
- Authorization headers in request/response panels
- Credentials stored in browser storage
- JavaScript console logs containing authentication data
Basic Auth-Specific Remediation
Remediating token leakage in Basic Auth requires both code fixes and architectural changes. Here are specific solutions for Basic Auth implementations:
1. Secure Header Handling
Never log Authorization headers. Use middleware to sanitize logs:
const authSanitizer = (req, res, next) => {
if (req.headers.authorization) {
// Remove Authorization header from logs
const sanitizedHeaders = { ...req.headers };
delete sanitizedHeaders.authorization;
req.sanitizedHeaders = sanitizedHeaders;
}
next();
};
app.use(authSanitizer);
// In your route handlers:
app.post('/api/login', (req, res) => {
console.log(`Request from ${req.ip} with headers:`,
req.sanitizedHeaders); // Authorization header removed
// Continue processing...
});2. Error Response Sanitization
Never include authentication headers in error responses:
app.get('/api/protected', (req, res) => {
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Basic ')) {
return res.status(401).json({
error: 'Authentication required',
details: { message: 'Basic Auth credentials missing' }
});
}
// Continue processing...
});3. Client-Side Credential Storage
Never store Basic Auth credentials in browser storage. Use HTTP-only cookies instead:
// Server-side: set HTTP-only cookie
app.post('/api/login', (req, res) => {
const { username, password } = req.body;
// Authenticate user...
// Set secure, HTTP-only cookie instead of returning credentials
res.cookie('auth-session', generateSessionId(), {
httpOnly: true,
secure: true,
sameSite: 'strict',
maxAge: 3600000 // 1 hour
});
res.json({ success: true });
});4. Transport Layer Security
Always use HTTPS to prevent credential interception:
// Express middleware to enforce HTTPS
app.use((req, res, next) => {
if (req.secure || process.env.NODE_ENV === 'development') {
return next();
}
if (req.header('x-forwarded-proto') === 'https') {
return next();
}
res.redirect(`https://${req.header('host')}${req.url}`);
});5. Rate Limiting and Account Lockout
Implement rate limiting to prevent credential brute force attacks:
const rateLimit = require('express-rate-limit');
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 5, // limit each IP to 5 requests per windowMs
message: 'Too many authentication attempts',
standardHeaders: true,
legacyHeaders: false,
keyGenerator: (req) => req.ip
});
app.use('/api/login', authLimiter);6. middleBrick Integration for Continuous Monitoring
Set up continuous monitoring to catch new token leakage issues:
// GitHub Action for continuous monitoring
name: middleBrick Security Scan
on:
schedule:
- cron: '0 2 * * *' # Daily at 2 AM
workflow_dispatch:
jobs:
scan:
runs-on: ubuntu-latest
steps:
- name: Run middleBrick Scan
run: |
npx middlebrick scan https://api.example.com \
--auth basic \
--user ${{ secrets.API_USER }} \
--password ${{ secrets.API_PASSWORD }} \
--threshold B \
--output json > security-report.json
- name: Upload Report
uses: actions/upload-artifact@v3
with:
name: middleBrick-Report
path: security-report.json
retention-days: 30