An open API service indexing awesome lists of open source software.

https://github.com/snailsploit/snail-url

Snail-Url is Yet another Wrapper for Open Redirect finding,
https://github.com/snailsploit/snail-url

docker openredirect-scanner penetration-testing ptsnails

Last synced: about 1 month ago
JSON representation

Snail-Url is Yet another Wrapper for Open Redirect finding,

Awesome Lists containing this project

README

          

# Snail-url

**Async open-redirect hunter** for red teams and appsec engineers.
Crawls, harvests redirect-prone URLs, injects payloads, and confirms real open redirects via HTTP 30x, HTML meta refresh, and common JS redirects.

> ⚠️ **Legal/Ethical**: Use only on assets you own or are authorized to test. You are responsible for complying with all laws and terms of service.

---

## Highlights

* ⚑ **Fast & async** (aiohttp) with **per-host rate limiting**
* 🧭 **Crawler fallback** (scope-aware) to discover targets when you don’t have a URL list
* πŸ§ͺ **Payload strategy sets**: `basic`, `aggressive`, `stealth` (and custom test domain)
* πŸ” **SAML / OIDC** focus: `RelayState`, `redirect_uri`, `returnTo`, `continue`, etc.
* πŸ“€ **Outputs**: JSON, NDJSON, CSV + optional dump of unverified candidates
* πŸ–₯️ **Pretty CLI**: compact, padded tables that don’t overflow your terminal

---

## Install

### Local

```bash
git clone https://github.com//snail-url.git
cd snail-url
python3 -m venv .venv && source .venv/bin/activate
pip install --upgrade pip
pip install -e .
```

### Docker

```bash
docker build -t snail-url:latest .
# mount current folder for saving results
docker run --rm -v "$(pwd)":/scan snail-url:latest \
snail-url -d example.com --crawl --max-pages 2000 --json-out /scan/results.json
```

---

## Quick start

Basic run (no crawl):

```bash
snail-url -d example.com --json-out results.json
```

Crawler fallback + aggressive payloads:

```bash
snail-url -d example.com \
--crawl --max-pages 2000 \
--payload-set aggressive \
--include-subdomains \
--samloidc \
--pretty --max-col 100 \
--json-out results.json --csv-out results.csv
```

Use a custom callback/test domain:

```bash
snail-url -d example.com --test-domain https://red.example/cb --json-out results.json
```

Scan a pre-collected list instead of crawling:

```bash
snail-url --in urls.txt --json-out results.json --pretty
```

Dump the **unverified** candidate list for manual review:

```bash
snail-url -d example.com --crawl --candidates-out candidates.txt
```

---

## CLI

```
snail-url [-d DOMAIN] [--seed URL ...] [--in FILE] [--crawl]
[--include-subdomains] [--respect-robots]
[--max-pages N] [-c N] [--per-host N]
[--payload-set {basic,aggressive,stealth}]
[--test-domain URL]
[--json-out FILE] [--ndjson-out FILE] [--csv-out FILE]
[--candidates-out FILE] [--user-agent UA] [--samloidc]
[--pretty] [--no-banner] [--max-col N]
```

**Most useful flags**

* `-d, --domain` β€” target registrable domain (sets default scope/seed)
* `--seed` β€” one or more starting URLs (repeatable)
* `--in` β€” file with URLs to check (one per line)
* `--crawl` β€” enable crawler fallback (async, scope-aware)
* `--include-subdomains` β€” widen scope to subdomains
* `--max-pages` β€” crawl budget (default: 2000)
* `-c, --concurrency` β€” global concurrency (default: 40)
* `--per-host` β€” per-host concurrency limit (default: 10)
* `--payload-set` β€” `basic` | `aggressive` | `stealth`
* `--test-domain` β€” destination injected into redirect params
* `--samloidc` β€” prioritize SAML/OIDC keys (`RelayState`, `redirect_uri`, etc.)
* `--pretty`, `--max-col` β€” tidy, padded table output
* `--json-out`, `--ndjson-out`, `--csv-out` β€” choose one or many

---

## What gets detected

* **HTTP redirects**: 30x with `Location` pointing to your **test domain**
* **HTML Meta Refresh**: e.g., ``
* **JS redirects**: `location =`, `location.replace()`, `location.assign()`

