Fix WPA3/SAE attack correctness, honesty, and dead flags#526
Merged
Conversation
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>
There was a problem hiding this comment.
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
-ttimestamps; addhas_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 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 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 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), |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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):
Dead/inconsistent CLI flags:
Reliability: