Metadata-Version: 2.4
Name: wraith-sec
Version: 0.9.7
Summary: Offensive web recon & vulnerability detection — a pipeline of composable phases.
Project-URL: Homepage, https://github.com/gusta-ve/wraith
Project-URL: Repository, https://github.com/gusta-ve/wraith
Project-URL: Issues, https://github.com/gusta-ve/wraith/issues
Project-URL: Changelog, https://github.com/gusta-ve/wraith/blob/main/CHANGELOG.md
Author-email: Gustavo Almeida <gustavoalm09@gmail.com>
License: MIT
License-File: LICENSE
Keywords: automation,offensive-security,pentest,recon,red-team,security
Classifier: Environment :: Console
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Security
Requires-Python: >=3.10
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == 'dev'
Provides-Extra: http
Requires-Dist: httpx>=0.27; extra == 'http'
Description-Content-Type: text/markdown

# wraith

<p align="center">
  <img src="docs/hero.svg" alt="wraith — offensive recon & vulnerability detection pipeline" width="900">
</p>

An offensive security scanner that runs the recon-to-detection workflow as a
pipeline of small composable phases. Point it at a target; it resolves hosts,
scans ports, maps the web surface, tests it and reports what it finds — then
hand the catch to [hickok](https://github.com/gusta-ve/hickok) to act on it. The
core has no third-party dependencies.

[![PyPI](https://img.shields.io/pypi/v/wraith-sec?color=crimson&label=pypi)](https://pypi.org/project/wraith-sec/)
[![CI](https://github.com/gusta-ve/wraith/actions/workflows/ci.yml/badge.svg)](https://github.com/gusta-ve/wraith/actions/workflows/ci.yml)
[![Release](https://img.shields.io/github/v/release/gusta-ve/wraith?color=crimson)](https://github.com/gusta-ve/wraith/releases)
![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue)
![MIT](https://img.shields.io/badge/license-MIT-green)

- [Install](#install)
- [Usage](#usage)
- [Phases](#phases)
- [Web testing](#web-testing)
- [Post-exploitation](#post-exploitation--hickok)
- [Extending](#extending)
- [Lab](#lab)

## Install

pipx gives you a global `wraith` (the right call on Kali, which blocks system
pip via PEP 668):

```bash
sudo apt install -y pipx && pipx ensurepath
pipx install wraith-sec            # the command is `wraith`
pipx install "wraith-sec[http]"    # + httpx, faster probing
```

From a clone:

```bash
git clone https://github.com/gusta-ve/wraith && cd wraith
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[http]"
```

Or without installing anything: `PYTHONPATH=src python3 -m wraith run target`.

<details>
<summary>Restricted network (proxy / broken IPv6 / HTTP-2 hiccups)</summary>

If `pip`/`git` time out on PyPI or GitHub, grab the prebuilt wheel from the
[releases page](https://github.com/gusta-ve/wraith/releases/latest) — one file,
zero dependencies, no clone and no build step:

```bash
python3 -m venv ~/.local/share/wraith-venv
~/.local/share/wraith-venv/bin/pip install ./wraith_sec-*.whl   # the wheel you downloaded
ln -sf ~/.local/share/wraith-venv/bin/wraith ~/.local/bin/wraith
```

`git clone` failing with *"HTTP2 framing layer"*? Force HTTP/1.1:
`git config --global http.version HTTP/1.1`.
</details>

## Usage

`run` is the default command, so a target is all you need:

```bash
wraith target.com                              # full pipeline (no subcommand needed)
wraith -u https://target.com:8443              # target as a URL (-u/--url); the port is scanned too
wraith 10.10.10.5 -p resolve,tcp-scan,http-probe   # only these phases
wraith target.com --recon                      # recon only: ports + service/version, no attack traffic
wraith target.com -P web                       # sweep HTTP/alt-HTTP ports; -P all for a full scan
wraith target.com -s sessions.json             # adds access-control / IDOR
wraith target.com -v                           # progress; -v 2 = attack detail (payloads/requests), -v 3 = responses
wraith target.com -x high                      # exit code 2 on a High+ finding
wraith target.com --delay 0.5 --jitter 0.5     # quiet: pace requests, randomise the timing
wraith target.com --random-agent               # send a real browser UA, not wraith/<ver>
wraith target.com --proxy http://127.0.0.1:8080  # route through Burp (or any HTTP/SOCKS proxy)
wraith target.com --tor                        # route via Tor — verified, fails closed
wraith target.com --ghost                      # max-opsec preset: Tor + random UA + low-and-slow, one flag
wraith --theme matrix target.com               # crimson (default) | matrix | ice | amber | mono
wraith showdown                                # toggle "showdown mode" — wraith plays the catch out (reveal + verdict)
wraith phases                                  # list phases and their dependencies
```

A run writes a self-contained directory under a fixed per-user location —
`~/.local/share/wraith/runs/` by default (set `WRAITH_RUNS` to move it, or
`--workdir` per run) — so [hickok](https://github.com/gusta-ve/hickok) finds it
from anywhere:

```
~/.local/share/wraith/runs/target.com-<ts>/
  workspace.json   every host, service, endpoint and finding (resumable)
  report.md
  report.html      dark, self-contained
  findings.json
```

A run against the bundled lab (`examples/vuln_app.py`) — every finding shown is
one wraith actually catches:

![a wraith run](docs/demo.svg)

`--no-banner` and `--no-color` (or `NO_COLOR`) strip the cosmetics for logs and
CI; `WRAITH_THEME` sets a default theme.

## Phases

Each phase declares the phases it depends on. The engine resolves that graph and
runs independent phases concurrently; a failing phase is isolated and its
dependents are skipped. Everything is shared through one persisted workspace.

```
resolve            DNS resolution
tcp-scan           async TCP connect scan of common ports
http-probe         status, Server header and title
content-discovery  path/file wordlist with soft-404 filtering
tech-detect        server / language / framework / CMS fingerprint
vhost              virtual-host discovery via Host-header fuzzing
template-checks    declarative JSON/YAML vulnerability checks
security-headers   security headers, cookie flags and CORS
injection          XSS, SQLi (error/boolean/time), command injection, SSTI, LFI, open redirect
access-control     Broken Access Control and IDOR (needs sessions)
```

## Web testing

`injection` crawls the target, pulls parameters from query strings and forms,
and probes each with a battery of techniques. Every technique has a single,
explainable oracle — and **every hit is confirmed a second way before it's
reported**, so a finding is evidence, not a guess:

| Technique | Oracle | Confirmed by |
|---|---|---|
| Reflected XSS | a raw `<`/`>`/`"` marker reflects unencoded | — |
| SQLi (error-based) | a single quote raises a DB error | a *balanced* quote clears it |
| SQLi (boolean-blind) | a TRUE condition page matches normal, FALSE diverges | a second, different injection context |
| SQLi (time-blind) | `SLEEP`/`pg_sleep`/`WAITFOR` delays the response | a longer sleep delays proportionally more |
| Command injection | `; sleep N` delays the response | same time-correlation proof |
| SSTI | `{{a*b}}` comes back evaluated (the product) | a second random product |
| Path traversal / LFI | `../../etc/passwd` returns a `root:x:0:0:` signature | read twice |
| Open redirect | a redirect param lands in `Location` | — |

Verbosity is levelled like other scanners. `-v` (level 1) is lightweight
progress — which parameter is being tested, crawl brackets — so a run never
looks frozen. `-v 2` is the full attack play-by-play: every payload, its oracle
measurement (similarity ratios, response timings) and the confirmation step,
plus each HTTP request. `-v 3` adds the responses:

```bash
wraith target.com -p injection -v      # level 1 — progress only
wraith target.com -p injection -v 2    # the detailed attack trace
```

`security-headers` reports missing CSP/HSTS/X-Frame-Options/nosniff, weak cookie
flags and CORS that reflects an arbitrary origin.

`access-control` needs authenticated sessions. It crawls as the privileged
session and replays every request as the lower-privilege and anonymous ones; a
lower principal getting identical content is a vertical bypass, and mutating
numeric ids surfaces IDOR. Grab a session with:

```bash
wraith login http://target/login -u alice -p secret \
    --user-field user --pass-field password -o sessions.json
```

## Evasion / opsec

By default wraith scans flat out from a `wraith/<ver>` User-Agent — loud, and easy
to attribute in a target's logs. For an authorized engagement where the footprint
matters, control it:

```bash
wraith target.com --ghost                      # the safest footprint, one flag: Tor + random UA + low-and-slow
wraith target.com --delay 0.5 --jitter 0.5     # pace requests (+ random jitter)
wraith target.com -A "Mozilla/5.0 …"           # an explicit User-Agent
wraith target.com --random-agent               # a random real-browser UA per run
wraith target.com -H "X-Forwarded-For: 1.2.3.4" --cookie "session=…"
wraith target.com --proxy socks5h://127.0.0.1:9050   # any HTTP/SOCKS proxy (Burp, …)
wraith target.com --tor                        # route via Tor, verified
wraith --check-tor --tor                       # just confirm the exit, then exit
```

The quietest run of all is `--recon`: it sends no attack traffic at all — just port
discovery and service/version fingerprinting, like an `nmap -sV` (a couple of
requests, not a wordlist of `/wp-login.php` probes). Pair it with the knobs below to
map a target before deciding whether to bring the loud phases.

`--delay` is enforced across every phase (the scan goes serial while it's set), so
the whole run is paced, not just one phase. SOCKS/Tor is native (no PySocks) and
resolves DNS remotely (`socks5h`) so the hostname never leaks to your resolver.
`--tor` **fails closed**: wraith verifies the exit really is Tor before sending any
attack traffic and aborts otherwise, so a misconfigured run can't deanonymise you.
One caveat: wraith doesn't verify the target's TLS certificate (offensive targets
routinely have broken ones), so a hostile proxy or Tor exit can read or tamper with
the traffic to the target — your origin stays hidden, but the channel to the target
itself isn't trusted.

Don't want to remember the knobs? `--ghost` is the one-flag preset for the safest
footprint — Tor (fail-closed), a random browser UA, low-and-slow pacing and serial
requests, all at once. Override any single piece with its own flag (`--ghost --delay
2`). The same flag works in [hickok](https://github.com/gusta-ve/hickok).

## Finding targets — `wraith dork`

`wraith dork` turns a search-engine **dork** (a query with operators like `inurl:`,
`intitle:`, `ext:`) into a list of URLs — and stops there. It's a **discovery**
command: it lists results and **never sends a request to them**. Testing what you
find is the separate, deliberate `wraith <url>` step.

```bash
wraith dork "inurl:login"                  # a raw dork
wraith dork --params                       # URLs with injectable params (SQLi/IDOR candidates)
wraith dork --params --site target.com     # the same, scoped to a target you're authorized to test
wraith dork --files --max 50 -o urls.txt   # exposed files (.env/.bak/.sql…), save the list
```

Preset flags build the dork for you and combine with a query and each other:
`--params` (also `--injec` — injectable-looking parameters), `--files` (exposed
files), `--panels` (login/admin), `--listing` (open directory listings). `--site
DOMAIN` scopes the search to one domain and drops anything off it. `--with-params`
keeps only URLs carrying a `?param=` (the injectable ones), cutting the articles a
search engine surfaces *about* dorking — `--params` implies it.

By default it needs **no setup** — it scrapes DuckDuckGo's HTML endpoint (the same
no-key path sqlmap's `-g` falls back to). For heavier or steadier use, configure an
API backend and wraith prefers it automatically:

```bash
export WRAITH_SEARXNG_URL=https://searx.example          # SearXNG (self-host or public)
export WRAITH_GOOGLE_API_KEY=…  WRAITH_GOOGLE_CX=…        # Google Programmable Search
export WRAITH_BRAVE_API_KEY=…                            # Brave Search API
```

`--engine duckduckgo|searxng|google|brave` forces a specific one. DuckDuckGo honours
`inurl:` loosely, so expect some noise (`--with-params` trims it); for the cleanest
`inurl:` dorking configure Google Programmable Search. Discovery is for targets
you're authorized to assess — a dork points you at an attack surface, it doesn't
grant permission to test it.

## Post-exploitation — [hickok](https://github.com/gusta-ve/hickok)

wraith finds and proves the way in; landing a shell and working the box is
[**hickok**](https://github.com/gusta-ve/hickok)'s job — wraith's companion. It
reads a wraith run and acts on it:

```bash
hickok call          # picks up wraith's latest run on its own, flags the footholds
hickok -l 9001       # catch the reverse shell
```

wraith holds the aces, hickok brings the eights — aces and eights, the dead
man's hand.

## Extending

A phase is one file; a check can be pure data. See
[docs/writing-a-phase.md](docs/writing-a-phase.md) and
[docs/writing-a-template.md](docs/writing-a-template.md).

```python
from wraith.core.phase import Phase, register

@register
class MyPhase(Phase):
    name = "my-phase"
    requires = frozenset({"http-probe"})

    async def run(self, ws, console):
        for ep in ws.endpoints:
            ...  # ws.add_finding(...)
```

## Lab

`examples/vuln_app.py` is a deliberately vulnerable app to practise against and
to exercise every web phase: BAC, IDOR, reflected XSS, SQLi (error/boolean/time),
command injection, SSTI, path traversal/LFI, open redirect, CORS, insecure
cookies and missing headers. Its `/db?id=` is a boolean-blind SQLi over a real
(tiny) SQLite database — point [hickok](https://github.com/gusta-ve/hickok)'s
`hickok sql` at it to walk and dump it.

```bash
python3 examples/vuln_app.py &
wraith 127.0.0.1 -s examples/sessions.json -v
```

For a bigger, leveled target — a whole town of rooms, tutorial to impossible —
there's [**deadwood**](https://github.com/gusta-ve/deadwood), the dedicated
practice range for wraith and hickok:

```bash
pipx install deadwood-sec && deadwood serve   # http://127.0.0.1:8666
wraith 127.0.0.1:8666 -v
```

## Tests

```bash
pip install -e ".[dev]" && pytest
```

## Disclaimer

Built for security research and testing — point it where you're meant to. What
anyone does with it from there is theirs alone; the author takes no
responsibility for misuse or for any damage caused.

## License

MIT.

---

*You never saw it coming — the wraith was already holding aces.*

*the aces Wild Bill was holding — Deadwood, 1876.*
