HIGH path traversalflaskhmac signatures

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.realpath and confine it with os.path.commonpath against 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 IDNameSeverity
CWE-20Improper Input Validation HIGH
CWE-22Path Traversal HIGH
CWE-74Injection CRITICAL
CWE-77Command Injection CRITICAL
CWE-78OS Command Injection CRITICAL
CWE-79Cross-site Scripting (XSS) HIGH
CWE-89SQL Injection CRITICAL
CWE-90LDAP Injection HIGH
CWE-91XML Injection HIGH
CWE-94Code Injection CRITICAL

Frequently Asked Questions

Can a valid Hmac Signature prevent path traversal if the server properly validates the path?
No. A valid Hmac only ensures the parameters were not altered after signing. Path traversal must be prevented by canonicalizing the path and enforcing strict boundaries; the signature does not replace filesystem safety checks.
What should I include in the Hmac to protect against path manipulation?
Include only immutable identifiers that do not influence filesystem paths, such as a resource ID. Avoid including raw filenames or paths in the Hmac scope, and validate all user-controlled path inputs independently with allowlists and confinement.