Skip to content

Fix WPA3/SAE attack correctness, honesty, and dead flags#526

Merged
kimocoder merged 1 commit into
masterfrom
wpa3-implementation-fixes
Jun 3, 2026
Merged

Fix WPA3/SAE attack correctness, honesty, and dead flags#526
kimocoder merged 1 commit into
masterfrom
wpa3-implementation-fixes

Conversation

@kimocoder

Copy link
Copy Markdown
Owner

Audit of the WPA3-SAE subsystem surfaced several issues where the code either misled the user or didn't do what its flags/docs promised.

Honest success semantics (wpa3.py, model/sae_handshake.py):

  • A captured SAE handshake is NOT offline-crackable (WPA3-SAE/Dragonfly is a PAKE that resists dictionary attacks; there is no hashcat mode that recovers a PSK from captured SAE frames). Stop reporting a bare SAE capture as a green "success"; print an explicit caveat explaining that offline recovery is only feasible via transition-mode downgrade or a Dragonblood timing partition. The capture is still saved.
  • SAE completeness now requires BOTH an SAE Commit (auth seq 1) and a Confirm (auth seq 2); previously any >=2 SAE auth frames (e.g. two retransmitted commits) falsely counted as a complete handshake.

Dead/inconsistent CLI flags:

  • --no-downgrade and --force-sae were parsed and documented but never consulted. Gate the downgrade strategy on them (can_use_downgrade) and skip the transition-mode WPA2 fallback attacks for --force-sae.
  • --wpa3-only only duplicated --wpa3's discovery filter. Enforce it at attack time: skip any non-WPA3 target (so WPA2-only/WEP/OWE are never attacked), while still attacking transition-mode APs.
  • Downgrade now honours --wpa3-timeout (was hardcoded to 30s), and the previously-unreachable "no clients" warning now fires partway through the (configurable) window.

Reliability:

  • Dragonblood live timing: derive the commit->response latency from wpa_supplicant's own microsecond timestamps (-t) instead of Python readline/poll-sleep times, which injected tens of ms of jitter and swamped the microsecond-scale signal. Return no sample (not a noisy one) when timestamps are unavailable.
  • hcxdumptool min version bumped 6.0.0 -> 7.0.0 to match the 7.x-only capture syntax the wrapper emits (-w, --rds=1, band-suffix channels).
  • has_captured_data() is now meaningful (data beyond the pcapng header, via a baseline recorded at start) and a new has_new_data() lets the capture loops skip re-validation when the file hasn't grown.

Audit of the WPA3-SAE subsystem surfaced several issues where the code
either misled the user or didn't do what its flags/docs promised.

Honest success semantics (wpa3.py, model/sae_handshake.py):
- A captured SAE handshake is NOT offline-crackable (WPA3-SAE/Dragonfly
  is a PAKE that resists dictionary attacks; there is no hashcat mode that
  recovers a PSK from captured SAE frames). Stop reporting a bare SAE
  capture as a green "success"; print an explicit caveat explaining that
  offline recovery is only feasible via transition-mode downgrade or a
  Dragonblood timing partition. The capture is still saved.
- SAE completeness now requires BOTH an SAE Commit (auth seq 1) and a
  Confirm (auth seq 2); previously any >=2 SAE auth frames (e.g. two
  retransmitted commits) falsely counted as a complete handshake.

Dead/inconsistent CLI flags:
- --no-downgrade and --force-sae were parsed and documented but never
  consulted. Gate the downgrade strategy on them (can_use_downgrade) and
  skip the transition-mode WPA2 fallback attacks for --force-sae.
- --wpa3-only only duplicated --wpa3's discovery filter. Enforce it at
  attack time: skip any non-WPA3 target (so WPA2-only/WEP/OWE are never
  attacked), while still attacking transition-mode APs.
- Downgrade now honours --wpa3-timeout (was hardcoded to 30s), and the
  previously-unreachable "no clients" warning now fires partway through
  the (configurable) window.

Reliability:
- Dragonblood live timing: derive the commit->response latency from
  wpa_supplicant's own microsecond timestamps (-t) instead of Python
  readline/poll-sleep times, which injected tens of ms of jitter and
  swamped the microsecond-scale signal. Return no sample (not a noisy
  one) when timestamps are unavailable.
