HIGH zip slipfastapihmac signatures

Zip Slip in Fastapi with Hmac Signatures

Zip Slip in Fastapi with Hmac Signatures — how this specific combination creates or exposes the vulnerability

Zip Slip is a path traversal vulnerability that occurs when an archive’s entries are extracted without proper validation of file paths. In Fastapi applications that accept uploaded archives and verify integrity with Hmac Signatures, the presence of Hmac does not prevent malicious paths from being processed; it only ensures the payload has not been altered after signing. An attacker can craft an archive containing files with crafted relative paths (e.g., ../../../etc/passwd) and a valid Hmac if the server recomputes the signature over the attacker-controlled bytes before path validation. Because the signature matches, the server may trust the payload and proceed to extraction, leading to unauthorized file overwrites or reads.

When Fastapi endpoints use Hmac Signatures to validate upload authenticity, the risk arises if validation logic confirms the signature and then directly uses the provided filename or extracted entry names without canonicalization. For example, an endpoint may compute the Hmac over the raw archive bytes, compare it to a client-supplied signature header, and then forward the file to extraction routines. If extraction routines do not enforce strict path sanitization—such as resolving paths with os.path.normpath and ensuring they remain within a designated directory—the application remains vulnerable despite the Hmac check. This makes the combination of Zip Slip and Hmac Signatures particularly dangerous: integrity assurance creates a false sense of safety while the trust boundary shifts to path handling rather than payload tampering.

In practice, this manifests when an API accepts an archive and an Hmac signature, verifies the signature, and then extracts contents using unsafe methods like Python’s zipfile.extract without path checks. Attackers can leverage directory traversal sequences to escape the intended extraction directory, potentially overwriting critical configuration files or reading arbitrary files on the host if the server runs with elevated privileges. The vulnerability is not in the Hmac algorithm but in the sequencing and assumptions: verifying integrity does not equate to verifying safety of extracted paths. MiddleBrick’s checks for Input Validation and Property Authorization help surface such logic flaws by testing whether path constraints are enforced after signature validation.

Hmac Signatures-Specific Remediation in Fastapi — concrete code fixes

To remediate Zip Slip in Fastapi when using Hmac Signatures, ensure signature verification is the final step after strict path validation and extraction safeguards. Always normalize and confine extracted paths to a safe directory, and never trust filenames from the archive. Below is a concrete Fastapi snippet that demonstrates secure handling: compute the Hmac over the raw archive bytes, validate it against a trusted source, then extract with explicit path checks using extractall with a filtered member list.

import hashlib
import hmac
import os
import tempfile
from fastapi import Fastapi, UploadFile, File, Form, HTTPException
from zipfile import ZipFile, is_zipfile

app = Fastapi()

# Use a securely stored key, for example from environment variables
SECRET_KEY = os.environ.get("HMAC_SECRET").encode()

def verify_hmac(data: bytes, received_signature: str) -> bool:
    expected_signature = hmac.new(SECRET_KEY, data, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected_signature, received_signature)

def safe_zip_entries(base_path: str, members: list) -> list:
    safe_members = []
    for member in members:
        # Normalize path to remove dot segments
        member_path = os.path.normpath(member)
        if member_path.startswith(".."):
            continue  # reject paths that escape
        full_path = os.path.join(base_path, member_path)
        # Ensure the resolved path remains inside base_path
        if not full_path.startswith(os.path.abspath(base_path)):
            continue
        safe_members.append(member)
    return safe_members

@app.post("/upload")
async def upload_archive(file: UploadFile = File(...), signature: str = Form(...)):
    if not file.filename.endswith(".zip"):
        raise HTTPException(status_code=400, detail="Only ZIP archives are allowed")
    data = await file.read()
    if not verify_hmac(data, signature):
        raise HTTPException(status_code=403, detail="Invalid signature")
    if not is_zipfile(file.filename):
        raise HTTPException(status_code=400, detail="File is not a valid ZIP")
    with tempfile.TemporaryDirectory() as tmpdir:
        with ZipFile(io.BytesIO(data)) as zf:
            safe_members = safe_zip_entries(tmpdir, zf.namelist())
            zf.extractall(tmpdir, members=safe_members)
        # Process extracted files within tmpdir
        # ...
    return {"status": "ok"}

This approach validates the Hmac before any filesystem interaction, then filters archive members to block traversal sequences. By using os.path.normpath and a prefix check, you ensure that no extracted file escapes the temporary directory. MiddleBrick’s scans can help identify whether your endpoints perform such path validation after signature checks, highlighting gaps in Input Validation and Property Authorization.

Additionally, prefer libraries that enforce safe extraction by default, and avoid manual string concatenation when building destination paths. Rotate Hmac keys periodically and scope signatures to specific operations (e.g., upload vs. download) to limit the impact of a potential leak. Remember that Hmac Signatures protect integrity and authenticity, not path safety; secure extraction logic remains your responsibility.

Frequently Asked Questions

Does a valid Hmac prevent Zip Slip if the server extracts archives?
No. Hmac ensures the payload has not been altered, but it does not validate file paths. If the server extracts entries without canonicalizing and confining paths, Zip Slip can still occur despite a correct signature.
How does middleBrick relate to detecting this class of issue?