HIGH zip slipbuffalo

Zip Slip in Buffalo

How Zip Slip Manifests in Buffalo

Zip Slip in Buffalo applications typically occurs when handling file uploads or processing archive files through the archive/zip package. The vulnerability emerges when an attacker crafts a ZIP file containing files with path traversal sequences like ../../ or absolute paths that allow writing files outside the intended directory.

In Buffalo applications, this often appears in file upload handlers where developers extract ZIP archives using Go's standard library without proper validation. Consider a typical Buffalo handler:

func UploadFile(c buffalo.Context) error {
    file, err := c.File("upload")
    if err != nil {
        return err
    }
    defer file.Close()

    zipReader, err := zip.OpenReader(file.FileName())
    if err != nil {
        return err
    }
    defer zipReader.Close()

    for _, f := range zipReader.File {
        rc, err := f.Open()
        if err != nil {
            return err
        }
        defer rc.Close()

        // Vulnerable: no path validation
        destPath := filepath.Join("uploads", f.Name)
        
        os.MkdirAll(filepath.Dir(destPath), 0755)
        
        outFile, err := os.Create(destPath)
        if err != nil {
            return err
        }
        defer outFile.Close()

        io.Copy(outFile, rc)
    }

    return c.Render(200, r.JSON(map[string]string{"status": "success"}))
}

The critical vulnerability here is that f.Name from the ZIP archive is used directly without validation. An attacker can craft a ZIP containing ../../etc/passwd or /etc/passwd, which would write files to arbitrary locations on the server's filesystem.

Buffalo's middleware stack doesn't inherently protect against this, as it's a file handling issue rather than an HTTP-level concern. The vulnerability becomes particularly dangerous when combined with Buffalo's default file storage patterns, where uploaded files might be processed and extracted in locations with broader filesystem permissions.

Buffalo-Specific Detection

Detecting Zip Slip vulnerabilities in Buffalo applications requires examining both the codebase and runtime behavior. Here are Buffalo-specific approaches:

Code Analysis: Search for patterns where zip.OpenReader is used with filepath.Join or similar path construction without validation. Look for these specific patterns in your Buffalo handlers:

# Find vulnerable ZIP handling patterns
grep -r "zip\.OpenReader" . --include="*.go"
grep -r "filepath\.Join" . --include="*.go" | grep -v "Clean" | grep -v "Base"

Static Analysis with middleBrick: The middleBrick CLI can scan your Buffalo application's API endpoints for file upload handlers that might be vulnerable to Zip Slip. Run:

middlebrick scan http://localhost:3000 --endpoint /upload

The scanner examines the runtime behavior of your file upload endpoints, testing with crafted ZIP files containing path traversal sequences to verify if files are written outside the intended directory.

middleBrick Dashboard: For continuous monitoring, the middleBrick Dashboard tracks your API security scores over time. If you have a file upload endpoint that processes ZIP files, middleBrick will flag potential Zip Slip vulnerabilities and provide severity ratings with remediation guidance.

GitHub Action Integration: Add Zip Slip scanning to your CI/CD pipeline with the middleBrick GitHub Action. This ensures every pull request is tested for file upload vulnerabilities before deployment:

- name: Run middleBrick Security Scan
  uses: middlebrick/middlebrick-action@v1
  with:
    target-url: "http://localhost:3000"
    scan-profile: "file-upload"
  env:
    MIDDLEBRICK_API_KEY: ${{ secrets.MIDDLEBRICK_API_KEY }}

Runtime Testing: Create test ZIP files with known malicious paths and attempt to upload them to your Buffalo application. Monitor where files are actually written using temporary directories and verbose logging during development.

Buffalo-Specific Remediation

Securing Buffalo applications against Zip Slip requires proper path validation before extracting files. Here's a Buffalo-specific secure implementation:

import (
    "archive/zip"
    "path/filepath"
    "github.com/gobuffalo/buffalo"
    "github.com/gobuffalo/buffalo/render"
)

