Hitchhiker's Guide — Building a Security Research Range That Fails Closed
The operational companion to the Phase 00 WARMUP. The WARMUP explains why authorization, containment, and evidence are executable properties; this guide is the how — the concrete topology, firewall rules, commands, drills, and acceptance packet that turn a pile of VMs into a range where a mistake is contained, observable, reversible, and attributable. "I used a VM" is not a design.
Table of Contents
- The Operator's Goal
- Reference Zones and Topology
- The Default-Deny Policy
- Build Checklist
- Proving Containment — Concrete Commands
- Telemetry: Prove Every Source
- Attack Simulation Rules
- Operator and Tool Identity
- The Evidence Pipeline Exercise
- Failure Scenarios and Drills
- Teardown
- Failure Injection and the Readiness Packet
- References
The Operator's Goal
Build a range with four properties, each testable:
- Contained — a compromised guest cannot reach your LAN, the internet, the cloud metadata endpoint, the hypervisor, or the management plane.
- Observable — every zone ships telemetry you have verified with a real event.
- Reversible — snapshots and teardown return the range to a known-clean state.
- Attributable — every action ties to an operator, a tool/version, and a policy decision.
If you cannot demonstrate all four with commands and packet evidence, the range is not ready.
Reference Zones and Topology
┌────────────── management (10.10.0.0/24) ──────────────┐
│ Git · package mirror · evidence vault · orchestration │
└───────────────┬───────────────────────────────────────┘
│ (admin only, one direction)
┌──────────────┬────────────────┼────────────────┬───────────────┐
│ attacker │ victim │ mobile │ kubernetes │ → all zones ship logs →
│ 10.10.1.0/24 │ 10.10.2.0/24 │ 10.10.3.0/24 │ 10.10.4.0/24 │ telemetry 10.10.9.0/24
└──────────────┴────────────────┴────────────────┴───────────────┘
cloud: dedicated sandbox accounts/projects (federated, no stored keys)
ot-sim: synthetic protocols + process simulator only (10.10.5.0/24)
Use host-only / isolated virtual switches with no uplink to your real NIC; a dedicated lab router VM (e.g. OPNsense/VyOS) enforces inter-zone policy. The host firewall is the backstop if the switch is ever misconfigured.
The Default-Deny Policy
- management may administer lab zones; lab zones may not administer management;
- every lab zone ships logs to telemetry (one direction);
- attacker reaches only the declared victim service ports;
- victim/mobile/OT cannot initiate arbitrary internet or LAN connections;
- no vulnerable zone reaches host credentials, hypervisor sockets, shared clipboard, or home directories;
- cloud and package access goes through dedicated identities in explicit setup windows only.
Build Checklist
Host
- full-disk encryption; patched hypervisor;
- a dedicated lab directory with no production credentials;
- a separate browser profile and SSH config (
~/.ssh/configHost lab-*block, distinct keys); - password-manager entries scoped to lab accounts only;
- host firewall denies lab subnets → local LAN (example, Linux nftables):
# Drop anything from lab subnets headed to the home/corp LAN and metadata
nft add rule inet filter forward ip saddr 10.10.0.0/16 ip daddr 192.168.0.0/16 drop
nft add rule inet filter forward ip saddr 10.10.0.0/16 ip daddr 169.254.169.254 drop
Virtualization
- host-only / isolated switches; verify no guest has a bridged/NAT adapter it shouldn't;
- disable drag-and-drop, clipboard sharing, and shared folders for vulnerable/malware-adjacent
guests (
virsh/VirtualBox/VMware settings — confirm in the running guest, not just config); - snapshot clean states and label versions (
virsh snapshot-create-as victim clean-v1); - never expose hypervisor control sockets (
/var/run/libvirt/..., the Docker socket) to guests.
Cloud
- separate organization/account/project; MFA; no root/owner for daily use;
- budgets, quotas, region restrictions, teardown tags;
- short-lived federation (OIDC) instead of stored long-lived keys;
- organization-level audit logs stored outside workload-admin control.
Proving Containment — Concrete Commands
A diagram claims isolation; packets prove it. From every vulnerable/analysis host, run the negative-path tests and confirm each fails:
# From a victim/attacker guest — every one of these MUST fail (timeout/refused):
curl -m 3 http://192.168.1.1/ # home LAN gateway → must fail
curl -m 3 http://169.254.169.254/ # cloud metadata → must fail
curl -m 3 https://example.com/ # public egress → must fail (unless proxied)
nc -vz 10.10.0.10 22 # management SSH → must fail
# And the one ALLOWED path MUST succeed:
nc -vz 10.10.2.20 8080 # declared victim port → must succeed
Canary technique: place a synthetic secret on an unreachable host and confirm the vulnerable
guest cannot fetch it — denial then proves policy, not mere target absence. Capture with
tcpdump -i any -w proof.pcap running on the router so you have packet evidence the connection was
dropped, not just unanswered.
Re-run these after every reboot and snapshot restore — restored state can silently re-enable a NAT adapter.
Telemetry: Prove Every Source
Never assume a log source works; generate a benign event and query it back:
| Source | Generate benign event | Expected evidence |
|---|---|---|
| Linux | sudo -k; sudo -n true (denied) or read a 0600 root file | auditd/journal record w/ host+user |
| Windows | start a test service / process | Event Log + Sysmon (EID 1/7045) |
| Network | the denied curl above | router firewall log + Zeek conn.log |
| Kubernetes | kubectl apply a manifest the admission policy denies | API audit + policy decision |
| Application | a failed authorization on the victim app | {subject, action, resource, decision} — no token |
A source that doesn't produce a queryable record is a blind spot — fix it before you rely on it.
Attack Simulation Rules
- prefer seeded fixtures over general offensive tooling;
- use synthetic identities and canary secrets only;
- cap requests, concurrency, bytes, runtime, and cost;
- start packet/log capture before the exercise;
- maintain a tester action log (timestamp, operator, tool/version, target, request IDs) so responders can subtract your activity from an incident;
- stop the moment the security property is demonstrated (minimum proof, Phase 00 WARMUP).
Operator and Tool Identity
Give human operators named identities and automation narrowly scoped service identities.
Never reuse personal cloud credentials inside the range. Require short-lived credentials, strong
admin authentication, and a separate identity for evidence-store access (the experiment plane must
not be able to write the evidence vault). For every consequential action record:
operator · tool/version · policy decision · target · result.
The Evidence Pipeline Exercise
Run this once per range build to prove your evidence handling (Phase 00 WARMUP, Chapter 7):
# 1. create a source artifact with known time/identity
# 2. collect with the documented tool
sha256sum capture.pcap > capture.pcap.sha256 # 3. hash + register the RAW artifact
cp capture.pcap derived_utc.pcap # 4. normalize time into a DERIVED copy
./redact --canary > presentation.txt # 5. redact a canary into a presentation copy
sha256sum -c capture.pcap.sha256 # 6. verify — must PASS
printf '\x00' | dd of=capture.pcap bs=1 seek=10 conv=notrunc 2>/dev/null
sha256sum -c capture.pcap.sha256 # 7. after edit — must FAIL (tamper-evident)
Record every transformation with its own derived hash and reason. Screenshots alone are weak evidence — they omit source state, collection method, searchable structure, and transformation history; derive them from primary evidence.
Failure Scenarios and Drills
Unexpected personal/third-party data. Stop collection, isolate the artifact, restrict access, notify the authorized owner/privacy contact, record what was seen without copying more than necessary, and follow deletion/retention direction.
Service degradation. Stop traffic, capture time and request IDs, inform the owner, preserve tester logs, assist recovery, and do not resume until explicitly re-authorized.
Real suspicious activity during testing. Freeze automated tests, preserve telemetry and your action log, invoke incident command, and mark every known tester event so responders can separate you from the adversary. Do not investigate beyond the authority the incident lead grants.
Teardown
□ terminate cloud and local workloads
□ revoke temporary identities, certs, tokens, secrets
□ remove routes, TAP devices, namespaces, mounts, cgroups
□ export and hash required evidence; store in the vault
□ destroy unnecessary captures/snapshots per retention policy
□ run a final discovery FROM management and confirm only baseline assets remain
Teardown that "looks done" but leaves an orphaned cloud resource (cost + exposure) or a lingering TAP device (a path back) is a failed teardown — verify, don't assume.
Failure Injection and the Readiness Packet
Before you trust the range, inject each failure and confirm the range/operator responds correctly: expired authorization, adjacent target, DNS reassignment, prohibited technique, rate-budget exhaustion, telemetry loss, unexpected sensitive data, service degradation, and emergency stop.
The readiness packet (the go/no-go artifact) contains: authorization/scope, ownership evidence, topology, permitted/denied reachability proofs, identities and budgets, evidence controls, stop contacts and drill results, snapshot/rebuild procedure, teardown verification, and cost checks.
References
- NIST SP 800-115 — Technical Guide to Information Security Testing and Assessment (lab setup, rules of engagement).
- NIST SP 800-61r2 / 800-86 — incident handling and forensic/evidence concepts.
- CIS Benchmarks — host/hypervisor hardening baselines.
- nftables / iptables and libvirt networking documentation (isolated networks, host-only switches).
- Zeek and Suricata documentation; Sysmon (Sysinternals) and Linux auditd documentation.
- disclose.io — safe-harbor and rules-of-engagement templates (paired with Phase 00 WARMUP).