DF-3323 / verdict.json
{ "finding_id": "DF-3323", "status": "reproduced", "reproduced": 1, "impact": "auth_bypass (remote RF-adjacent, no key: authorized+associated, AID, EAPOL passthrough; cleartext data when DROPUNENC off)", "confidence": "certain", "verdict": "hostap_input() decrypts AUTH frames only when the Protected bit is set and then clears it (:851-880); hostap_auth_shared() processes the seq-3 challenge response with no encryption requirement and memcmp()s it against the challenge the AP itself sent in cleartext (:1138). Echoing the overheard challenge in a cleartext seq-3 frame authenticates the attacker without the WEP key (ieee80211_node_authorize :1149). Reproduced on the stock INVARIANTS kernel: AUTHORIZED=1 + associd 0xc001 under wepmode on; corrupt-challenge control correctly refused (status 15); one cleartext TODS data frame delivered under wepmode mixed (netstat Ipkts 1->2).", "exploit_chain": "1) inject AUTH shared seq1 (30B) -> AP creates node, sends seq2 challenge cleartext; 2) capture challenge off the air in raw_xmit; 3) inject AUTH shared seq3 carrying the captured challenge with Protected bit CLEAR -> AP replies seq4 status 0, port authorized; 4) inject ASSOC_REQ -> associd 0xc001; 5) (wepmode mixed / no wepmode) inject cleartext TODS data frames -> delivered to AP stack", "evidence": "run.log/run.2.log: fw4[air]: AP TX AUTH seq=2 status=0 challenge_ie_len=128 protected=0, fw4.state[current]: ... AUTHORIZED=1 ... <<<< BYPASSED, associd 0xc001, netstat Ipkts 1->2; fix.log: patched kernel drops the cleartext seq3 (AUTHORIZED=0, no seq4 TX) while attack=1 still elicits the challenge", "kernel_refs": [ "sys/netproto/802_11/wlan/ieee80211_hostap.c:851", "sys/netproto/802_11/wlan/ieee80211_hostap.c:1122", "sys/netproto/802_11/wlan/ieee80211_hostap.c:1138", "sys/netproto/802_11/wlan/ieee80211_hostap.c:1149", "sys/netproto/802_11/wlan/ieee80211_output.c:2380" ], "poc_changes": "seed none (new harness): fw4.c = fw3.c pattern (DF-3282/3312/3314) + raw_xmit sniffer capturing the APs outgoing AUTH/challenge frames + sysctl-driven injectors (attack=1 request, 2 captured-challenge response, 3 corrupt-challenge control, 4 assoc, 5 cleartext data, 6 open-auth regression). DF ifconfig spells hostap mode wlanmode ap not wlanmode hostap.", "attempts": 3, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 (baseline) / #1 21:29:25 UTC 2026 (fix validation)", "runtime_sec": 1500, "guest_dirty": 0, "build_cmd": "sh findings/poc/DF-3323/build.sh (make SYSDIR=/usr/src/sys in /root/fw4)", "run_cmd": "sh findings/poc/DF-3323/run.sh ; sh findings/poc/DF-3323/fixcheck.sh", "code_hash": "4bf00201a1d2ae127b246f2ad2f87e3ec930c17741b396f09e7279f55c9f36f5", "notes": "APs seq-2 challenge frame is legitimately cleartext per 802.11-2016 12.3.3 (and the kernel never encrypts it); only frame 3 must be protected. The kernel also never encrypts its seq-4 success frame (add_auth marks crypto only for arg==3 which the AP never sends) - cosmetic spec deviation noted, not exploitable.", "recommended_fix": "In hostap_input()s MGT path, discard AUTH frames that arrive unprotected and parse as algo=SHARED seq=RESPONSE (802.11-2016 12.3.3); see fix.diff", "fix_status": "fixed", "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #1: Thu Sep 10 21:29:25 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_verdict": "make -j6 nativekernel rc=0 with fix.diff (+DF-3326 fix); baseline bypass (AUTHORIZED=1) is gone: cleartext seq3 dropped with is_rx_bad_auth++, no seq-4 TX, node stays AUTHORIZED=0; regression: seq-1 request still elicits the cleartext seq-2 challenge, open-auth flow associates normally.", "fix_evidence": "findings/poc/DF-3323/fix.log + findings/poc/DF-3326/fix.log (shared kernel #1 21:29)" } |