CS 161, Lesson 3 and Quiz 3, in 48 slides. It covers structured threat modeling with STRIDE and data-flow diagrams, marked as supplemental, then a TCB-identification exercise from section 1.12 and the classic access()/open() symlink TOCTTOU lab from section 1.13. It applies all 13 principles from Lessons 1 and 2.
Subject: Computer Security · 53 slides · applied lesson
Open the interactive version of this deck · Homework for this lesson
Title
CS 161 · Lesson 3 of 45 · Quiz day
STRIDE · data-flow diagrams · TCB identification · the TOCTTOU lab
Objectives
Warm-up
Discussion prompt
Before we open L03 · Threat Modeling (STRIDE/DFD) + TCB & TOCTTOU Labs: without looking back, what was the main idea of L02 · Security Principles II (the remaining nine: Defense in Depth → TOCTTOU), and what could you do by the end of it that you could not do before?
Hint: One sentence for the idea, one for the skill. If the second one is blank, that is the part to revisit.
Answer:
CS 161, Lesson 2, in 50 slides. It covers the nine remaining design principles: defense in depth, least privilege, separation of responsibility, complete mediation, Shannon's Maxim, fail-safe defaults, designing security in from the start, the Trusted Computing Base, and TOCTTOU races. It is anchored to textbook sections 1.5 to 1.13 and to Saltzer & Schroeder (1975).
Concept
STRIDE and DFDs are ⊕ supplemental — they are not in the CS 161 textbook; they come from Microsoft's threat-modeling practice. The TCB (§1.12) and TOCTTOU (§1.13) halves are straight from the book. Don't hunt for a STRIDE chapter in the notes.
Today is application day: you already have the 13 principles — now you'll run them as a repeatable process and beat the three diagnostic items.
Counterexample
Discussion prompt
Today is application day: you already have the 13 principles — now you'll run them as a repeatable process and beat the three diagnostic items.
That is stated as though it always holds. Do one of two things: produce a case where it fails, or say precisely what rules such a case out. "It just does" is not on the menu.
Hint: Hunt at the extremes first — zero, one, negative, empty, equal. If every extreme survives, the reason they survive is the proof.
Section
Part 1 · ⊕ supplemental
Concept
STRIDE is a checklist of six threat categories. Each is the negation of a security property — which is what makes it a complete-feeling list.
| Letter | Threat | Violates property | Countered by |
|---|---|---|---|
| S | Spoofing | Authentication | Strong auth, signatures |
| T | Tampering | Integrity | MACs, hashes, ACLs |
| R | Repudiation | Non-repudiation | Signed audit logs |
| I | Information disclosure | Confidentiality | Encryption, least privilege |
| D | Denial of service | Availability | Rate limiting, redundancy |
| E | Elevation of privilege | Authorization | Least privilege, mediation |
Comparison
Comparison matrix
From STRIDE: six ways things go wrong: refill the Threat column from what you know. The rest of the table is as it appeared.
| Letter | Threat | Violates property | Countered by |
|---|---|---|---|
| S | Spoofing | Authentication | Strong auth, signatures |
| T | Tampering | Integrity | MACs, hashes, ACLs |
| R | Repudiation | Non-repudiation | Signed audit logs |
| I | Information disclosure | Confidentiality | Encryption, least privilege |
| D | Denial of service | Availability | Rate limiting, redundancy |
| E | Elevation of privilege | Authorization | Least privilege, mediation |
Intuition
You will not think of every attack from a blank page. STRIDE gives you six questions to ask of each element in your design: can this be spoofed? tampered? repudiated? leaked? denied? escalated?
Notice the principle hooks: E maps to least privilege + complete mediation (Lesson 2), T to integrity primitives (crypto unit), I to confidentiality. STRIDE is a way to route the principles you already know.
Analogy
Discussion prompt
Explain Why STRIDE works as a prompt by analogy to something with no Computer Security in it at all — a queue, a recipe, a map, a bank balance, whatever fits. Then say where your analogy breaks.
Hint: An analogy that never breaks is not an analogy, it is the same idea wearing a hat. Find the seam — that is the part that is actually new.
Answer:
You will not think of every attack from a blank page. STRIDE gives you six questions to ask of each element in your design: can this be spoofed? tampered? repudiated? leaked? denied? escalated?
Step zero
Discussion prompt
Run STRIDE on a login endpoint — before any calculation: what is the plan? Name the moves in order, in plain English, without doing the arithmetic.
Hint: It starts with: Tampering / Information disclosure
Answer:
Worked example
Spoofing
Why: Attacker submits another user's username with a guessed/stuffed password — counter with rate limiting and a slow hash (foreshadows Lesson 32).
Tampering / Information disclosure
Why: Attacker modifies or reads the request in transit — counter with TLS so the channel has integrity and confidentiality.
Repudiation
Why: User denies a login ever happened — counter with an append-only, signed audit log.
DoS / Elevation
Why: Attacker floods the endpoint (lockout-as-DoS, Lesson 32) or abuses a flaw to gain admin — counter with throttling and least-privilege session scopes.
Blank canvas
Draw it
Draw what Run STRIDE on a login endpoint just did — the shape of it, not the line-by-line working. One picture, labels only where you need them. Then check it against the steps: anything you could not draw is a step you followed rather than understood.
Anomaly
Predict first
A student writes this, and it looks reasonable:
Attacker forges a log entry to look like it came from the admin.
It is wrong. Say what breaks — and say it before you turn the page.
Correct: Fixates on 'data was altered' and misses that the point was to impersonate and to deny accountability.
Attacker forges a log entry to look like it came from the admin.
Why: Fixates on 'data was altered' and misses that the point was to impersonate and to deny accountability.
Trap
Attacker forges a log entry to look like it came from the admin.
Classify it as Tampering and stop
Why: Fixates on 'data was altered' and misses that the point was to impersonate and to deny accountability.
Attacker forges a log entry to look like it came from the admin.
It's Spoofing (false identity) enabling Repudiation (deniable action), realized via Tampering
Why: STRIDE categories overlap; name the attacker's GOAL (impersonate + deny), not just the mechanism. The counter is signed logs, not just an integrity check.
Section
Part 2 · ⊕ supplemental
Concept
The payoff rule: threats cluster on data flows that cross a trust boundary. That's where attacker-controlled data meets trusted code.
Analogy
Discussion prompt
Explain DFD elements and the trust boundary by analogy to something with no Computer Security in it at all — a queue, a recipe, a map, a bank balance, whatever fits. Then say where your analogy breaks.
Hint: An analogy that never breaks is not an analogy, it is the same idea wearing a hat. Find the seam — that is the part that is actually new.
Answer:
The payoff rule: threats cluster on data flows that cross a trust boundary. That's where attacker-controlled data meets trusted code.
Explain it to yourself
Discussion prompt
In DFD for a web app, threats per boundary this move is made:
Enumerate threats on the crossing flow (browser → web app)
Why is that legal? Name the rule or definition it rests on before you read on.
Hint: If you can only say "because that is what you do", the rule is the thing to go and find.
Answer:
Tampering/Info-disclosure → require TLS; Spoofing → require auth; Elevation → validate and least-privilege the request. This is where injection (Lesson 35) and XSS (Lesson 40) live.
Worked example
Figure (svg): Data-flow diagram: a Browser external entity connects to a Web app process, which connects to a DB data store; a dashed trust boundary separates the untrusted browser from the trusted server.
Enumerate threats on the crossing flow (browser → web app)
Why: Tampering/Info-disclosure → require TLS; Spoofing → require auth; Elevation → validate and least-privilege the request. This is where injection (Lesson 35) and XSS (Lesson 40) live.
Now the web-app → DB flow
Why: It is inside the trust boundary, but still: a least-privilege DB account (Lesson 35) limits damage if the web app is compromised. Inside ≠ ignore.
Blank canvas
Draw it
Draw what DFD for a web app, threats per boundary just did — the shape of it, not the line-by-line working. One picture, labels only where you need them. Then check it against the steps: anything you could not draw is a step you followed rather than understood.
Anomaly
Predict first
A student writes this, and it looks reasonable:
A diagram with browser, app, and DB — but no dashed line drawn.
It is wrong. Say what breaks — and say it before you turn the page.
Correct: Without a trust boundary you can't see WHERE attacker data enters, so you waste effort and miss the real entry point.
Same diagram, with the trust boundary drawn between browser and app.
Why: Without a trust boundary you can't see WHERE attacker data enters, so you waste effort and miss the real entry point.
Trap
A diagram with browser, app, and DB — but no dashed line drawn.
Enumerate threats evenly across all three flows
Why: Without a trust boundary you can't see WHERE attacker data enters, so you waste effort and miss the real entry point.
Same diagram, with the trust boundary drawn between browser and app.
Concentrate on the flow that crosses the boundary first
Why: The boundary marks where untrusted input meets trusted code — the highest-yield place to apply STRIDE. Draw the boundary before you enumerate.
Break the constraint
Discussion prompt
The rule this trap just fixed:
The boundary marks where untrusted input meets trusted code — the highest-yield place to apply STRIDE. Draw the boundary before you enumerate.
Now break it on purpose. Build a case that violates it and follow the consequences until something visibly fails. Where does the failure first show up — and would you have noticed it if you had not been looking?
Hint: The dangerous rules are the ones whose violation still produces an answer. If yours fails loudly, try to find one that fails quietly.
Answer:
Without a trust boundary you can't see WHERE attacker data enters, so you waste effort and miss the real entry point.
Section
Part 3 · §1.12
Estimation
Predict first
Goal: a third-party plugin must not read the host app's saved passwords. What must be correct?
Commit before you compute: what does Circle the TCB: a sandboxed plugin host come out to? A rough magnitude and the right form is enough — the point is to have something concrete to be wrong about.
Correct: State the win condition
Why: A prediction you can defend turns the computation into a check rather than a leap of faith — and an answer that contradicts it is caught on the spot. §1.12: keep the TCB unbypassable, tamper-resistant, and verifiable — and as small as possible, so the code you must trust is auditable.
Worked example
Goal: a third-party plugin must not read the host app's saved passwords. What must be correct?
| Component | In TCB? | Justification |
|---|---|---|
| The sandbox / isolation layer | Yes | It enforces the read restriction — a bug here defeats the goal |
| OS kernel + memory protection | Yes | It backs the sandbox; if it fails, isolation fails |
| The password store's access checks | Yes | They decide who may read secrets |
| The third-party plugin itself | No | It is the thing being contained — it may be fully malicious and still must not win |
| The app's spell-checker | No | Irrelevant to the secret-reading goal if properly isolated |
State the win condition
Why: §1.12: keep the TCB unbypassable, tamper-resistant, and verifiable — and as small as possible, so the code you must trust is auditable.
Discrimination
Sort into buckets
Sort these by In TCB?, from memory, without looking back at Circle the TCB: a sandboxed plugin host. Telling them apart on the spot is the skill; the table is only where the answer happens to be written down.
Anomaly
Predict first
A student writes this, and it looks reasonable:
Listing components that must be correct.
It is wrong. Say what breaks — and say it before you turn the page.
Correct: Confuses 'present in the system' with 'must be trusted'.
Listing components that must be correct.
Why: Confuses 'present in the system' with 'must be trusted'. The whole point is that the plugin is OUTSIDE the TCB.
Trap
Listing components that must be correct.
Put the untrusted plugin IN the TCB because it 'touches' the system
Why: Confuses 'present in the system' with 'must be trusted'. The whole point is that the plugin is OUTSIDE the TCB.
Listing components that must be correct.
Put only what must be CORRECT for the goal in the TCB; the plugin stays out
Why: §1.12: anything outside the TCB may misbehave maliciously and still cannot defeat the goal. If isolating the plugin requires trusting it, the design is broken.
Section
Part 4 · §1.13
Concept
A setuid-root program wants to act on a file only if the real user may write it, so it checks first, then opens:
// runs as root, but should honor the caller's permissions
if (access(path, W_OK) != 0) // CHECK: may the real user write path?
exit(1);
int fd = open(path, O_WRONLY); // USE: open it as root
write(fd, data, len);access() checks the real UID; open() uses the program's effective (root) UID. Between the two lines, path can change identity.
Counterexample
Discussion prompt
A setuid-root program wants to act on a file only if the real user may write it, so it checks first, then opens:
That is stated as though it always holds. Do one of two things: produce a case where it fails, or say precisely what rules such a case out. "It just does" is not on the menu.
Hint: Hunt at the extremes first — zero, one, negative, empty, equal. If every extreme survives, the reason they survive is the proof.
Answer:
access() checks the real UID; open() uses the program's effective (root) UID. Between the two lines, path can change identity.
Ranking
Put in order
Put the moves of The symlink swap into the order they have to happen.
Why: These are the moves of the worked example in the order it makes them, and each one is set up by the one before it. access(path, W_OK) succeeds — the real user genuinely may write their own file.
Worked example
Attacker makes path a real file they own
Why: access(path, W_OK) succeeds — the real user genuinely may write their own file. The check passes honestly.
Between check and use, attacker replaces path with a symlink to /etc/passwd
Why: The name 'path' now points somewhere else. Nothing re-validated it.
| Time | path points to | Acting UID | Result |
|---|---|---|---|
| access() check | attacker's own file | real (user) | check passes ✓ |
| — attacker swaps — | symlink → /etc/passwd | — | race window |
| open() use | /etc/passwd | effective (root) | opens a root-only file |
| write() | /etc/passwd | root | privilege escalation |
Root writes /etc/passwd on the user's behalf
Why: The stale check authorized a write the user could never do directly. This is §1.13: the state (what 'path' names) changed between check and use.
Discrimination
Sort into buckets
Sort these by path points to, from memory, without looking back at The symlink swap. Telling them apart on the spot is the skill; the table is only where the answer happens to be written down.
Anomaly
Predict first
A student writes this, and it looks reasonable:
Fix attempt: call access() twice, before and after.
It is wrong. Say what breaks — and say it before you turn the page.
Correct: Still TOCTTOU — the attacker just swaps after the second check.
Fix attempt: drop privileges and open atomically.
Why: Still TOCTTOU — the attacker just swaps after the second check. More checks, same race.
Trap
Fix attempt: call access() twice, before and after.
Add a second access() check just before open()
Why: Still TOCTTOU — the attacker just swaps after the second check. More checks, same race.
Fix attempt: drop privileges and open atomically.
Permanently drop to the real UID, then open() once — let the OS enforce permissions on the open itself
Why: §1.13: eliminate the check/use split. open() under the real UID is a single atomic, fully-mediated operation — no window for the name to change identity.
Two truths and a lie
Sort into buckets
Some of these hold up and some are the exact mistakes this lesson is built to prevent. Sort them.
Ranking
Put in order
These are the steps of The threat-modeling recipe, scrambled. Put them back in order before the next slide shows you.
Why: This is the order the recipe itself gives. Recalling the sequence without the slide in front of you is the difference between recognising the method and being able to run it — most of what goes wrong in practice is a step done out of turn.
Pattern
Sorting
Sort into buckets
These are the pieces of L03 · Threat Modeling (STRIDE/DFD) + TCB & TOCTTOU Labs, out of order. Put each one back under the part of the lesson it belongs to.
Elimination
Eliminate the wrong options
Which STRIDE category is the PRIMARY threat, and which property does it violate?
3 of these 4 are wrong. Strike them one at a time, and say what rules each one out before you strike the next. The survivor is the answer.
Survives elimination: A
Why: Replaying a stolen token lets the attacker authenticate AS the victim — that is Spoofing, a violation of authentication. The capture also involves Information Disclosure, but the act of impersonation is the primary Spoofing threat.
Check
An attacker captures a valid session token over open Wi-Fi and replays it to act as the victim.
Check your understanding
Which STRIDE category is the PRIMARY threat, and which property does it violate?
Answer: A
Why: Replaying a stolen token lets the attacker authenticate AS the victim — that is Spoofing, a violation of authentication. The capture also involves Information Disclosure, but the act of impersonation is the primary Spoofing threat.
Prediction
Predict first
Which change actually removes the vulnerability?
Answer it in your own words, now, with nothing to choose from. The options are on the next slide — and picking the right one off a list is an easier skill than producing it.
Correct: Permanently drop to the real UID, then open() once and let the OS check permissions.
Why: The bug is the check/use split plus the privilege mismatch. Dropping to the real UID and opening once makes the permission check and the open one atomic, fully-mediated operation — there is no window for the name to change identity.
Check
The setuid program does access(path, W_OK) and then open(path).
Check your understanding
Which change actually removes the vulnerability?
Answer: B
Why: The bug is the check/use split plus the privilege mismatch. Dropping to the real UID and opening once makes the permission check and the open one atomic, fully-mediated operation — there is no window for the name to change identity.
Elimination
Eliminate the wrong options
Which is NOT part of the TCB for this goal?
3 of these 4 are wrong. Strike them one at a time, and say what rules each one out before you strike the next. The survivor is the answer.
Survives elimination: C
Why: §1.12: the TCB is what must be CORRECT for the goal. The sandbox, OS isolation, and cookie access checks all must work. The untrusted tab's JavaScript is exactly what is being contained — it may be fully malicious and must still fail.
Check
Goal: a sandboxed browser tab must not read another tab's cookies.
Check your understanding
Which is NOT part of the TCB for this goal?
Answer: C
Why: §1.12: the TCB is what must be CORRECT for the goal. The sandbox, OS isolation, and cookie access checks all must work. The untrusted tab's JavaScript is exactly what is being contained — it may be fully malicious and must still fail.
Concept
Concept
Concept
Connect it up
Draw it
One page, no notation unless you need it: draw how these connect — STRIDE · Data-Flow Diagrams · TCB Identification · The TOCTTOU Lab. Put an arrow wherever one of them is what makes another possible, and label the arrow with why.
Recap
You can now run STRIDE over a DFD, draw the trust boundary that focuses your effort, circle a TCB with justified inclusions/exclusions, and close a check→use race atomically.
| Tool | Source | Core move |
|---|---|---|
| STRIDE | Microsoft 1999 ⊕ | Six threats per element → property → principle |
| DFD | Shostack ⊕ | Threats cluster on boundary-crossing flows |
| TCB | §1.12 | Shrink to unbypassable, tamper-resistant, verifiable |
| TOCTTOU | §1.13 | Make check and use one atomic step |
Want this taught 1-on-1? Alexander tutors Computer Security — $55/session, free consultation.