1. Threat models and authority boundaries
Start with assets, adversaries, and the decisions a system must enforce.
FREE COMPUTER SCIENCE STACK LEVEL · 16 OF 20
What must remain true when inputs and participants are adversarial?
What must remain true when inputs and participants are adversarial?
Protect data, authority, and trust. This layer connects Threat models, Cryptography, Authorization, Web security, Incident response to the rest of the computing stack.
Trace trust boundaries through an application, identify the exact guarantees supplied by cryptography, and test authorization and failure paths. Practice with local models and synthetic data.
What must remain true when inputs and participants are adversarial?
This section is a sequence of worked studies. Each study asks you to reconstruct an example, solve a new problem, and check the assumptions behind your answer. Keep your derivations and code so you can revisit them without looking at the solution.
Start with assets, adversaries, and the decisions a system must enforce. Construct a threat model. Distinguish authentication from authorization. Apply least privilege to a concrete workflow.
Choose integrity, authenticity, or confidentiality without confusing the guarantees. Distinguish hashes, MACs, signatures, and encryption. Explain nonce requirements. Recognize password-storage requirements.
Follow credentials through login, requests, and logout. Describe the session lifecycle. Distinguish XSS from CSRF. Explain server-side revocation.
Keep untrusted bytes from becoming instructions or addresses. Explain parameter binding. Recognize context-specific injection. Separate memory safety from logical correctness.
Understand what a successful TLS connection actually authenticates. Describe channel authentication. Explain certificate-name validation. Plan key rotation and compromise response.
Turn a threat model into tests, maintenance, and a recoverable system. Prioritize vulnerabilities using exposure and impact. Design useful security telemetry. Separate containment, eradication, and recovery.
Programming contracts and basic networking. Each lesson names any additional prerequisites. Revisit the mathematics and programming sections whenever a calculation or execution trace becomes a barrier.
Review a private notes service: diagram data and authority, test cross-account access, identify injection boundaries, and rehearse credential revocation and recovery with synthetic data. A correct multiple-choice answer is only one kind of evidence. Preserve the intermediate steps, test an edge case, and explain why an attractive alternative fails.
The primary readings provide fuller treatments and additional exercises. Work the section project after the guided problems, then return to a problem a few days later without notes. Use a failed attempt to identify the specific definition, assumption, or step that needs more practice.
Start with assets, adversaries, and the decisions a system must enforce.
Choose integrity, authenticity, or confidentiality without confusing the guarantees.
Follow credentials through login, requests, and logout.
Keep untrusted bytes from becoming instructions or addresses.
Understand what a successful TLS connection actually authenticates.
Turn a threat model into tests, maintenance, and a recoverable system.
About 35 minutes. Authenticated subjects and object ownership.
Notes have an owner. A grant may allow read only. Owners may read, edit, and grant access. No other action is permitted. Use synthetic users A, B, and C.
A valid session identifies B; it does not preserve a revoked grant.
The owner has all three actions. A current read grantee may read only. Other users are denied. Test A editing its note, B reading a granted note, B trying to edit, C guessing the ID, and B trying to share. After revocation B is denied even with the same valid session because each request checks current object policy.
What race must you consider if authorization and an update observe different policy versions?
Use small defensive models to expose missing authority checks, replay assumptions, and recovery gaps. State the attacker capabilities before choosing a control.
2. Contract analysis · allow 40 minutes
An application encrypts account records with an unauthenticated stream cipher and stores the unkeyed digest SHA-256(ciphertext) beside each ciphertext. An attacker can change both stored values. Explain why the hash does not authenticate the record and why reusing a stream-cipher keystream is dangerous. Propose a design using a maintained authenticated-encryption library, unique nonces, associated data, and key rotation. How is password storage a different problem?
An unkeyed digest is computable by the attacker. For a reused keystream K, C1 XOR C2 cancels K.
The attacker can replace the ciphertext and recompute its public digest, so the hash detects accidental corruption but not malicious replacement. With C1=P1 XOR K and C2=P2 XOR K, their XOR is P1 XOR P2; known structure or known plaintext can expose information about the other message. Authenticated encryption combines confidentiality with integrity under its precise nonce and key requirements. Use a reviewed library, generate or allocate nonces according to the selected scheme, and never assume all AEAD algorithms tolerate reuse.
Bind tenant ID, record ID, format version, and other context as associated data when those fields must be authenticated without being encrypted. Store a key identifier, keep keys outside the data store with access controls, and define rotation, backup recovery, and compromised-key response. Verify authentication before using plaintext, and avoid revealing detailed decryption failures externally. Password verification should use a dedicated salted, deliberately expensive password-hashing scheme with reviewed parameters; reversible encryption is inappropriate when the service only needs to verify a password. Neither encryption nor hashing repairs excessive access permissions or sensitive logging.
3. Request-boundary reasoning · allow 35 minutes
A bank transfer endpoint accepts a POST with amount and destination and authenticates using a browser cookie. Explain how a different website might cause the browser to send an unwanted request. Design layered CSRF defenses. Would switching to POST alone, allowing only JSON, or adding CORS response headers be sufficient as a general proof? How does same-origin script injection change the threat model?
Cookies can be ambient credentials. CORS primarily controls a script's access to responses; some cross-origin requests can still be sent.
A malicious site can cause a victim's browser to submit a request while the browser attaches eligible cookies. The server sees a valid session but lacks evidence that the user intended this action. Use an appropriate CSRF token or a well-designed custom-header pattern, validate Origin or suitable request metadata, and set cookies with Secure, HttpOnly, and an appropriate SameSite policy. Require authorization and validate the operation independently. Sensitive actions may need explicit recent user verification.
POST alone does not prevent cross-site form submission. Strict JSON handling and custom headers can block simple cross-origin forms when correctly enforced, but accepting alternate content types, permissive origins, or unsafe endpoints can invalidate that design. CORS is not a universal CSRF defense, because blocking response reads does not necessarily block the effect. SameSite reduces attack surface but depends on site boundaries, navigation behavior, and application flows. Same-origin script injection can often read tokens or issue authorized requests, so CSRF controls do not replace output encoding, safe DOM APIs, and defenses against script injection. Test the actual browser and endpoint behavior, including rejected content types and missing or mismatched tokens.
4. Incident simulation · allow 45 minutes
A service token with access to production object storage appears in a public build log. Draft the first-hour technical response and a verification plan. The team deletes the log and declares the incident resolved. Explain what that misses. Distinguish containment, evidence preservation, scope assessment, recovery, and prevention, including the case where the old token can mint other credentials.
Exposure removal does not invalidate copies. Find the transitive authority of the credential, not only its displayed permissions.
Contain by revoking or disabling the exposed credential and restricting affected access while maintaining essential service through a controlled replacement. Preserve relevant logs and timestamps in an access-controlled location before destructive cleanup, and record when exposure and revocation occurred. Determine which objects and operations the credential could reach, whether it could create credentials or change policy, and whether those derived capabilities also require revocation. Public-log deletion limits further exposure but cannot recall copies already obtained.
Assess access logs, configuration changes, downloads, and suspicious activity across the exposure window, while acknowledging logging gaps and retention limits. Rotate dependent secrets only where their exposure or derivation is plausible, restore trusted configuration, and verify that the old credential and any descendants fail while the replacement has only required permissions. Test application recovery, not merely credential creation. Prevent recurrence through short-lived scoped credentials, secret redaction and scanning, least privilege, safer build outputs, and a rehearsed response path. Communicate facts and uncertainty through the organization's incident process; absence of a log entry is not proof that no access occurred.
5 to 7 hours. Build and adversarially test a local document-store API using Python and SQLite. Inputs are structured requests with a test session token, operation, document identifier, and optional text. Outputs are success results or stable authentication, authorization, validation, and missing-resource errors. Create local test users and opaque session tokens using the secrets module; store only token hashes and enforce expiration using an injectable clock. Each document has one owner, and every read, update, and deletion must authorize against the current owner. Treat account creation and session issuance as a local test fixture, not a production login system. Use parameterized SQL and bounded text sizes. Write a threat model covering an unauthenticated caller, a different authenticated user, expired sessions, guessed document IDs, and malformed inputs. Keep tests confined to the local program and synthetic records. Submit an authorization matrix, regression tests, and a short explanation of why random IDs, hidden buttons, and hashed tokens do not replace server-side access checks. Use an injectable clock to test the exact expiration boundary without sleeping. Define whether a token expires at or after its recorded timestamp, and make issuance and revocation behavior visible in the fixture.
Add explicit read-only sharing grants and revoke them, then test that revocation takes effect on the next request without changing ownership semantics.