⬢ DragonFlyBSD Kernel Audit
DF-3323 / verdict.json
← back to finding ↓ download raw
{
  "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)"
}