Path Traversal with Basic Auth
How Path Traversal Manifests in Basic Auth
Path traversal vulnerabilities in Basic Auth contexts occur when authentication mechanisms fail to properly sanitize file paths, allowing attackers to escape intended directories. In Basic Auth implementations, this often manifests through several attack vectors.
The most common pattern involves URL manipulation where attackers append ../ sequences to authenticated endpoints. For example, a Basic Auth-protected endpoint at /api/v1/files/download might be manipulated to /api/v1/files/download/../../../../etc/passwd. Since Basic Auth headers are processed before path validation in many frameworks, the authentication check passes before the path traversal is detected.
Another variant exploits case-insensitive file systems. An attacker might request /api/v1/files/download/Windows/System32/cmd.exe on a Linux server, or /api/v1/files/download/etc/passwd with mixed case variations. Basic Auth implementations that don't normalize paths before validation can be tricked into serving files outside the intended directory.
Directory traversal can also occur through URL encoding attacks. Basic Auth credentials are base64-encoded but URL encoding of the path portion can bypass simple sanitization. An attacker might use %2e%2e%2f (URL-encoded ../) or ..%2f to evade path traversal filters. Since the Basic Auth header is processed separately from the URL path, these attacks can succeed if the server doesn't properly decode and normalize paths before file access.
Basic Auth-specific implementations are particularly vulnerable when using Node.js's fs module without path normalization. Consider this vulnerable pattern:
const http = require('http');
const fs = require('fs');
const auth = require('basic-auth');
const server = http.createServer((req, res) => {
const credentials = auth(req);
if (!credentials || credentials.name !== 'admin' || credentials.pass !== 'secret') {
res.statusCode = 401;
res.setHeader('WWW-Authenticate', 'Basic realm="files"');
res.end('Unauthorized');
return;
}
// Vulnerable: no path normalization
const filePath = `/var/files/${req.url.split('/').pop()}`;
fs.readFile(filePath, (err, data) => {
if (err) {
res.statusCode = 404;
res.end('File not found');
} else {
res.end(data);
}
});
});
This code authenticates correctly but fails to validate the requested path. An attacker can access /api/v1/files/download/../../../etc/passwd and bypass the intended file directory.
Another Basic Auth-specific scenario involves default directory indexes. When Basic Auth protects a directory listing endpoint, attackers can use path traversal to navigate to parent directories and discover file structures. For instance, requesting /api/v1/files/../../../../ might reveal directory contents that should remain hidden, even though the Basic Auth credentials are valid.
Windows-specific path traversal attacks also affect Basic Auth implementations. Using ..
sequences or \ backslashes can sometimes bypass filters that only check for forward slashes. Basic Auth middleware that doesn't normalize path separators creates opportunities for these attacks.
Time-of-check to time-of-use (TOCTOU) race conditions can occur in Basic Auth contexts when file validation and access are separated. An attacker might authenticate, then quickly manipulate the path between the validation and access phases, exploiting Basic Auth's stateless nature where credentials are re-validated for each request.
Basic Auth-Specific Detection
Detecting path traversal in Basic Auth implementations requires examining both the authentication layer and file access patterns. Several approaches can identify these vulnerabilities.
Static code analysis tools can scan for dangerous patterns in Basic Auth implementations. Look for code that:
- Uses
fsor similar file system modules without path normalization - Concatenates user input directly into file paths after Basic Auth validation
- Doesn't use
path.normalize(),path.join(), orpath.resolve()when constructing file paths - Relies solely on Basic Auth for security without additional path validation
Dynamic testing with tools like middleBrick can automatically detect path traversal vulnerabilities in Basic Auth-protected APIs. The scanner tests for common traversal patterns including:
| Test Pattern | Attack Vector | Expected Detection |
|---|---|---|
../ sequences | Standard traversal | Unauthorized access to parent directories |
URL-encoded %2e%2e%2f | Encoding bypass | Access when encoding should be blocked |
| Mixed case variations | Case sensitivity | Access on case-insensitive systems |
Windows-specific \ sequences | Platform-specific | Access when backslashes are accepted |
middleBrick's black-box scanning approach tests the unauthenticated attack surface by submitting these traversal patterns to Basic Auth-protected endpoints and analyzing responses. The scanner checks if authentication is bypassed or if files outside the intended directory are accessible.
Manual testing should include attempting to access known sensitive files through Basic Auth endpoints. Common targets include:
/api/v1/files/download/../../../../etc/passwd
/api/v1/files/download/../../../../windows/win.ini
/api/v1/files/download/../../../../boot.ini
/api/v1/files/download/..%2F..%2F..%2F..%2Fetc%2fpasswd
/api/v1/files/download/..\..\..\..\..\etc\passwd
Monitor the server's response time and error messages. Path traversal often results in different response times or error messages compared to valid requests, which can be detected through timing analysis or error pattern matching.
Log analysis can reveal path traversal attempts. Search for patterns like:
- Multiple consecutive
../sequences in URLs - Access attempts to system directories (
/etc/,/proc/,/boot/) - Unusual file extensions or system file requests
- Encoded path sequences in request logs
Network-level detection can identify path traversal through intrusion detection systems that monitor for suspicious path patterns in HTTP requests, even when Basic Auth headers are present.
Basic Auth-Specific Remediation
Remediating path traversal in Basic Auth implementations requires a defense-in-depth approach that combines authentication, authorization, and input validation. Here are specific code-level fixes for Basic Auth scenarios.
The most critical remediation is path normalization before file access. Always resolve and validate paths against a known base directory:
const http = require('http');
const fs = require('fs');
const auth = require('basic-auth');
const path = require('path');
const BASE_DIR = '/var/files';
const server = http.createServer((req, res) => {
const credentials = auth(req);
if (!credentials || credentials.name !== 'admin' || credentials.pass !== 'secret') {
res.statusCode = 401;
res.setHeader('WWW-Authenticate', 'Basic realm="files"');
res.end('Unauthorized');
return;
}
// Get the requested filename from URL
const urlParts = req.url.split('/');
const filename = urlParts.pop() || urlParts.pop(); // handle trailing slash
// Critical: normalize and validate the path
const filePath = path.normalize(path.join(BASE_DIR, filename));
// Verify the resolved path is within the base directory
if (!filePath.startsWith(BASE_DIR + path.sep)) {
res.statusCode = 403;
res.end('Forbidden');
return;
}
// Check if file exists and is accessible
fs.stat(filePath, (err, stats) => {
if (err || !stats.isFile()) {
res.statusCode = 404;
res.end('File not found');
return;
}
// Serve the file
fs.createReadStream(filePath).pipe(res);
});
});
This implementation ensures that even if an attacker provides a path with ../ sequences, the normalized path will either stay within the base directory or be rejected.
For Express.js applications with Basic Auth middleware, use a similar approach:
const express = require('express');
const basicAuth = require('express-basic-auth');
const path = require('path');
const app = express();
// Basic Auth middleware
app.use(basicAuth({
users: { admin: 'secret' },
challenge: true,
realm: 'files'
}));
// Secure file download endpoint
app.get('/api/v1/files/download/:filename', (req, res) => {
const filename = path.basename(req.params.filename); // strip any directory components
const filePath = path.join(__dirname, 'files', filename);
// Validate the file exists and is within the files directory
if (!filePath.startsWith(path.join(__dirname, 'files'))) {
return res.status(403).send('Forbidden');
}
fs.stat(filePath, (err, stats) => {
if (err || !stats.isFile()) {
return res.status(404).send('File not found');
}
res.download(filePath);
});
});
Additional security measures include:
- Whitelist allowed file extensions to prevent executable file access
- Set file permissions to restrict access to sensitive files
- Use a chroot jail or container to limit file system access
- Implement rate limiting to prevent brute-force path traversal attempts
For Python Flask applications with Basic Auth:
from flask import Flask, request, send_from_directory
from functools import wraps
import os
def check_auth(username, password):
return username == 'admin' and password == 'secret'
def authenticate():
return 'Unauthorized', 401, {'WWW-Authenticate': 'Basic realm="files"'}
def requires_auth(f):
@wraps(f)
def decorated(*args, **kwargs):
auth = request.authorization
if not auth or not check_auth(auth.username, auth.password):
return authenticate()
return f(*args, **kwargs)
return decorated
app = Flask(__name__)
FILES_DIR = '/var/files'
@app.route('/api/v1/files/download/<path:filename>')
@requires_auth
def download_file(filename):
# Normalize and validate path
base_path = os.path.abspath(FILES_DIR)
requested_path = os.path.abspath(os.path.join(FILES_DIR, filename))
if not requested_path.startswith(base_path):
return 'Forbidden', 403
if not os.path.isfile(requested_path):
return 'File not found', 404
return send_from_directory(FILES_DIR, filename, as_attachment=True)
Remember that Basic Auth alone provides only authentication, not authorization or input validation. Always combine it with proper path validation, least privilege file system access, and regular security testing to prevent path traversal vulnerabilities.
Related CWEs: inputValidation
| CWE ID | Name | Severity |
|---|---|---|
| CWE-20 | Improper Input Validation | HIGH |
| CWE-22 | Path Traversal | HIGH |
| CWE-74 | Injection | CRITICAL |
| CWE-77 | Command Injection | CRITICAL |
| CWE-78 | OS Command Injection | CRITICAL |
| CWE-79 | Cross-site Scripting (XSS) | HIGH |
| CWE-89 | SQL Injection | CRITICAL |
| CWE-90 | LDAP Injection | HIGH |
| CWE-91 | XML Injection | HIGH |
| CWE-94 | Code Injection | CRITICAL |