Chapter 2 — Networks and internet services
Lesson map
Lesson 02 published. Map, example, EX004.
flowchart TD
N0["Learning outcomes"]
N1["2.1 Addresses, prefixes and ownership"]
N2["2.2 Exclusions inside ranges"]
N3["2.3 Names versus numbers"]
N4["2.4 Typical exposed services"]
N5["Lab A — scope checker"]
N6["Synthesis"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6
N6 --> EX["Worked example"]
EX --> Q["Exercise EX004"]
Logical drawing
flowchart LR
N0["Learning outcomes"]
N1["2.1 Addresses, prefixes and ownership"]
N2["2.2 Exclusions inside ranges"]
N3["2.3 Names versus numbers"]
N4["2.4 Typical exposed services"]
N5["Lab A — scope checker"]
N6["Synthesis"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> Q["EX004"]
[Learning outcomes]
|
v
[2.1 Addresses, prefixes and ownership]
|
v
[2.2 Exclusions inside ranges]
|
v
[2.3 Names versus numbers]
|
v
[2.4 Typical exposed services]
|
v
[Lab A — scope checker]
|
v
[Synthesis]
|
v
[Worked example] --> [Exercise EX004]
Learning outcomes
You will (1) read address ranges in CIDR notation; (2) separate in-scope, excluded and out-of-scope addresses with a small script; (3) explain why DNS names and IP addresses can drift apart during an engagement; (4) list the internet services a transit operator typically exposes.
2.1 Addresses, prefixes and ownership
An IPv4 network such as 192.0.2.0/25 covers 128 addresses from .0 to .127. The prefix length tells you how many leading bits are fixed. Scope documents almost always list prefixes rather than single hosts, so a technologist must be able to test membership quickly and without mental arithmetic errors. Ownership is separate from membership: a prefix announced by a cloud provider may contain addresses that belong to thousands of customers.
lab_scope prints 192.0.2.10 and 198.51.100.20 as IN-SCOPE inside TRT's documented /25 teaching ranges. Priya teaches prefix length with those RFC 5737 addresses so learners never point tools at live transit networks. Ownership of each prefix is written beside the CIDR before Northpoint receives the list.
2.2 Exclusions inside ranges
Real scopes often carve holes. TRT's fare-payment segment, 192.0.2.64/27, sits inside the larger in-scope block because of how the network was historically numbered. A checker must evaluate exclusions first; otherwise the broader inclusion wins and a forbidden system is touched.
The fare carve-out 192.0.2.70 EXCLUDED sits inside a larger block on purpose. Priya's checker must honour holes, not only outer prefixes; otherwise ENG-712 would green-light fare-payment hosts. She demos the EXCLUDED line in kickoff so Northpoint sees the hole is intentional, and she fails any scope sheet that lists only outer CIDRs without the fare carve-out written beside them.
2.3 Names versus numbers
DNS records change. A hostname approved on Monday may resolve to a different address on Thursday after a migration, perhaps to a shared content-delivery address. Good practice is to approve both the name and the address, resolve again before each session, and stop if they diverge.
After a CDN migration the staff-portal name resolved outside the approved addresses. Priya paused ENG-712, re-ran lab_scope, and waited for a written white-team update. Names alone never authorize; numbers on the signed list do. While the session is held, Priya screenshots the old and new resolutions into evidence with a HOLD note, not a guess.
2.4 Typical exposed services
A transit operator usually publishes a passenger website, a timetable or real-time API, a staff remote-access gateway, mail, and sometimes a vendor support portal. ATT&CK catalogues the adversary use of remote-access gateways as T1133 External Remote Services, which is why such gateways are commonly prioritised in scope discussions.
TRT's ordinary exposed face is the passenger site, timetable API, staff VPN and mail — not fare validators. Method statements for ENG-712 list those services explicitly. Anything that looks like fare.trt.example is refused even if it answers on an interesting port.
Lab A — scope checker
"""Lab A (ch 02): classify synthetic targets against a written scope. Documentation ranges only."""
import ipaddress
IN_SCOPE = [ipaddress.ip_network(n) for n in ("192.0.2.0/25", "198.51.100.16/28")]
EXCLUDED = [ipaddress.ip_network("192.0.2.64/27")] # fare-payment segment, carved out by the client
targets = ["192.0.2.10", "192.0.2.70", "192.0.2.200", "198.51.100.20", "203.0.113.5"]
def verdict(addr):
ip = ipaddress.ip_address(addr)
if any(ip in n for n in EXCLUDED):
return "EXCLUDED"
if any(ip in n for n in IN_SCOPE):
return "IN-SCOPE"
return "OUT-OF-SCOPE"
for t in targets:
print(f"{t:15} {verdict(t)}")
print("testable:", sum(verdict(t) == "IN-SCOPE" for t in targets), "of", len(targets))
Run with python3 lab_scope.py. Verified output:
192.0.2.10 IN-SCOPE
192.0.2.70 EXCLUDED
192.0.2.200 OUT-OF-SCOPE
198.51.100.20 IN-SCOPE
203.0.113.5 OUT-OF-SCOPE
testable: 2 of 5
Worked example
Five candidate addresses reach Priya from Northpoint's planning sheet. The script marks 192.0.2.70 EXCLUDED because it falls in the fare-payment carve-out, and 192.0.2.200 OUT-OF-SCOPE because a /25 ends at .127. Only two of five are testable. She returns the sheet with those verdicts before any session is scheduled.
Synthetic case. Addresses use RFC 5737 documentation ranges; TRT's network layout is fictional.
Errors and limits
Checking inclusions before exclusions, trusting yesterday's DNS answer, and confusing "the client uses this address" with "the client owns it" are the classic failures. The script checks arithmetic, not legal authority.
Exercises
- EX004 — Range boundary. Using the lab output, why is 192.0.2.200 out of scope even though it starts with 192.0.2? Rubric: 3 = /25 covers .0–.127, so .200 is outside; 2 = says outside without reason; 1 = says in scope; 0 = none.
- EX005 — Ordering bug. Suppose a colleague rewrites the function to test IN_SCOPE before EXCLUDED. What would 192.0.2.70 return, and why is that dangerous? Rubric: 3 = IN-SCOPE; fare-payment system would be tested; 2 = wrong verdict noted; 1 = no change; 0 = none.
- EX006 — Drifting hostname. The approved name portal.trt.example now resolves to 203.0.113.5. What should Priya do? Rubric: 3 = stop, the address is out of scope, confirm with owner and re-approve before testing; 2 = stop only; 1 = test the name anyway; 0 = none.
Synthesis
Membership is arithmetic, exclusions come first, and every name is re-resolved and re-checked before a session starts.
Continue studying — chapter 02 of 30
← Chapter 01 (draft) · Course chapter index · Chapter 03 (draft) →