Phishing Api Keys with Basic Auth
How Phishing API Keys Manifests in Basic Auth
Phishing API keys in Basic Auth environments typically exploit credential harvesting through man-in-the-middle attacks and credential replay. The fundamental weakness lies in Basic Auth's simplicity: credentials are Base64-encoded and transmitted in HTTP headers, making them trivially extractable from network traffic, logs, or browser developer tools.
Common phishing patterns in Basic Auth include:
- Credential interception proxies - Attackers position themselves between clients and APIs, capturing Authorization headers containing Base64-encoded credentials
- Fake login prompts - Malicious websites mimic legitimate Basic Auth dialogs, harvesting credentials when users enter them
- Log file harvesting - Applications that log full request headers inadvertently store Base64-encoded credentials in plain text
- Referer header leakage - When API endpoints are embedded in web pages, Referer headers can expose Basic Auth credentials to third-party sites
The Base64 encoding provides no security - it's merely an encoding scheme. 'dXNlcm5hbWU6cGFzc3dvcmQ=' decodes to 'username:password'. Attackers can easily decode captured credentials and use them to authenticate as legitimate users.
Real-world examples show phishing attacks targeting Basic Auth endpoints through cloned documentation sites, fake API explorers, and malicious npm packages that log credentials. The simplicity that makes Basic Auth easy to implement also makes it vulnerable to these social engineering attacks.
Basic Auth-Specific Detection
Detecting phishing vulnerabilities in Basic Auth requires examining both configuration and runtime behavior. Key detection methods include:
- Credential exposure analysis - Scanning for Basic Auth credentials in HTTP logs, application logs, and error messages
- Transport security verification - Ensuring all Basic Auth endpoints require HTTPS to prevent credential interception
- Referer header inspection - Checking if Basic Auth credentials leak through Referer headers to external domains
- Credential rotation capability - Verifying that compromised credentials can be quickly revoked and replaced
middleBrick's Basic Auth-specific scanning includes:
middlebrick scan https://api.example.com --basic-auth username:passwordThe scanner tests for:
- Credential exposure in response headers and body content
- Lack of HTTPS enforcement on Basic Auth endpoints
- Weak credential policies (short passwords, common usernames)
- Missing rate limiting that allows credential brute force
- Credential logging in server access logs
Code-level detection involves reviewing middleware configurations:
// Vulnerable: Credentials logged in plain text
app.use((req, res, next) => {
console.log(`Auth: ${req.headers.authorization}`); // Logs Base64 credentials
next();
});Security-focused detection tools should flag these patterns and recommend immediate remediation.
Basic Auth-Specific Remediation
Remediating phishing vulnerabilities in Basic Auth requires architectural changes and security best practices. The most effective approach is migrating away from Basic Auth entirely, but when Basic Auth must be used, implement these hardening measures:
HTTPS Enforcement - Never transmit Basic Auth credentials over HTTP:
// Express middleware for HTTPS-only Basic Auth
app.use((req, res, next) => {
if (req.secure) {
return next();
}
res.status(403).json({ error: 'HTTPS required for Basic Auth' });
});Credential Rotation and Revocation - Implement short-lived credentials and immediate revocation:
# Flask example with timed credentials
from flask import Flask, request, jsonify
from datetime import datetime, timedelta
from functools import wraps
def basic_auth_required(expiry_minutes=5):
def decorator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
auth = request.headers.get('Authorization')
if not auth or not auth.startswith('Basic '):
return jsonify({'error': 'Basic Auth required'}), 401
# Validate credentials and check expiry
username, password = decode_basic_auth(auth)
if not validate_credentials(username, password):
return jsonify({'error': 'Invalid credentials'}), 401
# Check if credentials are expired
if is_expired(username):
return jsonify({'error': 'Credentials expired'}), 401
return f(*args, **kwargs)
return decorated_function
return decorator
Credential Masking - Prevent credential logging and exposure:
// Go HTTP handler with credential protection
func secureHandler(w http.ResponseWriter, r *http.Request) {
// Immediately reject non-HTTPS requests
if r.TLS == nil {
http.Error(w, "HTTPS required", http.StatusForbidden)
return
}
// Extract credentials without logging
auth := r.Header.Get("Authorization")
if auth == "" || !strings.HasPrefix(auth, "Basic ") {
http.Error(w, "Basic Auth required", http.StatusUnauthorized)
return
}
// Decode credentials in memory only
payload, err := base64.StdEncoding.DecodeString(auth[6:])
if err != nil || strings.Contains(string(payload), "") {
http.Error(w, "Invalid credentials", http.StatusUnauthorized)
return
}
// Process request without logging credentials
// ... business logic ...
}Multi-Factor Enhancement - Add token-based verification to Basic Auth:
// Spring Boot with Basic Auth + OTP
@RestController
public class SecureApiController {
@GetMapping("/api/secure")
public ResponseEntity<String> secureEndpoint(
@RequestHeader("Authorization") String auth,
@RequestParam("otp") String otp) {
// Basic Auth validation
if (!validateBasicAuth(auth)) {
return ResponseEntity.status(401).body("Invalid Basic Auth");
}
// OTP validation (time-based)
if (!validateOTP(otp)) {
return ResponseEntity.status(401).body("Invalid OTP");
}
return ResponseEntity.ok("Access granted");
}
}These remediation strategies significantly reduce phishing risks while maintaining Basic Auth compatibility where required.