HIGH zip slipdjangohmac signatures

Zip Slip in Django with Hmac Signatures

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

Zip Slip is a path traversal vulnerability that occurs when an archive (e.g., ZIP) is extracted without validating or sanitizing file paths inside it. When this pattern intersects with Hmac Signatures in Django, the risk can become more nuanced because the signature is typically used to verify integrity or authenticity of data, such as a payload or a file token. If a Django application accepts an Hmac-signed payload that references a downloadable file or archive, and then extracts that archive based on the signed claim without validating contained file paths, an attacker can craft a signed archive containing malicious paths (e.g., ../../etc/passwd) that overwrite or expose sensitive files upon extraction.

In practice, this can happen in workflows where Django uses Hmac Signatures to authorize a file archive download or import. For example, a signed URL or token may be used to permit an automated import of a ZIP file. If the server-side extraction logic trusts the signed data and does not enforce path canonicalization, an attacker can include crafted paths in the ZIP that traverse outside the intended directory. Because the signature validates the request, the server may incorrectly assume that the content is trusted and proceed to extract it, leading to unauthorized file writes or information disclosure. This is especially relevant when the signature is tied to file metadata or a filename that the server later uses to locate or extract the archive.

Django does not provide built-in ZIP extraction utilities that enforce safe path resolution, so developers often use Python’s zipfile module directly. If the code uses the signature to gate extraction without independently verifying that each entry’s resolved path remains within the target directory, the application remains vulnerable. An attacker who can influence the archive contents — for example, by uploading a malicious ZIP and obtaining a valid Hmac signature for it — can exploit this trust boundary. The signature acts as an authentication wrapper around the operation, but does not inherently prevent path traversal within the archive itself. Therefore, the combination of Zip Slip-prone extraction logic and Hmac-based authorization creates a scenario where malicious archives can be processed under the guise of integrity verification.

Hmac Signatures-Specific Remediation in Django — concrete code fixes

To mitigate Zip Slip when using Hmac Signatures in Django, ensure that path validation is performed independently of signature verification. The signature should only attest to the authenticity of the request or metadata, not to the safety of the extracted content. Always resolve and sanitize file paths before extraction, and enforce that every resolved path remains within the intended base directory.

Below is a concrete, secure example of handling a ZIP file in Django with Hmac verification and safe extraction. This example assumes the Hmac signature is used to validate a payload that includes a filename or archive reference. The code uses Python’s zipfile module with strict path checks.

import hmac
import hashlib
import os
import zipfile
from django.conf import settings
def verify_hmac(data, signature, secret):
    expected = hmac.new(secret.encode(), data.encode(), hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature)
def safe_extract_zip(zip_path, extract_to):
    base = os.path.commonpath([os.path.realpath(extract_to)])
    with zipfile.ZipFile(zip_path, 'r') as zf:
        for member in zf.infolist():
            # Normalize and resolve the member path
            member_path = os.path.normpath(member.filename)
            resolved = os.path.realpath(os.path.join(extract_to, member_path))
            # Ensure the resolved path stays within extract_to
            if not resolved.startswith(base):
                raise ValueError(f"Invalid path outside target directory: {member.filename}")
            zf.extract(member, extract_to)
# Example usage in a Django view
from django.http import JsonResponse
from django.views import View
class ImportArchiveView(View):
    def post(self, request):
        data = request.POST.get('data', '')
        signature = request.POST.get('signature', '')
        secret = settings.HMAC_SECRET_KEY
        if not verify_hmac(data, signature, secret):
            return JsonResponse({'error': 'Invalid signature'}, status=403)
        # Assume file handling logic that stores the uploaded archive at archive_path
        archive_path = '/tmp/uploaded_archive.zip'
        try:
            safe_extract_zip(archive_path, '/safe/extract/dir')
        except ValueError as e:
            return JsonResponse({'error': str(e)}, status=400)
        return JsonResponse({'status': 'ok'})

This pattern separates concerns: the Hmac signature confirms the request’s integrity, while path canonicalization and prefix checks prevent traversal. Avoid using filenames or paths directly from the archive for further operations without the same validation. For additional protection, consider using libraries that provide strict extraction utilities or explicitly reject entries with absolute paths or parent directory components.

Frequently Asked Questions

Can Hmac Signatures alone prevent Zip Slip vulnerabilities in Django?
No. Hmac Signatures verify authenticity or integrity of data, but they do not validate file paths within archives. You must independently enforce path canonicalization and directory constraints to prevent Zip Slip.
What additional measures should be taken when using Hmac Signatures with file uploads in Django?
Always validate and sanitize file paths before extraction, use strict path prefix checks, avoid trusting metadata from the archive, and consider using safe extraction libraries or custom logic that rejects unsafe entries.