Lesson 20 / 20
Wireless Network Auditing
A fictional branch building's coverage map is calculated on a one-meter grid: the portion of the connectable area that spills outside the building is one thousand eight hundred thirty-eight square meters, the area where frames can only be heard is twenty-nine thousand six hundred twenty-two square meters, twelve times the inside area. Lowering transmit power zeroes the outside connectable area but does not close the audible area; an unauthorized-device scan finds three of six out-of-inventory sources in two hours, one of which is not found even with continuous monitoring.
Published Updated
In this lesson
- Measures, with a path-loss calculation, the area where the signal spills outside the building boundary on a coverage map
- Calculates together what lowering transmit power gains on the outside surface and what it costs in indoor coverage
- Counts what an unauthorized-device scan finds and does not find, along with the reason code
- Gathers the twenty lessons' unverified claims, verified claims, and cost of verification into a single table
Contents
The previous lesson separated out three paths that protection cannot close, and what the three had in common was that none of them was about verifying a claim. Jamming, making the medium appear busy, and impersonating pre-connection frames can all be done anywhere the signal reaches. Every defense in this course assumed a boundary; in the wireless layer, that boundary is not a rule, it is a surface.
This lesson calculates that surface. First it measures how far the signal spills outside the building wall, then it counts what an unauthorized-device scan finds and does not find on that surface. Scanning and listening outside one’s own network, without written authorization and a defined scope, is both illegal and unprofessional; all the measurements below are done as a model, over a fictional inventory.
- WS24. The fictional branch building is sixty-two by thirty-eight meters and carries four access points. Positions are a model decision; no real building, real location, or real measurement is written.
- WS25. The path-loss calculation is real; the exponents, the outside-wall loss, and the thresholds are model values and would be derived by measurement in a real building. For points outside the building, a single wall crossing is assumed. The grid has a one-meter step and includes the building area’s edges.
- WS26. Two thresholds are separated: the power at which a connection can be established, and the power at which a signal can only be heard. The second is the level at which frames can be received but a connection cannot be established.
- WS27. In the scanning model, a source is found only if it is on a scanned channel, the listening window is longer than the source’s transmission interval, and it is on during the scan.
The Physical Surface on the Coverage Map
Coverage is not a management preference, it is a path-loss calculation. The building and its surroundings are divided into a one-meter grid, the power received from the strongest access point is calculated in each cell, and classified against the two thresholds.
// coverage.mjs — a fictional branch building's coverage map (model). No real location or real // measurement is written; the path-loss calculation is real, the environment constants are model values. const BUILDING = { x1: 62, y1: 38 }, AP = [[15, 10], [47, 10], [15, 28], [47, 28]]; const IN_EXP = 3.5, OUT_EXP = 2.6, WALL = 8; // path-loss exponent and outside-wall loss (dB) const FSPL1 = 20 * Math.log10((4 * Math.PI * 5.2e9) / 2.998e8); // 1 m reference loss const CONNECT = -70, HEAR = -85, LAPTOP = 210; // dBm thresholds and laptops inside the building const inside = (x, y) => x >= 0 && x <= BUILDING.x1 && y >= 0 && y <= BUILDING.y1; const received = (x, y, eirp) => Math.max(...AP.map(([ax, ay]) => { const d = Math.max(1, Math.hypot(x - ax, y - ay)); return eirp - (inside(x, y) ? FSPL1 + 10 * IN_EXP * Math.log10(d) : FSPL1 + 10 * OUT_EXP * Math.log10(d) + WALL); })); function coverageMap(eirp) { // grid: each cell counts as 1 square meter const h = { inside: 0, covered: 0, outConnect: 0, outHear: 0, farthest: 0 }; for (let x = -120; x <= 182; x++) for (let y = -120; y <= 158; y++) { const g = received(x, y, eirp); if (inside(x, y)) { h.inside++; if (g > CONNECT) h.covered++; continue; } if (g > CONNECT) h.outConnect++; if (g > HEAR) { h.outHear++; h.farthest = Math.max(h.farthest, -x, x - BUILDING.x1, -y, y - BUILDING.y1); } } return h; } const E = [11, 13, 12, 16, 14, 11, 15]; const row = (a) => a.map((d, i) => String(d)[i ? 'padStart' : 'padEnd'](E[i])).join(''); console.log(`building ${BUILDING.x1} x ${BUILDING.y1} m, access point ${AP.length}, 1 m loss ` + `${FSPL1.toFixed(1)} dB, threshold ${CONNECT} / ${HEAR} dBm`); console.log(row(['transmit', 'in covered', 'in gap', 'out connectable', 'out audible', 'farthest m', 'devices cut'])); for (const eirp of [20, 17, 14, 11, 8]) { const h = coverageMap(eirp); console.log(row([`${eirp} dBm`, h.covered, h.inside - h.covered, h.outConnect, h.outHear, h.farthest, Math.round((LAPTOP * (h.inside - h.covered)) / h.inside)])); } const t = coverageMap(20); console.log(`\nout audible area is ${(t.outHear / t.inside).toFixed(1)} times the inside area; at ` + `8 dBm out connectable 0, out audible still ${coverageMap(8).outHear} m2`);
building 62 x 38 m, access point 4, 1 m loss 46.8 dB, threshold -70 / -85 dBm transmit in covered in gap out connectable out audible farthest m devices cut 20 dBm 2416 41 1838 29622 75 4 17 dBm 1998 459 612 18148 55 39 14 dBm 1554 903 124 11046 40 77 11 dBm 1158 1299 0 6558 28 111 8 dBm 740 1717 0 3702 19 147 out audible area is 12.1 times the inside area; at 8 dBm out connectable 0, out audible still 3702 m2
The first row gives this lesson’s central number. At twenty dBm transmit power, two thousand four hundred sixteen square meters are covered inside the building, leaving a gap of forty-one square meters. At the same time, outside the building, a connection can be established over an area of one thousand eight hundred thirty-eight square meters, and frames can be heard over an area of twenty-nine thousand six hundred twenty-two square meters. The second number is twelve times the inside area and extends seventy-five meters past the building wall.
No rule can be written at any point in this zone. All the paths measured by the third and fourth lessons live here: an evil twin, or a source impersonating pre-connection frames, can be positioned anywhere within the twenty-nine-thousand-square-meter area.
Lowering transmit power is the first defense that comes to mind, and the table counts its cost. At seventeen dBm, the outside usable area drops to six hundred twelve; in exchange, the inside coverage gap rises from forty-one to four hundred fifty-nine square meters, and thirty-nine laptops are left outside. At eleven dBm, the outside usable area reaches zero, the inside gap is one thousand two hundred ninety-nine square meters, and the number of affected devices is one hundred eleven.
The last row gives the real conclusion. Even though the outside usable area is zero at eight dBm, the outside audible area is still three thousand seven hundred two square meters. Since transmit power cannot be reduced to zero, this number cannot be zeroed either: the connectable surface can be closed, the audible surface cannot be closed. The physical boundary is not a defense; at most, it is a narrowing.
Lowering power also has a side effect that does not appear in the table: since a client picks the strongest-signaled candidate among those announcing the same name, weakening one’s own access points makes it easier for an evil twin to win that comparison.
What the Scan Finds and Does Not Find
The second measurement asks who is present on the same surface. A scan listens over a list of channels and compares the sources it hears against the inventory.
// scan.mjs — what an unauthorized-device scan finds and does not find (model). The scan runs // only over a fictional inventory; no operation targets a real network. // [name, channel, broadcast interval (s), always on?, in inventory?] const SOURCE = [ ['meter endpoint', 6, 900, true, true], ['field terminal', 36, 5, true, true], ['branch laptop', 44, 2, true, true], ['panel display', 36, 30, true, true], ['barcode printer', 6, 600, true, true], ['maintenance laptop', 149, 2, true, true], ['personal access point', 11, 0.1, true, false], ['non-broadcasting access point', 157, 300, true, false], ['wireless bridge', 165, 1800, true, false], ['temporary evil twin', 44, 0.1, false, false], ['old-generation test access point', 1, 0.1, true, false], ['access point on an unscanned band', 100, 0.1, true, false], ]; const CHANNEL = [1, 6, 11, 36, 40, 44, 48, 149, 153, 157, 161, 165]; const PLAN = [['8 channels, 20 minutes', 8, 1200], ['12 channels, 20 minutes', 12, 1200], ['12 channels, 2 hours', 12, 7200], ['12 channels, continuous', 12, 86400]]; const seen = ([, channel, interval, always], [, channelCount, duration]) => !CHANNEL.slice(0, channelCount).includes(channel) ? 'out of channel range' : duration / channelCount < interval ? 'listening window too short' : (!always && duration < 86400) ? 'off during the scan' : 'found'; const inInventory = SOURCE.filter((k) => k[4]), outInventory = SOURCE.filter((k) => !k[4]); const E = [25, 14, 17, 18, 18]; const row = (a) => a.map((d, i) => String(d)[i ? 'padStart' : 'padEnd'](E[i])).join(''); console.log(`source ${SOURCE.length} (in inventory ${inInventory.length}, out of inventory ` + `${outInventory.length}), scannable channels ${CHANNEL.length}`); console.log(row(['scan plan', 'channel/time', 'inventory item', 'out of inventory', 'per channel (s)'])); for (const p of PLAN) { const b = (l) => l.filter((k) => seen(k, p) === 'found').length; console.log(row([p[0], `${p[1]}/${p[2]}s`, `${b(inInventory)}/${inInventory.length}`, `${b(outInventory)}/${outInventory.length}`, (p[2] / p[1]).toFixed(0)])); } const A = [35, 14, 28, 28]; const row2 = (a) => a.map((d, i) => String(d)[i ? 'padStart' : 'padEnd'](A[i])).join(''); console.log('\n' + row2(['source', 'in inventory', '2-hour scan', 'continuous monitoring'])); for (const k of SOURCE) console.log(row2([k[0], k[4] ? 'yes' : 'no', seen(k, PLAN[2]), seen(k, PLAN[3])]));
source 12 (in inventory 6, out of inventory 6), scannable channels 12 scan plan channel/time inventory item out of inventory per channel (s) 8 channels, 20 minutes 8/1200s 4/6 2/6 150 12 channels, 20 minutes 12/1200s 4/6 2/6 100 12 channels, 2 hours 12/7200s 5/6 3/6 600 12 channels, continuous 12/86400s 6/6 5/6 7200 source in inventory 2-hour scan continuous monitoring meter endpoint yes listening window too short found field terminal yes found found branch laptop yes found found panel display yes found found barcode printer yes found found maintenance laptop yes found found personal access point no found found non-broadcasting access point no found found wireless bridge no listening window too short found temporary evil twin no off during the scan found old-generation test access point no found found access point on an unscanned band no out of channel range out of channel range
The first table shows what scan duration buys. A twenty-minute scan, whether it covers eight channels or twelve, finds four of the six inventory items and two of the six out-of-inventory sources: increasing the channel count alone gains nothing, because with the total duration fixed, the per-channel listening window drops from one hundred fifty seconds to one hundred. In two hours, the numbers rise to five and three. What matters is the listening window: a scan that listens for six hundred seconds per channel cannot hear a source that speaks once every nine hundred seconds.
The first row of the second table is this lesson’s real finding. The organization’s own four thousand one hundred meter endpoints do not show up in the two-hour scan — not an unauthorized device, but the most populous item in the inventory. A scan reporting that it “matches the inventory” does not mean the inventory has been verified; it only means the items the scan heard match.
For two of the reasons a source is not found, the solution is time: continuous monitoring catches the meter endpoint, the wireless bridge, and the temporary evil twin. The third is different — a source that stays out of channel range is not found even with continuous monitoring, because the scan’s scope is the channel list, not the duration.
The same boundary ties back to the map in the first section: a scan only covers where the scanner can hear. The two measurements give the same surface — the area where the signal spills out is both the vulnerable zone and the scan’s blind spot.
Summary
- On the coverage map, a connection can be established over 1,838 square meters outside the building, and frames can be heard over 29,622 square meters: the second figure is 12.1 times the inside area and reaches 75 meters past the wall.
- Lowering transmit power zeroes the outside usable area at 11 dBm; the cost is a 1,299-square- meter coverage gap and 111 devices. The outside audible area never reaches zero at any power level: 3,702 square meters even at 8 dBm.
- A twenty-minute scan finds 4 of the 6 inventory items; increasing the channel count alone gains nothing, since it shortens the per-channel listening window, and the organization’s own 4,100 meter endpoints do not show up in a two-hour scan.
- 3 of the 6 out-of-inventory sources are found in two hours, 5 in continuous monitoring; a source operating on an unscanned band is not found under any plan.
Course Wrap-Up
| Lesson | Unverified claim | What the defense verifies | Cost of verification |
|---|---|---|---|
| Layer models and attack surface | 18 claims, 0 proof | 5 layers 11 claims | 4 extra round trips, 25 manual items |
| Ports and services | 49 acceptance points, 21 unproven | narrowing brings it down to 27 points | 4 periodic flows are cut |
| Address resolution attacks | 6 poisoned records among 26 responses | three defenses rescue 6 records | 16 extra round trips, 4 rejected responses |
| Name resolution attacks | 7 poisoned names, 38 services | signed verification 3 names, 14 services | strict mode stops 47 services |
| Address assignment risks | 70 claims across 14 endpoints, 35 forged | pool and static separation 12 endpoints | 3 manual items, 2 endpoints wrong |
| Denial of service attacks | 4,096 sockets fill in 1.02 seconds | handshake proof zeroes the socket | 15% of legitimate traffic is eliminated |
| On-path attacks | 16 of 36 steps read the content | endpoint verification and root pinning 16 steps | 84-item list, 7 cut flows |
| Replay and spoofing attacks | 5 of 10 types change state via replay | three proofs 3 full, 5 partial types | 503 rejected messages, 224 state items |
| Firewall generations | 40 of 48 claims unproven | the application-aware generation 45 claims | 94,112 state records, 6 resolvers |
| Network segmentation and the DMZ | 210 transitive items | segmentation brings it down to 25 items | 15 rule lines, 2 cut flows |
| Proxy and jump servers | 99.5% of connections unrecorded | subject identity on 3,118 connections | 210,502 connections in a single outage |
| Intrusion detection and prevention | 3 of 14 classes invisible from the network | two sensors 6 of 7 classes | prevention cuts 5,214 legitimate events |
| Honeypots and sinkholes | 29.8% false positive in the signature scheme | deception 594 alerts, 1.2% wrong | 22,690 connections unrecorded at the sinkhole |
| Virtual private networks | the remote endpoint directly accesses 136 items | a separate zone brings it down to 16 items | 8 hours of proof, 97,100 unaudited connections |
| Access control lists | 2 order-sensitive pairs among 10 rules | 15 of 16 flows in the order written | in reverse order 16 flows are rejected |
| Wireless encryption generations | 10 claims, 0 proof in the old generation | the simultaneous-authentication generation 7 claims | 4,321 devices are left out |
| Authentication methods | 6 of 7 claims unproven | enterprise mode and a fixed root 7 claims | 7 infrastructure items, 4,138 devices |
| Rogue access points | 6 signals 0 proof, 4 open paths | three defenses zero out the open path | 976 manual approvals a day |
| Deauthentication | 11 of 12 frame types unproven | protection 3 frames, 3 paths | 5 paths open, protection made mandatory |
| Wireless network auditing | outside audible area is 12.1 times the inside area | at 11 dBm outside usable area 0 | 1,299 m² gap, 111 devices |
The second column writes this course’s rule: network security is not a checklist of boxes, it is how many of the claims a message carries can be proven; every claim that cannot be proven is a path. No defense was measured as “installed and done”; each one was run against a set of claims.
The third column gathers into four groups. Extra round trips and key items are the cost verification writes into the protocol; legitimate work cut off is the cost written into the work itself; devices left out is the cost written into the inventory, and in the wireless lessons it is measured in the thousands; manually managed items are both a maintenance load and a count of places that can be misconfigured.
In none of the twenty lessons did the number of open claims fall to zero, and the claims that remained were of the same kind: who a subject is, whether a frame was sent before the connection was established, whether a signal can be heard outside the wall. Underneath this entire measurement, there is also an assumption that was never asked. Across the twenty lessons, calling a claim “verifiable” meant that a proof could be tested: a signature held up, a shared secret was known, an identity was tied to a trust root. What that proof rested on was never asked. Where did the key that verifies the signature come from, who holds the shared secret, why is the trust root trusted? M24/K04 Identity, Access and Cryptography begins with exactly this question: what does a claim’s provability rest on, who holds the key, and where does trust begin?
To keep your progress and take notes, Log in
My notes
Log in to take notes.