**Redirect-ish parameters** (partial list):
`redirect`, `redirect_uri`, `url`, `next`, `dest`, `destination`, `return`, `returnTo`, `continue`, `cb`, `RelayState`, etc.

**SAML/OIDC** heuristics (when `--samloidc`):

* Detects SAML-ish or OIDC-ish endpoints (`/saml/...`, `/oauth*/authorize`, `/callback`).
* Elevates `RelayState` and `redirect_uri` for injection.

---

## Output examples

### JSON

```json
[
{
"original": "https://app.example.com/redirect?redirect_uri=/dashboard",
"confirmed": true,
"param": "redirect_uri",
"payload": "https://red.example/cb",
"mutated": "https://app.example.com/redirect?redirect_uri=https%3A%2F%2Fred.example%2Fcb",
"via": "http_redirect",
"status": 302,
"location": "https://red.example/cb"
}
]
```

### NDJSON

```
{"original":"https://...","confirmed":true,"param":"redirect","via":"html/js_redirect","status":200,...}
```

### CSV (columns vary with data)

```
confirmed,param,original,mutated,via,status,location,payload
true,redirect_uri,https://...,https://...,http_redirect,302,https://red.example/cb,https://red.example/cb
```

---

## How it works (high-level)

```
Seeds/URLs
└─► Crawler (optional) ─► Harvester (redirect-ish params)
└─► Verifier (payload sets, no-follow)
└─► Findings (JSON/NDJSON/CSV)
```

* **Crawler**: async fetch, extracts links, respects scope, per-host RL.
* **Harvester**: filters URLs with redirect-ish parameters.
* **Verifier**: injects payloads β†’ checks 30x `Location`, meta refresh, JS redirect.

---

## Tuning & tips

* **Throughput**: Bump `-c` but keep `--per-host` reasonable (8–12) to reduce server strain.
* **Noise**: Use `--payload-set stealth` for low-touch passes; `aggressive` when you need depth.
* **Scope**: Start narrow (`-d`) and add `--include-subdomains` if needed.
* **Crawler budget**: Increase `--max-pages` for large estates; capture candidates via `--candidates-out`.
* **User-Agent**: Customize with `--user-agent` for logs/attribution.

---

## Troubleshooting

* **No findings but many candidates**
Targets might block external destinations; try different `--payload-set` or `--test-domain`.
* **Timeouts**
Reduce `-c` and `--per-host`; some WAFs throttle concurrency.
* **Messy terminal output**
Use `--pretty --max-col 100` (table is padded & ellipsized). Use `--no-banner` to minimize whitespace.

---

## Development

```bash
# lint/format as you like; basic tests included
pytest -q
```

Project layout:

```
snail_url/
cli.py # CLI entry
crawler.py # async crawler (scope-aware)
harvester.py # picks redirect-like URLs
verifier.py # injects payloads, confirms redirects
payloads.py # basic/aggressive/stealth generators
saml_oidc.py # SAML/OIDC heuristics
ui.py # pretty table output
utils.py, constants.py, output.py
```

---

## Roadmap

* Optional archive sources (Wayback, GAU) as inputs
* SARIF exporter for CI
* Parameter mutation strategies by framework (Next.js, Spring, ASP.NET)
* Allow/deny-lists per path/param

---

## Contributing

PRs and issues welcome. Please include:

* Clear repro steps (target pattern anonymized)
* Before/after output snippets
* Any performance/safety considerations

---

## License

MIT Β© SnailSploit

---

Want me to drop this straight into your repo as `README.md` (and add status badges)? Say the word and I’ll prep a PR description and push-ready commit message.

---

## πŸ“š Documentation & Author

This project's full writeup, methodology, and related research lives at:

**[https://snailsploit.com/tools](https://snailsploit.com/tools)**

Created by **Kai Aizen** β€” independent offensive security researcher.

[snailsploit.com](https://snailsploit.com) Β· [Research](https://snailsploit.com/research) Β· [Frameworks](https://snailsploit.com/frameworks) Β· [GitHub](https://github.com/SnailSploit) Β· [LinkedIn](https://linkedin.com/in/kaiaizen) Β· [ResearchGate](https://www.researchgate.net/profile/Kai-Aizen-2) Β· [X/Twitter](https://x.com/SnailSploit)

> *Same attack. Different substrate.*