func SecureUploadHandler(c buffalo.Context) error {
    file, err := c.File("upload")
    if err != nil {
        return c.Error(400, err)
    }
    defer file.Close()

    zipReader, err := zip.OpenReader(file.FileName())
    if err != nil {
        return c.Error(400, err)
    }
    defer zipReader.Close()

    // Define a secure base directory
    baseDir := filepath.Join("uploads", c.Session().ID())
    
    for _, f := range zipReader.File {
        // Validate the file path - critical security check
        safePath := filepath.Clean(f.Name)
        if safePath == "." || safePath == ".." || safePath == "/" {
            return c.Error(400, errors.New("invalid file path"))
        }
        
        // Ensure the path is within the base directory
        if !strings.HasPrefix(safePath, ".") && !strings.HasPrefix(safePath, "/") {
            safePath = filepath.Join(".", safePath)
        }
        
        fullPath := filepath.Join(baseDir, safePath)
        if !strings.HasPrefix(fullPath, filepath.Clean(baseDir)) {
            return c.Error(400, errors.New("path traversal detected"))
        }

        // Create directories and write file
        os.MkdirAll(filepath.Dir(fullPath), 0755)
        
        rc, err := f.Open()
        if err != nil {
            return c.Error(500, err)
        }
        defer rc.Close()

        outFile, err := os.Create(fullPath)
        if err != nil {
            return c.Error(500, err)
        }
        defer outFile.Close()

        if _, err := io.Copy(outFile, rc); err != nil {
            return c.Error(500, err)
        }
    }

    return c.Render(200, r.JSON(map[string]string{"status": "success"}))
}

Buffalo Middleware Approach: For applications with multiple file upload endpoints, create a middleware that validates paths:

type ZipSlipValidator struct{}

func (z *ZipSlipValidator) Before(next buffalo.Handler) buffalo.Handler {
    return func(c buffalo.Context) error {
        if c.Request().Method == http.MethodPost {
            if file, err := c.File("upload"); err == nil {
                if strings.HasSuffix(file.FileName(), ".zip") {
                    // Validate ZIP content before processing
                    if err := validateZipContents(file); err != nil {
                        return c.Error(400, err)
                    }
                }
            }
        }
        return next(c)
    }
}

func validateZipContents(file *multipart.FileHeader) error {
    f, err := file.Open()
    if err != nil {
        return err
    }
    defer f.Close()

    zipReader, err := zip.OpenReader(file.FileName())
    if err != nil {
        return err
    }
    defer zipReader.Close()

    for _, f := range zipReader.File {
        safePath := filepath.Clean(f.Name)
        if !strings.HasPrefix(safePath, ".") {
            return errors.New("path traversal detected in ZIP file")
        }
    }
    return nil
}

Register this middleware in your app.go:

app.Use(&ZipSlipValidator{})

Additional Security Measures: Combine path validation with file type restrictions, size limits, and content scanning. Use Buffalo's built-in middleware for basic protections:

app.Use(buffalo.LimitRequestSize(10 << 20)) // 10MB limit
app.Use(buffalo.CanonicalHost("yourapp.com"))

These remediation strategies ensure your Buffalo application safely handles ZIP uploads without exposing Zip Slip vulnerabilities.

Frequently Asked Questions

How can I test if my Buffalo application is vulnerable to Zip Slip?
Create a test ZIP file containing files with paths like ../../test.txt or /etc/passwd, then upload it to your file upload endpoint. Monitor where the files are actually written on the server. You can also use middleBrick's CLI to automatically test your endpoints with crafted malicious ZIP files.
Does Buffalo provide any built-in protection against Zip Slip?
No, Buffalo does not provide built-in protection against Zip Slip vulnerabilities. This is a file handling security issue that must be addressed at the application level by properly validating file paths before extraction. You need to implement path validation in your handlers or use middleware to secure ZIP file processing.