- hcxdumptool min version bumped 6.0.0 -> 7.0.0 to match the 7.x-only
  capture syntax the wrapper emits (-w, --rds=1, band-suffix channels).
- has_captured_data() is now meaningful (data beyond the pcapng header,
  via a baseline recorded at start) and a new has_new_data() lets the
  capture loops skip re-validation when the file hasn't grown.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 3, 2026 16:49
@kimocoder kimocoder merged commit a0f0690 into master Jun 3, 2026
9 of 10 checks passed
@kimocoder kimocoder deleted the wpa3-implementation-fixes branch June 3, 2026 16:50

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR tightens the WPA3-SAE attack subsystem’s correctness and user-facing honesty by (1) validating SAE handshakes more accurately, (2) enforcing previously-dead WPA3 CLI flags at attack time/strategy selection, and (3) improving reliability/performance of capture/timing loops (including more meaningful “new data” detection and reduced timing jitter).

Changes:

  • Make SAE handshake validation require both Commit (seq 1) and Confirm (seq 2), and add tests for the “commits-only” false-positive case.
  • Enforce WPA3-related flags in strategy/attack routing (--wpa3-only, --no-downgrade, --force-sae) and improve downgrade timeout/warnings to be configurable.
  • Improve reliability/performance: derive Dragonblood timing from wpa_supplicant’s -t timestamps; add has_new_data() to avoid expensive re-validation when capture files haven’t grown; bump hcxdumptool minimum version for the 7.x capture syntax.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
wifite/util/wpa3_tools.py Bumps hcxdumptool minimum version gate for WPA3 tool readiness checks.
wifite/util/dragonblood_timing.py Uses wpa_supplicant -t timestamps to reduce jitter in Dragonblood timing measurements.
wifite/tools/hcxdumptool.py Adds baseline/new-data tracking to distinguish header-only pcapng files and avoid repeated heavy validation.
wifite/model/sae_handshake.py Strengthens SAE completeness validation to require both auth seq 1 and 2.
wifite/attack/wpa3.py Makes SAE “success” messaging more honest; wires has_new_data() into capture loops; makes downgrade timeout configurable and warns sooner about no clients.
wifite/attack/wpa3_strategy.py Gates downgrade strategy based on --no-downgrade / --force-sae.
wifite/attack/all.py Enforces --wpa3-only at attack time and respects --force-sae to skip WPA2 fallbacks on transition mode.
tests/test_sae_handshake.py Updates/adds tests matching the stricter SAE validation semantics.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 381 to 386
with contextlib.suppress(Exception):
process.interrupt()
time.sleep(0.3)
if process.poll() is None:
process.kill()

Comment on lines +142 to +149
# Record the header-only size now that the file exists, so subsequent
# data checks measure growth beyond the pcapng header rather than
# treating the always-present header as "captured data".
try:
self._baseline_size = os.path.getsize(self.output_file) \
if os.path.exists(self.output_file) else 0
except OSError:
self._baseline_size = 0
Comment thread wifite/attack/wpa3.py
Comment on lines +822 to +827
# Set timeout for the downgrade attempt. Honour --wpa3-timeout when
# the user set it; otherwise keep a short 30s window — the downgrade
# is a fast first attempt that falls back to SAE capture, so it
# shouldn't occupy the full wpa_attack_timeout (300s) by default.
timeout_value = Configuration.wpa3_attack_timeout or 30
downgrade_timeout = Timer(timeout_value)
Comment thread wifite/attack/all.py
Comment on lines +104 to +108
if Configuration.wpa3_only:
is_wpa3_target = target.primary_encryption == 'WPA3' or (
hasattr(target, 'wpa3_info') and target.wpa3_info and
getattr(target.wpa3_info, 'has_wpa3', False))
if not is_wpa3_target:
Comment thread wifite/util/wpa3_tools.py
Comment on lines 31 to 37
# Minimum required versions
# hcxdumptool must be 7.x: the HcxDumpTool wrapper emits 7.x-only capture
# syntax (-w output, --rds=1, channel band-suffixes like 1a/6a), so a 6.x
# binary would pass an older gate and then fail at runtime.
MIN_VERSIONS = {
'hcxdumptool': (6, 0, 0),
'hcxdumptool': (7, 0, 0),
'hcxpcapngtool': (1, 0, 0),
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants