Files
Mark-VIII/docs/validation/2026-08-23-pineap-validation-round2.md
T
c4ch3c4d3 0f31bfe885 fix(portals,capture): round-2 validation fixes, live-verified on Pager
- portals: replace zipfile with struct+zlib ZIP writer in portal download
  (python3-light has no zipfile; GET /api/portals/<name>/download 500ed)
- capture: revive watchdog re-arms the 5 GHz deploy auto-capture if the
  post-deploy radio settle kills it (was: empty pcap, dead tcpdump)
- capture: route GET /api/attacks/capture to status (was unrouted -> 404)

New tests/test_validation_fixes2.py covers each fix (TDD); full suite
(30 modules) green. Live-verified: download CRC-clean via stock zipfile,
capture survived settle window and revived automatically (56 MB pcap),
GET status returns proper JSON.

Round-2 validation report added at docs/validation/ (8/9 attack types
PASS against in-scope networks; enterprise PARTIAL per firmware limits).
2026-08-24 08:23:26 -06:00

7.0 KiB

Mark-VIII PineAP Attack Validation — Round 2 (post-fix), 2026-08-23

Full live re-validation of every PineAP attack type exposed by Mark VIII, executed after the fix round in commit d23ea56. All attacks were run against authorized, in-scope networks only.

Environment

Role Host Identity
Attack platform WiFi Pineapple Pager 24.10.1, root@172.16.52.1, Mark VIII :8080 radio0 MAC base 00:13:37:ae:e0:50, radio1 00:13:37:ae:8e:7c
Victim client Kali Linux, bzuccaro@192.168.1.103, wlan0 a0:a4:c5:93:f8:05 NetworkManager + standalone wpa_supplicant
In-scope targets Znet (WPA2/WPA3-SAE-mixed, 5GHz ch36/44/48/…; PSK provided) and Znet-Open (open, 2.4GHz ch6 B6:8B:A9:17:2A:6E, ch11 B6:8B:A9:17:47:33) recon.db fresh scans confirmed both

Pre-flight: /api/health env pass (pineapd alive, both monitors up, recon readable).

Results summary

# Attack / capability Endpoint(s) Result Proof captured
1 Recon recon.db / scan history PASS Both SSIDs present with fresh timestamps, correct BSSIDs/channels/crypto
2 Evil Open twin + Evil Portal credential capture POST /api/attacks/deploy kind=open + portals API PASS Victim associated to spoofed-BSSID twin (172.16.52.123); DNS hijack resolved arbitrary domain → 172.16.52.1; portal served on :80; POSTed creds recorded with MAC/hostname/IP (evidence/r2_t1_portal_captures.json)
3 Karma association (implicit) PASS Real third-party client 48:e1:e9:4d:98:8a associated to Znet-Open twin unprompted; later handshakes from 68:9e:19:d1:6e:e1 / e6:75:7f:45:fd:57 on the WPA twin across multiple probed SSIDs
4 Filters auto-config post-deploy GET /api/pineap/filters/{ssid,client} PASS (BUG 2 fix verified) After deploy both filters read deny + empty with no manual help — twins accept clients unaided
5 Single deauth via API POST /api/attacks/deauth PASS (BUG 1 fix verified) ok:true, inject:wlan0mon; pcap holds 556 deauth frames incl. directed SA=twin-BSSID → DA=victim (evidence/r2_t2_deauth.cap); victim dropped (NM re-associated sub-second)
6 Client kick POST /api/pineap/clients/kick PASS Deny filter added for victim MAC; victim flapped DISCONNECTED/CONNECTED and could not hold association until filter cleared
7 Evil WPA twin 5GHz + handshake capture deploy kind=wpa + attacks/capture PASS Twin live ch44 (02:13:37:ae:8e:7c); full EAPOL 4-way from victim captured on pinned wlan1mon; export produced 18-row .hc22000 incl. victim AND real-client handshakes
8 hc22000 export → crack GET /api/attacks/export/hc22000 + hashcat -m 22000 (Kali) PASS PSK recovered for victim (021337ae8e7c:a0a4c593f805:Znet) and real client (…:e6757f45fd57:Znet) = exact known PSK (evidence/r2_t4_cracked.txt)
9 Bulk deauth POST /api/attacks/deauth/bulk PASS 3-target batch: 2 valid sent (sent:2), malformed target rejected per-index without aborting batch; victim dropped on-air
10 Evil Enterprise PEAP/MSCHAPv2 deploy kind=enterprise PARTIAL AP verified + ctrl-linked + runtime-bridged; client associates; TLS tunnel up; server issues inner MSCHAPv2 success for victim@znet.local. BUT wpa_supplicant rejects the karma wpad's success request ("Invalid authenticator response") so no full CONNECTED; hostap_basic/hostap_chalresp remain empty (known firmware residual). See §T6
11 Post-suite hygiene PASS All attacks stopped, zero leftover APs/tcpdump/watchdog churn, health env pass, victim restored to real Znet (18:e8:29:b5:a4:2c)

