Foundations of Ethical Security Testing with Python: A Beginner's Laboratory Guide
Chapter 8 of 11 · updated Jul 08, 2026
Wireless and Social Attack Vectors: Expanding the Threat Model
Wireless and Social Attack Vectors: Expanding the Threat Model
So far in Lab Wintermute we've mapped the wired segment—Kali at 192.0.2.10 probing Metasploitable2 at 192.0.2.20 and DVWA at 192.0.2.30. But real networks bleed into wireless, and the most dangerous attacks rarely touch the network stack at all. This page extends our threat model beyond Ethernet frames and TCP ports. I want you to think in decisions: given what you observe, what vector matters, what do you do, and why.
Decision Framework: If You See X, Do Y
| Condition you observe | Attack vector to assess | Immediate defensive action | Rationale |
|---|---|---|---|
| WiFi network using WEP or no encryption | Wireless eavesdropping / unauthorized association | Disable WEP; minimum WPA2-Enterprise with certificate validation | WEP's key stream is recoverable from captured traffic (check current literature for specifics); open networks expose all layer-3 traffic |
| WPA2-PSK with weak or shared password | Offline dictionary attack against PSK | Migrate to WPA3-Personal (SAE) or WPA2-Enterprise; enforce 16+ character unique PSKs | PSK mode derives session keys from the password; capture the 4-way handshake and the password becomes brute-forceable offline |
| WPA3-Personal or Wi-Fi Enhanced Open available but not enabled in client config | Downgrade attack to weaker protocol | Verify CONFIG_SAE=y and CONFIG_OWE=y in wpa_supplicant build; prevent manual addition of weak networks | Per the WFA spec, if these aren't compiled in, users cannot connect to these network types even when available—this creates shadow downgrade paths |
| Enterprise network with certificate warnings ignored by users | Evil twin / rogue AP with captive portal | Deploy WPA3-Enterprise (CONFIG_SUITEB192/CONFIG_SUITEB); certificate pinning via MDM; user training on warning dialogs | Users trained to click through warnings defeat the cryptography |
| Email with urgency, authority, or fear triggers; mismatched sender domain | Phishing / pretexting | SPF/DKIM/DMARC enforcement; user reporting pipeline; simulated phishing program with written authorization | Technical filters catch maybe 99%; that 1% at scale is catastrophic, and the human is the last control |
| Unattended USB drive or "lost" credential in parking lot | Baiting / quid pro quo | USB port disablement via GPO; physical security awareness; honey tokens that alert when used | The attacker offers something (a "free" drive, "helpful" IT support) to extract access |
| Password hashes exfiltrated to attacker-controlled system | Offline cracking (Hashcat, John) | bcrypt/Argon2id with work factor tuning; unique salts; MFA everywhere | Offline attacks run at GPU speed without rate limits; online attacks are throttled by the target system |
| Account lockout not implemented; predictable usernames | Online brute force / password spraying | Implement progressive lockout; monitor for distributed low-volume attempts; deploy MFA | Attackers spray common passwords across many accounts to avoid triggering per-account lockouts |
WiFi Security Evolution: What the Lab Teaches
Lab Wintermute's VirtualBox NAT network doesn't natively simulate WiFi, but you can attach a USB WiFi adapter in monitor mode to the Kali VM for authorized spectrum analysis on your own isolated access point. Here's what you'll observe across generations:
WEP — If you find legacy gear still running this, the lesson is historical: the RC4 key stream exhibits statistical biases that accumulate across captured frames. I won't detail the crack here because the technique is well-documented externally and the point is defensive: inventory your hardware, flag anything older than WPA2, and replace it.
WPA/WPA2 — The critical fork is PSK versus Enterprise. PSK (Pre-Shared Key, one password for all users) means anyone with the password can decrypt traffic if they captured the 4-way handshake. Enterprise uses RADIUS (a central authentication server issuing per-session keys), so compromise of one user's credentials doesn't expose the network. In the lab, if you configure a test AP with WPA2-PSK "password123", capture the handshake with airodump-ng, and run a dictionary attack, you'll recover the PSK. Same AP with WPA2-Enterprise and certificate validation? The handshake doesn't yield a crackable secret.
WPA3 — Two parts matter for your defensive posture. WPA3-Personal replaces PSK with SAE (Simultaneous Authentication of Equals), which uses a zero-knowledge proof: even capturing the exchange doesn't let you brute-force the password offline. Wi-Fi Enhanced Open (OWE) encrypts public networks without authentication, eliminating the "open WiFi = exposed traffic" problem. Check your wpa_supplicant build: CONFIG_SAE=y, CONFIG_OWE=y, and for Enterprise CONFIG_SUITEB192/CONFIG_SUITEB must be enabled or these modes simply aren't available to users.
⚠️ Authorized, defensive use only. Spectrum analysis and handshake capture require your own hardware on your own spectrum. Unauthorized interception of third-party wireless traffic violates laws in most jurisdictions regardless of encryption status.
Python for Wireless: Scapy and 802.11 Basics
Scapy 2.7.1 (July 2026 documentation release) handles 802.11 frames through layer composition. The / operator stacks layers: RadioTap() / Dot11() builds a frame with the radiotap header (signal metadata) and the 802.11 MAC header. In monitor mode, your interface captures management frames—beacons, probes, associations—that reveal network presence even when SSID broadcast is suppressed.
Here's a minimal passive discovery concept. You won't run this against Wintermute's wired segment; you'd run it against your authorized lab access point:
from scapy.all import * def ssid_sniff(pkt): # Dot11Beacon = network announcement; Dot11ProbeResp = response to client probe if pkt.haslayer(Dot11Beacon) or pkt.haslayer(Dot11ProbeResp): ssid = pkt[Dot11Elt].info.decode(errors='replace') bssid = pkt[Dot11].addr3 channel = ord(pkt[Dot11Elt:3].info) if pkt.haslayer(Dot11Elt) else '?' # hide_defaults() strips fields matching defaults for cleaner display print(f"SSID: {ssid} | BSSID: {bssid} | Channel: {channel}") # sniff(iface="wlan0mon", prn=ssid_sniff, count=100)
# ^ Uncomment only when wlan0mon is your authorized monitor-mode interface
In plain terms: This listens for network announcements and extracts the name, hardware address, and channel. The errors='replace' handles malformed SSIDs that would otherwise crash your script—a real-world fragility I hit early on.
Monitor mode means the interface captures all raw 802.11 traffic, not just frames addressed to it. Your adapter must support this; many cheap chipsets don't. Check with iw list for "monitor" in supported interface modes.
Social Engineering: The Highest-Success Vector
If I had to bet on one attack category succeeding in any given organization, it's social engineering. Not because the technology is weak, but because the target helps you. Technical controls—filters, MFA, DLP—assume a motivated attacker pushing against defenses. Social engineering makes the defenses irrelevant by walking through the door the target opens.
Pretexting: Fabricating a scenario to extract information. "I'm from IT, we're migrating mail servers, I need to verify your password." The pretext leverages organizational trust patterns.
Baiting: Leaving something attractive for the target to find. A USB labeled "Q4 Bonuses" in a parking lot. When plugged in, it autoruns or simply exploits the human curiosity that inspects contents.
Quid pro quo: Offering a service in exchange for access. "I can fix that slowness if you let me remote in." The attacker provides minimal actual help to establish reciprocity obligation.
Why technical controls fail: email filters catch known-bad indicators, but a live phone call bypasses every filter. MFA stops credential theft, but not session hijacking if the attacker persuades the user to approve a push notification. The defense is layered: technical (DMARC enforcement, link protection), procedural (verification callbacks for sensitive requests), and cultural (reporting without punishment, simulated phishing with written authorization only).
⚠️ Authorized, defensive use only. Phishing simulations require explicit scope, opt-out mechanisms, and post-click education. Un authorized simulation is indistinguishable from attack and may violate anti-phishing laws or employment agreements.
Authorized simulation infrastructure: dedicated domain (not your production domain), isolated mail relay, landing pages that immediately educate, and metrics tied to reporting rate improvement—not punishment. Never use real credentials harvested in simulation; the data is toxic liability.
Password Cracking: From Hashes to Understanding
In Lab Wintermute, suppose you've extracted hashes from 192.0.2.20 for offline analysis in your controlled environment. (How? Covered earlier—sufficient to say, authorized access to a system you own yields hash storage for defensive study.) The pedagogical question is: what makes a hash crackable?
Python's hashlib lets you explore this directly. It's built into the standard library—no installation needed—and provides constructors for each algorithm type:
import hashlib # Guaranteed algorithms per current Python docs; verify with hashlib.algorithms_guaranteed
# sha256, blake2b, md5, etc. def compare_speeds(): import time password = b"lab_test_password_2024" # MD5: fast, broken for collision resistance, terrible for password storage start = time.perf_counter() for _ in range(100000): hashlib.md5(password).hexdigest() md5_time = time.perf_counter() - start # bcrypt not in hashlib; use bcrypt module. SHA-256: still too fast for passwords start = time.perf_counter() for _ in range(100000): hashlib.sha256(password).hexdigest() sha256_time = time.perf_counter() - start # Blake2b: modern, fast for integrity, still wrong for passwords without key stretching start = time.perf_counter() for _ in range(100000): hashlib.blake2b(password).hexdigest() blake2b_time = time.perf_counter() - start print(f"MD5: {md5_time:.3f}s") print(f"SHA-256: {sha256_time:.3f}s") print(f"Blake2b: {blake2b_time:.3f}s") # illustrative output — verify on your target compare_speeds()
Why this matters: The hash object methods are update() (feed more data), digest() (raw bytes), hexdigest() (hex string). The GIL releases for large inputs (>2047 bytes), but for password-length data, this is irrelevant. What matters is work factor: how much CPU time verification takes. MD5 and SHA-256 are designed to be fast. Password hashes should be slow.
Hashcat 6.0.0+ modularizes hash modes via plugins; all 300+ legacy modes were refactored. For lab comparison against your Python experiments: capture a WPA2 handshake, extract the hash, and observe Hashcat's speed versus your Python implementation. The GPU parallelism isn't the lesson—the lesson is why WPA3-SAE and bcrypt exist. Slow the attacker by making each guess expensive.
| Hash type | Appropriate for passwords? | Why / why not | Lab observation |
|---|---|---|---|
| MD5 | No | Fast, no salt, parallelizable on GPU | Crack billions/second in Hashcat |
| SHA-256 | No | Fast, designed for integrity not resistance | Better than MD5, still wrong |
| NTLM | No (legacy Windows) | Fast, no salt | Common in Windows pentesting labs; demonstrates why Kerberos + MFA matters |
| bcrypt | Yes | Adaptive work factor, salt automatically | Tune cost factor so verification takes ~250ms |
| Argon2id | Yes | Memory-hard, resistant to GPU/ASIC | Current OWASP recommendation |
Offline versus online: offline attacks run at attacker hardware speed with no rate limit. Online attacks hit the target system's authentication endpoint; lockout policies and logging apply. The defensive asymmetry is stark—offline, the attacker has all advantages; online, you control the battlefield.
Applying the Framework to Wintermute
Your Lab Wintermute report, building toward the consolidated exercise on page 10, should now address:
- If the assessment scope includes wireless: Document SSID discovery methodology, handshake capture conditions, and why WPA3-SAE or Enterprise with certificate validation closes the offline crack path.
- If the assessment scope includes human factors: Document simulated phishing authorization boundaries, pretexting indicators users should verify, and why callback verification for sensitive requests outperforms technical filtering alone.
- If hash exposure is identified: Document hash type identification, why fast hashes constitute critical findings, and recommended migration to memory-hard algorithms with MFA enforcement.
The decision tree isn't just for attack selection. It's for defensive prioritization. The vector with lowest technical barrier and highest success rate—social engineering—deserves disproportionate training investment even though it doesn't appear in vulnerability scanners.