Chapter 6 — Operating systems and virtualization
Lesson map
Lesson 06 published. Map, example, EX016.
flowchart TD
N0["Learning outcomes and connection"]
N1["6.1 Hardening as subtraction"]
N2["6.2 Service accounts and least privilege"]
N3["6.3 Configuration files are security-relevant"]
N4["6.4 File-integrity baselines"]
N5["6.5 Virtualization"]
N6["6.7 Practical activity: file-integrity baseline"]
N7["Chapter synthesis"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7
N7 --> EX["Worked example"]
EX --> Q["Exercise EX016"]
Logical drawing
flowchart LR
N0["Learning outcomes and connection"]
N1["6.1 Hardening as subtraction"]
N2["6.2 Service accounts and least privilege"]
N3["6.3 Configuration files are security-relevant"]
N4["6.4 File-integrity baselines"]
N5["6.5 Virtualization"]
N6["6.7 Practical activity: file-integrity baseline"]
N7["Chapter synthesis"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7 --> Q["EX016"]
[Learning outcomes and connection]
|
v
[6.1 Hardening as subtraction]
|
v
[6.2 Service accounts and least privilege]
|
v
[6.3 Configuration files are security-relevant]
|
v
[6.4 File-integrity baselines]
|
v
[6.5 Virtualization]
|
v
[6.7 Practical activity: file-integrity baseline]
|
v
[Chapter synthesis]
|
v
[Worked example] --> [Exercise EX016]
Learning outcomes and connection
After this chapter you should be able to:
- harden a server by removing what it does not need and constraining what it does;
- run a service under a dedicated, unprivileged account with only the files and ports it needs;
- build and use a file-integrity baseline to detect unapproved change;
- explain what virtualization changes for security — and what it does not.
LANTERN's relays and historian are ordinary servers. Most compromises of such servers, and many outages, come not from exotic flaws but from things left on them: an unused service listening on all interfaces, a debug option, a world-writable file, an old account. This chapter is about keeping a server small, known and checkable.
6.1 Hardening as subtraction
Hardening means reducing a system to what its function requires and configuring what remains securely. NIST's server-security guide recommends removing or disabling unneeded services, applications and network protocols, configuring authentication and resource controls, and keeping the system patched and monitored (NIST SP 800-123). For a relay, that means: no desktop environment, no compilers, no file-sharing services, SSH listening only on the management interface, the relay process listening only on its declared address and port, and nothing listening on 0.0.0.0 without a reason written down.
6.2 Service accounts and least privilege
Run each service as its own unprivileged account (relay, not root). Give that account read access to its configuration, write access only to its own data and log directories, and no shell login. Use the operating system's service manager to restart it on failure and to apply further restrictions (for example, a read-only view of most of the filesystem). If the relay process is ever compromised, these choices determine whether the attacker holds one service or the whole host.
On RLY-01 this is the service definition whose permissions changed to 0666.
6.3 Configuration files are security-relevant
On a relay, the most security-relevant files are its configuration (what it listens on, where it forwards, where its key lives), its allowlist of stations, and its service definition (which account it runs as, with what restrictions). A change to any of them changes the security of the service. File permissions matter as much as content: a service definition that has become writable by any user lets any local user decide what runs as the service.
RLY-01 showed both kinds: a content change, debug_listen 0.0.0.0:9000, and a permission change to 0666.
6.4 File-integrity baselines
A file-integrity baseline records a cryptographic hash and the permissions of each important file at a known-good moment. Later snapshots are compared with it; every difference is either explained by an approved change record or investigated. SHA-256, specified in FIPS 180-4, is a standard choice: any change to the file's content changes its digest. The baseline itself must be protected — stored off the host or signed — because an attacker who can change a file and the baseline can hide the change.
6.5 Virtualization
Virtualization runs several operating systems on one physical host through a hypervisor. It helps operations — snapshots, quick rebuilds, separate guests for separate functions — and it creates new things to protect. NIST's guide to full virtualization notes that the hypervisor and its management interfaces become high-value targets, and that guests on one host share physical resources and can affect each other (NIST SP 800-125). Practical consequences: the hypervisor management network is its own zone; whoever administers the hypervisor effectively administers every guest; snapshots contain secrets and must be protected like backups; and placing a station-facing relay and a corporate-facing report server on the same host joins two zones through shared hardware and a shared administrator.
6.6 Worked example: a baseline catches a debug listener (synthetic)
You baseline RLY-01's three configuration files. A week later the comparison shows four differences. The allowlist gained PS-11 under approved change CHG-118 — explained. The relay configuration gained debug_listen 0.0.0.0:9000 with no change record: someone enabled a debug port on every interface, perhaps while troubleshooting, and left it. The service definition's permissions changed from 0640 to 0666: any local user can now rewrite it. A new file helper.sh appeared in the units directory. Three unapproved changes on a critical host is an investigation, not a tidy-up: before reverting anything, preserve the current files and the comparison output, and ask who changed what (Chapter 20).
6.7 Practical activity: file-integrity baseline
Lab 6 (save as lab06.py, run with python3 lab06.py):
# Lab 6 - a file-integrity baseline for the relay host's configuration (offline, standard library only)
# Synthetic files are created in a temporary directory; nothing outside it is read or changed.
import hashlib, json, os, tempfile
def digest(path):
h = hashlib.sha256()
with open(path, "rb") as f:
for block in iter(lambda: f.read(65536), b""):
h.update(block)
return h.hexdigest()
def snapshot(root):
out = {}
for d, _, files in os.walk(root):
for name in sorted(files):
p = os.path.join(d, name)
st = os.stat(p)
out[os.path.relpath(p, root)] = {"sha256": digest(p), "mode": oct(st.st_mode & 0o777)}
return out
with tempfile.TemporaryDirectory() as root:
files = {"relay.conf": "listen 10.30.0.5:8443\nupstream hist-01:443\nhmac_key_file /etc/relay/key\n",
"allow.list": "PS-04\nPS-07\nPS-09\n", "units/relay.service": "[Service]\nUser=relay\n"}
for rel, text in files.items():
p = os.path.join(root, rel); os.makedirs(os.path.dirname(p), exist_ok=True)
with open(p, "w") as f: f.write(text)
os.chmod(p, 0o640)
base = snapshot(root)
print("baseline entries:", len(base), "| relay.conf", base["relay.conf"]["sha256"][:16])
# simulated changes: one approved (change ticket CHG-118), one not, one permission change, one new file
with open(os.path.join(root, "allow.list"), "a") as f: f.write("PS-11\n")
with open(os.path.join(root, "relay.conf"), "a") as f: f.write("debug_listen 0.0.0.0:9000\n")
os.chmod(os.path.join(root, "units/relay.service"), 0o666)
with open(os.path.join(root, "units/helper.sh"), "w") as f: f.write("#!/bin/sh\n")
approved = {"allow.list": "CHG-118"}
now = snapshot(root)
for rel in sorted(set(base) | set(now)):
b, n = base.get(rel), now.get(rel)
if b == n: continue
kind = "added" if b is None else "removed" if n is None else "content" if b["sha256"] != n["sha256"] else "mode " + b["mode"] + "->" + n["mode"]
print(f"{rel:<20} {kind:<16} {'approved ' + approved[rel] if rel in approved else 'UNAPPROVED - investigate'}")
print("baseline json bytes:", len(json.dumps(base, sort_keys=True)))
Expected output (Python 3.13.5):
baseline entries: 3 | relay.conf 1defd9289ede0120
allow.list content approved CHG-118
relay.conf content UNAPPROVED - investigate
units/helper.sh added UNAPPROVED - investigate
units/relay.service mode 0o640->0o666 UNAPPROVED - investigate
baseline json bytes: 342
The script creates its files in a temporary directory, so you can run it anywhere. Note that the digest printed for relay.conf depends only on the file's content: if you change one character of the synthetic content in the script, the digest changes completely.
Compare the output with the RLY-01 week described above: four differences, of which only the PS-11 allowlist entry under CHG-118 has a change record. Then make one edit of your own inside the script, for example add a second debug line or change a mode from 0640 to 0644, rerun it and confirm the comparison reports exactly that difference and nothing else. A baseline that reports more or less than you changed is not yet reliable enough to be evidence in an investigation.
6.8 Common errors and limits
- Hardening once at build time and never checking again.
- Running services as root "because it was easier to get working".
- Keeping the integrity baseline on the same host, writable by the same administrators.
- Alerting on every file change on a busy system, so the alerts are ignored; baseline the files that matter.
- Treating a snapshot as a backup without testing restore, or leaving snapshots with keys in them unprotected.
- Co-locating guests from different zones on one hypervisor without recording that the zones now share a failure and an administrator.
File integrity detects change; it does not tell you whether the change was malicious, and it says nothing about changes in memory or in files you did not baseline.
Exercises — chapter 6
EX016 — Hardening review. Objective: apply hardening as subtraction. Inputs: a synthetic listing for RLY-02: listening on 0.0.0.0:22, 10.30.0.6:8443, 0.0.0.0:9000, 0.0.0.0:111; installed packages include a compiler and a desktop environment; relay runs as root. Constraints: propose changes only; each needs a reason. Steps: (1) list every change; (2) mark which need a change ticket and which can be done in the next standard change. Expected evidence: table. Rubric: 3 = SSH bound to management interface, debug 9000 removed, port 111 (RPC) disabled, compiler and desktop removed, relay moved to an unprivileged account with restrictions; sensible change classification; 2 = most; 1 = generic; 0 = none.
EX017 — Protect the baseline. Objective: design baseline storage. Inputs: Lab 6. Constraints: two designs. Steps: (1) describe storing the baseline off-host on a write-once location; (2) describe signing the baseline with a key not held on the relay; (3) compare what each protects against. Expected evidence: half page. Rubric: 3 = both designs correct; notes that an attacker with root on the relay can change files but cannot change an off-host or signed baseline undetected; notes that the comparison tool on the host itself can be subverted, so comparison should also run from outside; 2 = one design; 1 = vague; 0 = none.
EX018 — Hypervisor placement. Objective: reason about shared platforms. Inputs: proposal to run RLY-01 (station-facing), HIST-01 (corporate-facing) and the hospital's clinical gateway as guests on one FSTS hypervisor to save cost. Constraints: do not reject automatically; state conditions. Steps: (1) list what the zones would now share; (2) list conditions under which you would accept it; (3) name the residual risk and its owner. Expected evidence: one page. Rubric: 3 = shared hardware, hypervisor administrators, management network, storage and a single failure point across two sectors; conditions such as separate management zone, restricted admin group with MFA, separate virtual networks with no bridging, documented capacity headroom, and a failure plan for losing the host; residual risk owned by named service owners; 2 = partial; 1 = flat yes/no; 0 = none.
Chapter synthesis
Keep servers small and known: remove what the function does not need, run services under dedicated unprivileged accounts, bind listeners to declared addresses, and treat configuration files and their permissions as security-relevant. Baseline the files that matter with a cryptographic hash, protect the baseline, and investigate every unexplained difference. Virtualization simplifies operations but concentrates control in the hypervisor and its administrators; record which zones share a host.
Continue studying — chapter 06 of 30
← Chapter 05 · Course chapter index · Chapter 07 →
Continue to the next authored lesson.