New defects found this round

D1 — MEDIUM: portal download endpoint crashes on device

h_portal_download (server.py:5395) imports zipfile, which python3-light does not ship (the import endpoint was converted to struct+zlib in d23ea56 but download was missed): GET /api/portals/<name>/download{"error": "No module named 'urllib'"}. Fix: reuse the minimal ZIP writer approach or stream raw files.

D2 — MEDIUM: deploy-time auto-capture produces an empty pcap

The 5GHz WPA deploy reported "capture": true but the auto-started wlan1mon capture died during AP bring-up (file stayed at the 24-byte header; no tcpdump process left). A capture started after the AP is up works fine (frames flow, monitor inherits phy channel context). Fix: arm the auto-capture after hostapd verify-loop completes, and/or have _capture_state detect-and-restart the dead pid (ISSUE 7 stale logic exists but did not fire here). Also: h_attacks_capture silently ignores a channel body param — either honor it or reject it.

D3 — LOW/cosmetic: GET /api/attacks/capture with no active capture returns 404

{"error":"not found"} instead of {running:false,...} — UI-hostile shape.

T6 detail (Enterprise PARTIAL)

Repro: deploy kind=enterprise ssid=Znet enctype=wpa2 channel=44 passphrase=VictimPass123!verified:true, ctrl_linked:true. Victim (standalone wpa_supplicant, MAC randomization off):

  • Association OK; outer PEAP TLS tunnel completes (CTRL-EVENT-EAP-PROPOSED-METHOD method=25)
  • Inner MSCHAPv2 exchange runs; client logs EAP-MSCHAPV2: Received success — i.e. the standalone hostapd accepted the inner credentials (BUG 3 eap_users grammar fix works)
  • But every attempt then logs EAP-MSCHAPV2: Invalid authenticator response in success request → supplicant refuses, disconnects, retries forever. Same result with matched and mismatched passwords (server auto-accepts but its AuthResp never verifies) — consistent with the karma- patched wpad issuing success without computing it from the stored secret.
  • TTLS/PAP could not be differentiated this round (client-side sed failure meant PEAP ran; association-level flapping prevented a clean second attempt).
  • hostap_basic / hostap_chalresp: still empty (documented firmware residual — pineapd does not forward from foreign hostapd instances). Enterprise client list DOES record associations.

Net: enterprise twin captures inner-auth material server-side only as far as hostapd's own logs; portable credential loot remains impossible on 24.10.1 without a Hak5 pineapd change.

Evidence index (evidence/r2_*)

File Content
r2_t1_portal_captures.json Captured portal credentials (user/pass, victim MAC/hostname/IP)
r2_t2_deauth.cap wlan0mon pcap, 556 deauth frames (directed at victim)
r2_t2_deauth.json, r2_t2_kick.json API responses proving deauth/kick ok:true
r2_t3_deploy_wpa.json WPA twin deploy response (capture:true, verified:true)
r2_t3_hc_export.json, r2_handshakes.hc22000 Exported 18 handshake hashes
r2_t4_cracked.txt hashcat --show output recovering the true PSK (victim + real client)
r2_t5_bulk.json Bulk deauth batch results (2 sent / 1 rejected)
r2_t6_deploy_ent.json Enterprise deploy response

Copies of key artifacts also live on-device (/root/loot/**) and on Kali (/tmp/r2.hc22000, removed wordlist).