diff --git a/docs/superpowers/specs/2026-08-23-deauth-evilportal-capture-design.md b/docs/superpowers/specs/2026-08-23-deauth-evilportal-capture-design.md new file mode 100644 index 0000000..4f1afae --- /dev/null +++ b/docs/superpowers/specs/2026-08-23-deauth-evilportal-capture-design.md @@ -0,0 +1,116 @@ +# Mark VIII — Deauth UX, Evil Portal, Monitor Capture Fixes + +Date: 2026-08-23 +Status: approved (user confirmed design in session) + +## Goals + +1. Make deauth obvious: "Deauth All Clients" from Recon's AP focus sidebar, "Deauth All" + on the Deauth Targeting card — both gated by an engagement-scope confirmation. +2. New top-level **Evil Portal** tab compatible with Hak5 EvilPortalNano portals + (kleo/evilportals layout): import zips, serve pages to victims, capture credentials, + DNS-hijack delivery. +3. OpenAP gains an "Evil Portal" card: dropdown of imported templates, greyed out when + none exist; activating an OpenAP with a template selected starts the portal. +4. Fix Monitor Capture never appearing to work. + +## Non-goals + +- No PHP interpreter; the backend shims only the trivial PHP patterns stock portals use. +- No TLS interception (HTTPS requests are not redirected). +- `.enable`/`.disable` portal scripts are stored but **not executed** (divergence from + stock EvilPortalNano, documented here deliberately). + +## 1. Bulk deauth endpoint + +`POST /api/attacks/deauth/bulk` body `{targets: [{bssid, client, channel?}, ...]}` +(max 32). Shared helper `_deauth_one(bssid, client, channel)` extracted from +`h_attacks_deauth`; per-target results returned `{results: [...], sent, failed}`. +Uses the existing band→inject-iface logic and `PINEAPPLE_DEAUTH_CLIENT`. + +### Recon sidebar + +In `renderFocus()` (www/js/views.js), when the focused AP has confirmed clients, add a +danger button **"Deauth All Clients"**. Clicking shows +`confirm("Deauthenticate N client(s) of ? Confirm this target is IN SCOPE for your engagement.")`, +then posts one bulk call. + +### Deauth Targeting card + +`deauthPanel()` gains a danger **"Deauth All"** button that bulk-deauths every device in +the current result list against the selected AP, behind the same scope confirmation. + +## 2. Evil Portal + +### Storage & import + +- Root: `/mmc/mk8/portals//` (`[A-Za-z0-9._-]{1,64}` names, mk8_profiles rules). +- `POST /api/portals/import` `{data: }` (≤10 MB decoded). Zip-slip guarded + (reject absolute paths and `..`). If every entry shares a single top-level directory, + that directory becomes the portal root. `index.php` must exist at the root. +- Other endpoints: `GET /api/portals`, `DELETE /api/portals/{name}`, + `POST /api/portals/{name}/activate|deactivate`, `GET /api/portals/captures`, + `DELETE /api/portals/captures`, `GET /api/portals/{name}/logs` (Download), + `GET /api/portals/{name}/download` (zip of the portal folder). + +### Serving engine (port 80) + +Second listener thread in server.py, own connection handler (no auth, no same-origin — +victims are unauthenticated). Admin UI on :8080 untouched. + +- **GET anything** → active portal: + - Path resolves inside the portal dir (`_safe_join`); missing paths fall back to + `index.php`; asset files served raw with the standard mime map. + - `index.php` rendered through the PHP shim. +- **PHP shim**: replaces `getClientMac($_SERVER['REMOTE_ADDR'])` / + `getClientHostName(...)` with values resolved from DHCP leases for the requester IP, + `$_SERVER['REMOTE_ADDR']` with the requester IP, `$destination` with the request URL; + strips all other `` / `` blocks. +- **POST anything** → credential capture: parse urlencoded fields, enrich with client + ip/mac/hostname, append: + - `/.logs` in the exact MyPortal.php text format (stock-tool compatible), and + - `/mmc/mk8/portals/captures.jsonl` (one JSON object per line) for the UI. + Response: simple authorization-success HTML page. + +### Delivery: DNS hijack + +Activation writes `dhcp.@dnsmasq[0].address='/#/'` (UCI), commits, restarts +dnsmasq; deactivation deletes the option and restarts. LAN IP discovered via +`ip -4 addr show br-lan` (env-overridable `PAGER_LAN_IFACE`, fallback 172.16.52.1). +Active portal name persists at `/mmc/mk8/portals/.active`; on service start the hijack +is re-applied best-effort if a portal was left active. + +### Tab UI + +Rail entry + route `#/evilportal` + `views.evilportal`: Active Portal status card, +Templates card (list with Activate/Stop/Delete/Download, Import via zip file input → +base64), Captured Credentials table (time, portal, fields) with Clear and Download. + +## 3. OpenAP Evil Portal card + +`attackLauncher('open', {..., portal: true})`: card with a template `