Zip Slip in Echo Go with Hmac Signatures
Zip Slip in Echo Go with Hmac Signatures — how this specific combination creates or exposes the vulnerability
Zip Slip is a path traversal vulnerability that occurs when an archive extraction uses user-supplied paths without proper sanitization. In Echo Go, if you accept an uploaded archive and then validate or trust a hash-based message authentication code (Hmac Signatures) without validating file paths, you can inadvertently allow malicious entries that traverse directories. The vulnerability is not in the Hmac verification itself, but in how you combine unchecked archive contents with a trusted Hmac that gives a false sense of integrity.
Consider an upload flow where a client sends an archive and an Hmac header derived from the archive’s bytes. The server recomputes the Hmac using a shared secret and compares it before extraction. If the comparison succeeds, extraction proceeds. However, if extraction uses the archive member’s filename directly (e.g., via zipFile.Open(name) without cleaning the path), an entry like ../../../malicious.exe can write outside the intended directory. The Hmac matched because the attacker could have provided the correct hash if they controlled the archive bytes, but the server trusted the name implicitly. This is a classic case where strong Hmac Signatures protect integrity of the payload but do not protect against unsafe extraction logic.
In practice, an attacker might craft an archive with a file entry named ../../etc/passwd and a valid Hmac if the server’s secret is leaked or the comparison is done incorrectly (for example, comparing MACs in a non-constant-time way leading to timing leaks). Even when Hmac Signatures confirm the payload hasn’t been tampered with, the server must still enforce strict path sanitization. Echo Go handlers that bind request bodies and extract archives without validating paths expose the application to Zip Slip despite using Hmac Signatures, because the vulnerability lies in path handling, not cryptographic verification.
Hmac Signatures-Specific Remediation in Echo Go — concrete code fixes
To remediate Zip Slip in Echo Go while using Hmac Signatures, you must validate and sanitize file paths before extraction, and ensure Hmac comparison is performed safely. Below is a concrete, secure approach with working code examples.
1. Validate Hmac before extraction
Compute the Hmac over the raw request body (or the archive bytes) and compare it using a constant-time function before any filesystem operations.
import (
"crypto/hmac"
"crypto/sha256"
"net/http"
)
func verifyHmac(body []byte, receivedMac string, secret []byte) bool {
mac := hmac.New(sha256.New, secret)
mac.Write(body)
expectedMac := mac.Sum(nil)
// Use subtle.ConstantTimeCompare to avoid timing attacks
return hmac.Equal(expectedMac, []byte(receivedMac)) // simplified; in practice decode hex/base64
}
func uploadHandler(c echo.Context) error {
raw, err := c.Request().Body.ReadAll()
if err != nil {
return err
}
receivedMac := c.Request().Header.Get("X-Archive-Hmac")
secret := []byte(os.Getenv("HMAC_SECRET"))
if !verifyHmac(raw, receivedMac, secret) {
return echo.NewHTTPError(http.StatusBadRequest, "invalid hmac")
}
// proceed to safe extraction
return extractArchiveSafe(raw)
}
2. Sanitize archive paths during extraction
Use a strict path cleaning function that prevents directory traversal. Do not trust archive member names.
import (
"archive/zip"
"io"
"path/filepath"
"strings"
)
func extractArchiveSafe(archiveData []byte) error {
r, err := zip.NewReader(bytes.NewReader(archiveData), int64(len(archiveData)))
if err != nil {
return err
}
for _, f := range r.File {
// Clean path: ensure it stays within target directory
cleanPath := filepath.Clean(f.Name)
if strings.HasPrefix(cleanPath, "..") || filepath.IsAbs(cleanPath) {
return fmt.Errorf("invalid path in archive: %s", f.Name)
}
// Optionally, also restrict to a subdirectory like "uploads/"
if !strings.HasPrefix(cleanPath, "uploads"+string(os.PathSeparator)) {
return fmt.Errorf("path escapes upload directory: %s", f.Name)
}
rc, err := f.Open()
if err != nil {
return err
}
defer rc.Close()
// Write to cleanPath under a safe base directory
// ... your write logic here
}
return nil
}
3. Combine Hmac integrity with filesystem safety
Ensure Hmac verification runs before extraction and that extraction never uses raw names. This way, even if an archive contains malicious paths, the server rejects or safely handles them. You can also integrate these checks into your Echo middleware pipeline to enforce validation uniformly across endpoints.