Path Traversal in Flask with Hmac Signatures
Path Traversal in Flask with Hmac Signatures — how this specific combination creates or exposes the vulnerability
Path Traversal occurs when user-controlled input is used to build file system paths without proper validation, allowing an attacker to access files outside the intended directory. In Flask, this often manifests through endpoints that accept a filename or path parameter and directly concatenate it into file operations. When Hmac Signatures are used to authenticate or bind a request to a resource, developers may assume the signature protects the integrity of the parameters. However, if the server does not validate the resolved path after verifying the Hmac, an attacker can supply a malicious payload such as ../../../etc/passwd while the Hmac covers the attacker-supplied string. The signature verifies that the parameter was not altered in transit, but it does not guarantee the parameter is safe. The server must still canonicalize and constrain the path to an allowed directory. Without this, the combination of Hmac Signatures and unchecked file paths creates a false sense of security and can lead to unauthorized file reads.
Consider a Flask endpoint that serves reports identified by a filename and uses an Hmac to prevent tampering. If the code verifies the Hmac and then opens the file using the provided name, an attacker can supply ../../../secrets/database.yml as the filename. The Hmac will validate successfully if the attacker knows or can guess the signing key, or if the key is leaked. Even without key compromise, if the endpoint reflects file contents or errors, the traversal may expose sensitive files. This pattern is common in APIs that expose document storage or configuration via signed tokens. The risk is especially acute when the Hmac is computed over a subset of parameters and the server trusts the remaining parameters after signature validation. In secure designs, Hmac Signatures should be paired with strict allowlists, path normalization, and confinement to a designated base directory to prevent traversal regardless of signature validity.
Another subtle exposure arises when Hmac Signatures are used in logging or error handling. If the server logs the signed parameter before path resolution and an attacker can influence logs through traversal, sensitive context may be exposed. Additionally, if the signature covers a URL path that includes directory segments, an attacker might leverage encoded characters or double encoding to bypass naive checks. The interaction between cryptographic integrity checks and filesystem operations requires careful boundary definition: the signature ensures the request has not been modified, but the application must still enforce file system safety independently. Tools like middleBrick can detect such design gaps by scanning the unauthenticated attack surface, identifying endpoints that accept file-like parameters and assessing whether traversal protections are present alongside integrity checks.
Hmac Signatures-Specific Remediation in Flask — concrete code fixes
To remediate Path Traversal when using Hmac Signatures in Flask, enforce path confinement and canonicalization before any file operation, regardless of signature validity. Use os.path.realpath and os.path.commonpath to ensure the resolved path remains within the intended directory. Treat the Hmac as a tamper-proof wrapper around the parameters, not as a substitute for input validation.
Example of a vulnerable pattern to avoid:
import hmac
import hashlib
from flask import Flask, request
app = Flask(__name__)
SECRET = b'super-secret-key'
@app.route('/files')
def get_file():
filename = request.args.get('file')
received_hmac = request.args.get('hmac')
computed_hmac = hmac.new(SECRET, filename.encode(), hashlib.sha256).hexdigest()
if not hmac.compare_digest(computed_hmac, received_hmac):
return 'Invalid signature', 403
# Unsafe: path traversal possible after signature verification
with open(f'/safe/files/{filename}', 'rb') as f:
return f.read()
Corrected implementation that binds the signature to a safe path resolution:
import hmac import hashlib import os from flask import Flask, request, abort app = Flask(__name__) SECRET = b'super-secret-key' BASE_DIR = os.path.abspath('/safe/files') def verify_hmac(filename: str, received_hmac: str) -> bool: computed_hmac = hmac.new(SECRET, filename.encode(), hashlib.sha256).hexdigest() return hmac.compare_digest(computed_hmac, received_hmac) def safe_path(filename: str) -> str: # Normalize and resolve relative segments candidate = os.path.normpath(filename) full = os.path.realpath(os.path.join(BASE_DIR, candidate)) # Ensure the resolved path is inside BASE_DIR if os.path.commonpath([full, BASE_DIR]) != BASE_DIR: return None return full @app.route('/files') def get_file(): filename = request.args.get('file', '') received_hmac = request.args.get('hmac', '') if not verify_hmac(filename, received_hmac): abort(403, 'Invalid signature') path = safe_path(filename) if path is None: abort(400, 'Invalid path') try: with open(path, 'rb') as f: return f.read() except FileNotFoundError: abort(404, 'File not found')Key points in the remediation:
- Compute the Hmac over the raw user input before any transformation, so tampering is detectable.
- Normalize and resolve the path using
os.path.realpathand confine it withos.path.commonpathagainst the base directory. - Reject the request if the resolved path escapes the base directory, even if the Hmac is valid.
- Return generic errors to avoid leaking filesystem details through timing or error messages.
For more complex use cases involving multiple parameters, include only the immutable parts in the Hmac computation (e.g., a resource ID), and validate mutable inputs like filenames separately with allowlists. The middleBrick CLI can be used to verify that endpoints using Hmac Signatures do not exhibit path traversal by running middlebrick scan <url> and reviewing the findings for file handling patterns.
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 |