English
Security engineering is the discipline of building systems that resist adversarial action — attacks against confidentiality, integrity, and availability — by people who are actively trying to make them fail. The adversarial character is what makes it distinctive. Most engineering deals with passive failure modes: hardware wears out, software encounters unexpected edge cases, networks lose packets. Security engineering must account for an intelligent, adaptive opponent who studies the system, finds the weakest point, and exploits it. A defense that works against anticipated attacks provides no assurance against unanticipated ones; a system with one vulnerability is insecure regardless of how well-designed everything else is.
Cryptography provides the mathematical foundations for the field: techniques for transforming information in ways that guarantee confidentiality, integrity, and authenticity. It is the one area of security where strong formal guarantees are possible — where you can prove, under specific mathematical assumptions, that an adversary with limited computational power cannot break the scheme. But cryptographic security does not compose automatically into system security. A perfectly secure encryption algorithm provides nothing if the key is mismanaged, if the authentication protocol has a flaw, or if the application code can be tricked into decrypting an attacker’s chosen data. The gap between cryptographic security and system security is where most practical vulnerabilities live.
The subject has three organizing problems that appear throughout: how to give mathematical guarantees about secrets and authenticity (cryptography); how to build systems that remain secure when components fail, are misconfigured, or are actively attacked (security engineering); and how to discover vulnerabilities before adversaries do, and understand attacks well enough to defend against them (offensive security and threat modeling). These three problems require different skills — number theory and probability for the first, systems thinking and protocol analysis for the second, adversarial intuition for the third — and competent security work requires all three.
Prerequisites: Computer networks (§4.3) — protocols, TLS, and network-layer attacks. Operating systems (§4.2) — privilege separation, memory management, and system calls. Discrete mathematics (§2.2) — modular arithmetic, number theory, and probability for cryptography. Complexity theory (§3.2–§3.3) — cryptographic security is based on computational hardness.
From Military Codes to Mathematical Proof
Cryptography is ancient. The Caesar cipher, shifting each letter by three positions, protected Julius Caesar’s correspondence. The Vigenère cipher, using a repeating key to vary the shift, was considered unbreakable for centuries before Charles Babbage and Friedrich Kasiski independently broke it in the nineteenth century. The lesson from this history is consistent: ciphers that appeared secure under informal analysis were broken when analyzed more carefully. Intuition about cryptographic security is unreliable.
The mathematical transformation of cryptography began in World War II. Alan Turing’s work at Bletchley Park, breaking the Enigma cipher used by the German military, demonstrated that even complex mechanical cipher machines were vulnerable to systematic mathematical analysis, and that the security they offered was much weaker than their operators believed. The scale of the Bletchley operation — over ten thousand people ultimately worked there — and its impact on the war’s outcome established that cryptanalysis was an industrial-scale activity, not a purely intellectual puzzle.
Claude Shannon’s 1949 paper “Communication Theory of Secrecy Systems” provided the first rigorous mathematical framework for evaluating cryptographic security. Shannon proved that the one-time pad — a key as long as the message, used only once — was perfectly secure in a precisely defined sense, and that no cipher using shorter keys could be perfectly secure against an adversary with unlimited computation. This established the information-theoretic baseline: perfect security requires keys as long as messages, making it impractical for most applications. Shannon’s work also defined confusion and diffusion as the two properties that strong symmetric ciphers must achieve, providing design principles that the DES and AES block cipher designs would later follow.
The public-key revolution arrived in 1976. Whitfield Diffie and Martin Hellman’s paper “New Directions in Cryptography” proposed a concept that seemed impossible: a key exchange protocol in which two parties could establish a shared secret over an insecure channel, with no prior shared secret, even with an eavesdropper recording every message. The construction relied on the difficulty of the discrete logarithm problem — computing x from g^x mod p is easy when you know x, but hard to reverse. Diffie and Hellman had not found a practical implementation; Ronald Rivest, Adi Shamir, and Leonard Adleman published RSA the following year, the first practical public-key cryptosystem. RSA relied on the difficulty of factoring large integers: given n = p × q for large primes p and q, recovering p and q from n is computationally infeasible with current algorithms. Public-key cryptography made secure communication over public networks possible without requiring a prior secure channel to exchange keys — the foundational capability that the modern internet depends on.
The development of internet security protocols through the 1980s and 1990s was characterized by incremental improvement following each publicized attack. SSL (Secure Sockets Layer), developed by Netscape in 1994 to enable secure web transactions, was the first widely deployed protocol for encrypting internet traffic. Each version of SSL and its successor TLS was published, attacked, patched, and improved. SSLv2 had design flaws enabling cipher downgrade attacks. SSLv3 had POODLE. TLS 1.0 had BEAST. The pattern of publish-attack-improve is characteristic of the field, and the current TLS 1.3 standard (2018) represents the accumulated learning from twenty years of attacks on previous versions.
The software security crisis arrived with the exponential growth of networked software in the 1990s. The Morris Worm of 1988 was the first major incident: released by Robert Morris, a Cornell graduate student, it exploited a buffer overflow in Unix’s fingerd daemon and a weakness in sendmail to spread to thousands of computers, crashing approximately 10% of the internet. The worm was not destructive — it was intended as a demonstration — but it established that software vulnerabilities could be weaponized at scale. Aleph One’s 1996 Phrack article “Smashing the Stack for Fun and Profit” provided a systematic tutorial on exploiting buffer overflows, making the technique accessible to a wider range of attackers. The consequence was two decades of buffer overflow exploits, contributing to the security crisis in C and C++ software.
The defensive responses accumulated layer by layer. Stack canaries (1998) added a random value before the return address; buffer overflows had to overwrite it, and the program detected the corruption. Address Space Layout Randomization (ASLR) randomized where code and data were loaded, making it harder to predict target addresses. Non-executable stack and heap (NX/DEP) prevented injected shellcode from executing. Return-oriented programming (ROP) defeated NX by chaining together existing code gadgets from the program’s binary — showing that attackers adapted faster than defenses. The arms race between buffer overflow attacks and defenses drove both the development of memory-safe languages as alternatives to C, and eventually Rust’s ownership model as a way to provide memory safety in a systems language.
Diffie and Hellman received the Turing Award in 2015. The accompanying citation noted that their 1976 paper had “proved to be foundational to the modern Internet.” The DH key exchange, RSA, elliptic curve variants of both, and the TLS protocol built on them provide the security infrastructure of essentially every authenticated encrypted connection on the internet — HTTPS, SSH, Signal, encrypted email. The security of this infrastructure rests on computational hardness assumptions: that factoring large integers and computing discrete logarithms are infeasible with current computers. These assumptions are believed but not proven, which is a technical limitation with significant practical implications.
Spectre and Meltdown, disclosed in January 2018, produced a different kind of shock. Both exploited the speculative execution mechanisms that modern processors use for performance, extracting information from protected memory through timing side channels. The vulnerabilities were not bugs in the traditional sense — the processor was functioning as designed. The security failure arose from the gap between what the instruction-set architecture specified (isolation between processes) and what the microarchitecture did to achieve performance. Mitigating Spectre required changes to operating systems, compilers, web browsers, and the CPU microcode — and some mitigations remained incomplete years later because fully closing the vulnerability required architectural changes that would significantly degrade performance. Spectre demonstrated that the security of a system depends on the security of its hardware implementation, not just its specification, and that decades of hardware optimization for performance had introduced security vulnerabilities that were not visible at the software level.
The post-quantum cryptography transition is the current major concern. Shor’s algorithm, if run on a sufficiently large quantum computer, can factor integers and compute discrete logarithms in polynomial time — breaking RSA, Diffie-Hellman, and elliptic curve cryptography. The question is when (and whether) quantum computers of sufficient scale will exist. NIST ran a post-quantum cryptography standardization process from 2016, publishing the first post-quantum standards in 2024: ML-KEM, derived from CRYSTALS-Kyber, for key encapsulation, and ML-DSA, derived from CRYSTALS-Dilithium, for digital signatures, both based on the hardness of lattice problems rather than on factoring or discrete log. Organizations are now planning and executing migrations from RSA and ECDSA to these post-quantum alternatives — a multi-year infrastructure project required to maintain security against a threat that may materialize within the decade or may not materialize for several decades.
Cryptographic Primitives, System Security, and the Adversarial Mindset
Cryptographic Building Blocks
Modern cryptographic engineering is based on a set of vetted primitives — symmetric ciphers, hash functions, and public-key schemes — combined according to protocols proven secure under mathematical assumptions. The practitioner’s role is not to design new primitives (a task for cryptographers with significant mathematical training) but to use existing ones correctly.
Symmetric encryption uses the same key for encryption and decryption. AES (Advanced Encryption Standard), adopted in 2001, is the dominant symmetric cipher. AES operates on 128-bit blocks with 128, 192, or 256-bit keys, and is considered secure against all known practical attacks. Symmetric encryption is fast — AES-NI hardware acceleration enables gigabytes-per-second throughput — but requires a shared key, which creates the key distribution problem. Block cipher modes (CBC, GCM, CTR) determine how AES is applied to messages longer than 128 bits; GCM (Galois/Counter Mode) is the standard for authenticated encryption, providing both confidentiality and integrity in a single operation.
Cryptographic hash functions map arbitrary-length inputs to fixed-length outputs with several security properties: preimage resistance (given a hash, you cannot find an input that produces it), second preimage resistance (given an input, you cannot find a different input with the same hash), and collision resistance (you cannot find any two inputs with the same hash). SHA-256 and SHA-3 are the current standards. Hash functions appear throughout cryptography: as message authentication codes (HMAC), as components of digital signature schemes, as password storage functions (bcrypt, Argon2 use hash functions with deliberate slowness to increase the cost of dictionary attacks).
Public-key cryptography uses a mathematically linked key pair: anything encrypted with the public key can only be decrypted with the private key, and anything signed with the private key can be verified with the public key. RSA and elliptic curve Diffie-Hellman (ECDH) provide key encapsulation; ECDSA and Ed25519 provide digital signatures. Elliptic curve variants are preferred for new systems because they provide equivalent security to RSA at much shorter key lengths, reducing bandwidth and computation.
The critical principle is that these primitives should be used through well-designed protocols and libraries, not assembled from scratch. TLS 1.3 is the standard protocol for authenticated key exchange and encrypted communication. Signal Protocol is the standard for end-to-end encrypted messaging. libsodium is the standard library for implementing cryptographic operations in software not covered by TLS. Each was designed by cryptographers, reviewed extensively, and updated in response to discovered weaknesses. The alternative — designing a new protocol or implementing primitives directly — has a consistent history of subtle errors that undermine security even when the individual components are sound.
The Security Engineering Mindset
Security engineering differs from ordinary software engineering in its required adversarial perspective. An engineer building a reliable system asks: what could go wrong accidentally? A security engineer adds: what could an adversary do deliberately, given complete knowledge of the system’s design? Kerckhoffs’s principle, formulated in 1883 for military cryptography, states that a cryptographic system should be secure even if everything about it except the key is public knowledge. The modern interpretation is broader: system security should not depend on obscurity about how the system works.
Threat modeling is the systematic practice of identifying what could go wrong adversarially. The STRIDE framework (Microsoft Research, late 1990s) categorizes threats into Spoofing (impersonation), Tampering (modification), Repudiation (denying actions), Information Disclosure, Denial of Service, and Elevation of Privilege. For any system component, applying STRIDE generates a systematic list of threat categories to consider. The output is not a checklist but a set of questions: which threats are relevant, which mitigations apply, and what residual risk remains.
Least privilege is the design principle that every component should have only the capabilities it requires. A web server process that needs to read static files should not run as root; a database connection used for reads should not have write permissions; a microservice that needs to call one API should not have credentials for another. Violations of least privilege allow compromised components to cause damage beyond their intended scope. Defense in depth is the complementary principle: every security boundary might fail, and systems should be designed so that multiple boundaries must fail for the most important properties to be violated.
The OWASP Top 10 documents the most common application security vulnerabilities. Injection — especially SQL injection, where user-supplied input is interpreted as code — exploits the failure to distinguish data from commands. Authentication and access control failures — weak passwords, session management errors, missing authorization checks — allow unauthorized access. Cryptographic failures — using outdated algorithms, insufficient key lengths, insecure certificate handling — undermine confidentiality. Cross-site scripting (XSS) — injecting JavaScript into web pages viewed by other users — exploits the failure to sanitize output. Each category has standard mitigations; the failures persist because they are easy to introduce when developers are not thinking adversarially.
Finding Vulnerabilities: Fuzzing, Penetration Testing, and Code Review
Offensive security is the practice of finding vulnerabilities before adversaries do. Understanding attacks well enough to prevent them requires learning to think like an attacker.
Fuzzing — generating random or structured invalid inputs and observing whether the program crashes or exhibits unexpected behavior — is the most automated and scalable vulnerability discovery technique. Tools like American Fuzzy Lop (AFL) and libFuzzer use coverage-guided mutation: they track which code paths each input exercises and prioritize mutations that reach new paths. Fuzzing has found thousands of critical vulnerabilities in browsers, codecs, parsing libraries, and OS kernels. Its limitation is that it finds crashes and assertion failures, not logical vulnerabilities or authorization flaws.
Static analysis tools examine code without running it, flagging patterns associated with vulnerabilities: buffer accesses that might overflow, format string vulnerabilities, use of deprecated functions, null pointer dereferences. Tools like CodeQL (GitHub), Semgrep, and commercial analyzers identify these patterns across large codebases. Static analysis has high false positive rates — most flagged patterns are not actual vulnerabilities — but automated tools can scan millions of lines of code, identifying patterns that manual review would miss.
Penetration testing is systematic adversarial testing by human experts who attempt to compromise a system using the same techniques an attacker would. A penetration test scopes what systems are in scope, what techniques are permitted, and what the success condition is. The output is a report of discovered vulnerabilities with severity ratings and remediation recommendations. Penetration testing finds logical vulnerabilities, business logic flaws, and chained attack sequences that automated tools cannot discover.
What Studying This Changes
Security changes how practitioners design and evaluate systems.
The first change is the adversarial mindset: the habit of asking not just “will this work?” but “how could this be broken?” Before deploying any system that handles sensitive data, the security-trained practitioner asks: what happens if an attacker controls the inputs? What if an authenticated user tries to access another user’s data? What if the database is compromised? These questions are not hypothetical; they are anticipated design constraints. Systems designed with these questions from the beginning are more secure than systems to which security is retrofitted.
The second change is an accurate model of trust. Distributed systems have trust boundaries — interfaces between components where one cannot fully trust the other. Security-trained practitioners identify these boundaries explicitly: what does this component trust that it receives from the network? from the user? from external services? from internal services? Appropriate skepticism at each boundary — validating inputs, authenticating sources, authorizing operations — prevents the class of failures where a compromised or malicious component at one trust level propagates damage through trusted channels to other levels.
The third change is cryptographic literacy. The practitioner who understands which cryptographic primitives provide which guarantees can evaluate whether a system’s cryptographic design is sound: is confidentiality provided by authenticated encryption, or only by encryption without integrity? Is the key exchange using forward secrecy? Is the password storage using a slow hash with a per-user salt? These questions have specific, verifiable answers, and getting them wrong has severe consequences.
The fourth change is the ability to participate productively in security analysis. Security reviews, threat models, and penetration test findings are more actionable when developers understand why each finding matters. A finding that “the application does not validate JWTs on the API endpoint” is more alarming to a developer who understands what JWT validation prevents than to one who does not.
Resources
Books and Texts
Anderson’s Security Engineering (3rd ed., 2020, free at cl.cam.ac.uk/~rja14/book.html) is the foundational text. Written by Ross Anderson at Cambridge, it covers cryptography, system security, application security, human factors, physical security, psychology and security, and the organizational context in which security work happens. Its scope and balance are unique: it is simultaneously a technical reference and an analysis of why security fails in practice. Over a thousand pages, it is more reference than cover-to-cover reading; the chapters on cryptography, protocols, and psychology and security are the most essential.
Katz and Lindell’s Introduction to Modern Cryptography (3rd ed., 2020) is the rigorous academic treatment of cryptographic theory. It develops computational security definitions, proves constructions secure under standard assumptions, and covers symmetric and asymmetric cryptography, hash functions, and digital signatures. The mathematical level is undergraduate number theory and probability; the treatment is complete and careful. For practitioners who want to understand the theory underlying the cryptographic building blocks they use, this is the right text.
Aumasson’s Serious Cryptography (2017) is the accessible counterpart to Katz-Lindell — covering the same practical cryptographic topics (random functions, block ciphers, hash functions, public-key cryptography, TLS) with less mathematical formalism and more attention to real implementation concerns. For practitioners who need cryptographic literacy without full theoretical depth, this is the right starting point.
For web application security, the OWASP Testing Guide and OWASP Application Security Verification Standard (both free at owasp.org) are the authoritative references. Stuttard and Pinto’s The Web Application Hacker’s Handbook (2nd ed., 2011) provides the attacker perspective that makes the defensive guidelines comprehensible. Zalewski’s The Tangled Web (2011) provides the deepest treatment of web security, analyzing browser security models with unusual rigor.
For post-quantum cryptography, the NIST post-quantum cryptography standards (free, pqcrypto.org and nist.gov) are the current authoritative references. Bernstein and Lange’s tutorials on post-quantum cryptography provide the accessible introduction.
| Book | Role | Type |
|---|---|---|
| Anderson, Security Engineering (3rd ed., free) | Comprehensive foundational reference | Reference |
| Katz & Lindell, Introduction to Modern Cryptography (3rd ed.) | Cryptographic theory | Depth |
| Aumasson, Serious Cryptography | Accessible cryptographic practice | Entry |
| Crypto 101 (free) | Friendly practical cryptography supplement | Auxiliary |
| Boneh & Shoup, A Graduate Course in Applied Cryptography (free) | Graduate cryptographic theory | Depth |
| OWASP Testing Guide (free) | Web application security | Reference |
| OWASP ASVS (free) | Application security verification | Reference |
| Stuttard & Pinto, The Web Application Hacker’s Handbook (2nd ed.) | Web security attack perspective | Depth |
| Zalewski, The Tangled Web | Web security depth | Depth |
| Saltzer & Schroeder, “The Protection of Information in Computer Systems” (1975, free) | Foundational secure design paper | Depth |
Courses and Lectures
Stanford CS255 (Introduction to Cryptography, Dan Boneh, lecture notes and videos free) is the standard academic cryptography course, covering provable security, symmetric and asymmetric encryption, message authentication, and protocols. Boneh’s Coursera cryptography course covers similar material in a more accessible format.
MIT 6.858 (Computer Systems Security, free on MIT OCW) covers systems security: buffer overflows, web security, network security, and TLS, with hands-on lab assignments that implement and exploit the vulnerabilities being studied. The lab assignments are the most direct way to develop the adversarial intuition that security requires.
OWASP’s WebGoat (free, deliberateyvulnerable application) and HackTheBox (free and paid tiers) provide hands-on practice finding and exploiting vulnerabilities in safe, legal contexts. PortSwigger Web Security Academy (free) provides structured web application security training with challenges.
Cryptopals (cryptopals.com, free) is a set of increasingly difficult cryptographic programming challenges that develop intuition by implementing attacks against flawed cryptographic systems. Working through the first two sets provides more practical cryptographic understanding than reading alone.
| Course | Platform | Type |
|---|---|---|
| Stanford CS255 / Dan Boneh Coursera Cryptography (free) | Stanford / Coursera | Entry |
| MIT 6.858 Computer Systems Security (free) | MIT OCW | Entry |
| PortSwigger Web Security Academy (free) | portswigger.net/web-security | Practice |
| Cryptopals (free) | cryptopals.com | Practice |
| OWASP WebGoat / HackTheBox (free tiers) | Various | Practice |
| pwn.college (free) | pwn.college | Practice |
Practice, Tools, and Current Sources
Burp Suite Community Edition (free, portswigger.net) is the standard tool for web application security testing — an intercepting proxy that lets you inspect and modify HTTP requests between browser and server. Running Burp Suite while working through PortSwigger’s labs makes the mechanics of web attacks concrete.
libsodium (free, libsodium.org) is the recommended cryptographic library for application developers — it exposes a small, safe API that makes correct use of modern cryptographic primitives straightforward. Reading the documentation reveals which primitives are recommended, which are deprecated, and why. Using libsodium in a small project is the practical entry to cryptographic engineering.
Wireshark (§4.3 reference) is equally valuable for security as for networking: capturing and analyzing TLS handshakes reveals the protocol structure; capturing plaintext traffic reveals what is exposed on unencrypted connections. Running Wireshark on your own traffic before and after enabling HTTPS makes the value of transport security concrete.
AFL++ and libFuzzer (both free) provide fuzzing infrastructure. Running a fuzzer on any parser or protocol implementation for a few hours, then examining the crashes, provides direct experience with what automated vulnerability discovery looks like.
The CVE database (cve.mitre.org, free) and the NIST National Vulnerability Database (nvd.nist.gov, free) provide the canonical records of publicly disclosed vulnerabilities. Reading CVE reports for vulnerabilities in software you use — understanding what the vulnerability was, how it was exploited, and how it was fixed — is one of the most efficient ways to develop security judgment.
| Resource | Platform | Type |
|---|---|---|
| Burp Suite Community Edition (free) | portswigger.net | Practice |
| libsodium documentation (free) | libsodium.org | Practice |
| Wireshark for security traffic analysis (free) | wireshark.org | Practice |
| AFL++ / libFuzzer (free) | GitHub | Practice |
| CVE / NVD databases (free) | cve.mitre.org / nvd.nist.gov | Reference |
| Google Project Zero blog (free) | googleprojectzero.blogspot.com | Reference |
| USENIX Security / ACM CCS / IEEE S&P proceedings (free after delay) | Current security research venues | Reference |
Traps
| Trap | Why it misleads | Better response |
|---|---|---|
| Rolling your own cryptography | Cryptographic protocols and primitives look simple and are subtle in ways that are not visible until someone breaks them. Dozens of protocols designed by smart engineers, using correct underlying primitives, have been broken because of subtle compositional errors, padding oracle vulnerabilities, or timing side channels. The graveyard of broken cryptographic protocols includes contributions from experts. | Use TLS for authenticated encrypted channels. Use Signal Protocol for messaging. Use libsodium for everything else. Treat cryptography as infrastructure rather than as something to design. The correct response to “I need to implement X securely” is almost always to find a well-reviewed library for X, not to implement X from scratch. |
| Treating security as a checklist | Checklists cover known issues in anticipated contexts. An adversary with knowledge of your checklist who looks for issues not on it will find them. Security checklists are useful as starting points and inadequate as endpoint. | Use threat modeling to go beyond checklists: for any system component, ask what an adversary could do if they controlled any input, if they compromised any component, if they had the source code. The adversarial perspective generates questions that checklists do not. |
| Confusing obscurity with security | If your system is secure only because attackers don’t know how it works, it is not secure. Adversaries can reverse-engineer software, observe network traffic, read code repositories, and study your system’s behavior. Security that depends on ignorance fails as soon as that ignorance ends. | Apply Kerckhoffs’s principle: design systems to be secure even when the attacker knows everything about the design except the keys or secrets. This is conservative and produces more genuinely secure systems. |
| Treating vulnerabilities as individual bugs rather than systemic failures | Most significant security breaches involve multiple weaknesses that chain together. A SQL injection vulnerability gets an attacker into the database; insufficient privilege separation means the database user can read configuration files; insufficient secrets management means the configuration files contain production cloud credentials. Each individual weakness was manageable; the combination was catastrophic. | Think in attack chains, not individual vulnerabilities. For every vulnerability, ask: what can an attacker do with access to X, and what further access does X enable? Defense in depth matters because individual vulnerabilities are hard to prevent; what you can control is whether each breach provides a foothold for further damage. |
| Dismissing security findings because exploitation seems difficult | “This requires the attacker to already have X” is a common dismissal that ignores that attackers often acquire X in practice. The bar for dismissing a security finding is whether exploitation is practically infeasible (truly impossible with current techniques), not whether it requires multiple steps or certain preconditions. | Evaluate findings based on realistic threat models rather than ideal-case assumptions. Ask: what kind of attacker is the realistic adversary? what resources do they have? are the preconditions something that a motivated attacker could realistically achieve? |
| Treating post-quantum migration as a future concern | “Harvest now, decrypt later” attacks — collecting encrypted traffic today to decrypt when quantum computers become available — are already relevant for data with long-term sensitivity. State actors are plausibly doing this. Post-quantum migration takes years even when actively planned; starting after quantum computers exist is too late for sensitive data. | Assess which systems handle data with long-term sensitivity. For those systems, begin planning post-quantum migration now, even if quantum computers capable of breaking RSA are still years away. The NIST standards are final; the migration path is defined; the question is urgency, not direction. |
中文
安全工程是一门构建能够抵抗对抗性行动的系统的学科——这些行动针对的是机密性、完整性和可用性,发动者是那些主动试图让系统失败的人。对抗性正是它的独特之处。大多数工程处理的是被动失败模式:硬件会磨损,软件会遇到意外边缘情况,网络会丢包。安全工程必须考虑一个聪明、适应性强的对手:他会研究系统,寻找最薄弱点,并加以利用。一个能抵挡预期攻击的防御,对未预期攻击并不提供保证;一个系统只要存在一个漏洞,无论其他部分设计得多好,它都是不安全的。
密码学为这个领域提供数学基础:它提供一组技术,用特定方式转换信息,从而保证机密性、完整性和真实性。它是安全领域中少数能够提供强形式化保证的区域——你可以在特定数学假设下证明,一个计算能力有限的对手无法破解某个方案。但密码学安全不会自动组合成系统安全。一个完全安全的加密算法,如果密钥管理错误,如果认证协议有缺陷,或者如果应用代码可以被诱导去解密攻击者选择的数据,就什么也保护不了。密码学安全与系统安全之间的裂缝,正是大多数实践漏洞存在的地方。
这门学科有三个贯穿始终的组织性问题:如何对秘密和真实性给出数学保证(密码学);如何构建在组件失败、配置错误或遭受主动攻击时仍然保持安全的系统(安全工程);以及如何在对手之前发现漏洞,并足够理解攻击,从而进行防御(攻击性安全与威胁建模)。这三个问题需要不同技能——第一个需要数论和概率,第二个需要系统思维和协议分析,第三个需要对抗性直觉——而合格的安全工作要求三者兼备。
前置知识:计算机网络(§4.3)——协议、TLS 和网络层攻击。操作系统(§4.2)——特权隔离、内存管理和 system calls。离散数学(§2.2)——密码学所需的模运算、数论和概率。复杂性理论(§3.2–§3.3)——密码学安全建立在计算困难性之上。
从军事密码到数学证明
密码学非常古老。Caesar cipher 把每个字母移动三位,用来保护 Julius Caesar 的通信。Vigenère cipher 使用重复密钥来改变移位方式,在 Charles Babbage 和 Friedrich Kasiski 于十九世纪分别破解它之前,曾被认为数百年无法破解。这段历史给出的教训是一贯的:那些在非正式分析下显得安全的密码,在更仔细分析后会被破解。关于密码学安全的直觉并不可靠。
密码学的数学化转变始于第二次世界大战。Alan Turing 在 Bletchley Park 破解德国军方使用的 Enigma cipher 的工作表明,即使是复杂机械密码机,也会受到系统性数学分析的攻击;它们提供的安全性远弱于操作者所相信的程度。Bletchley 行动的规模——最终有超过一万人在那里工作——以及它对战争结果的影响,确立了密码分析是一种工业规模活动,而不是纯粹的智力谜题。
Claude Shannon 1949 年的论文 “Communication Theory of Secrecy Systems” 提供了第一个评估密码学安全的严格数学框架。Shannon 证明,one-time pad——与消息等长、且只使用一次的密钥——在精确定义意义上是完全安全的,并且没有任何使用更短密钥的密码能在无限计算能力的对手面前实现完全安全。这建立了信息论基线:完全安全要求密钥与消息一样长,因此对大多数应用来说并不现实。Shannon 的工作还定义了 confusion 和 diffusion 这两种强对称密码必须实现的性质,为后来 DES 和 AES block cipher 的设计提供了原则。
公钥革命发生在 1976 年。Whitfield Diffie 和 Martin Hellman 的论文 “New Directions in Cryptography” 提出了一个看似不可能的概念:一种 key exchange protocol,使双方可以在不安全信道上建立共享秘密,不需要事先共享秘密,即使有窃听者记录每条消息也不行。这个构造依赖 discrete logarithm problem 的困难性——当你知道 x 时,计算 g^x mod p 很容易,但反过来从结果恢复 x 很难。Diffie 和 Hellman 当时还没有找到实用实现;第二年,Ronald Rivest、Adi Shamir 和 Leonard Adleman 发表了 RSA,这是第一个实用公钥密码系统。RSA 依赖大整数分解的困难性:给定 n = p × q,其中 p 和 q 是大素数,用当前算法从 n 恢复 p 和 q 在计算上不可行。公钥密码学使公共网络上的安全通信成为可能,而不再要求先通过安全信道交换密钥——这正是现代互联网所依赖的基础能力。
1980 年代和 1990 年代互联网安全协议的发展,以每次公开攻击后的增量改进为特征。SSL(Secure Sockets Layer)由 Netscape 于 1994 年开发,用于支持安全 Web 交易,是第一种广泛部署的互联网流量加密协议。SSL 及其后继者 TLS 的每一个版本都会被发布、攻击、修补和改进。SSLv2 有设计缺陷,使 cipher downgrade attacks 成为可能。SSLv3 有 POODLE。TLS 1.0 有 BEAST。发布—攻击—改进的模式,是这个领域的典型特征;当前 TLS 1.3 标准(2018)代表了二十年来对旧版本攻击所积累的学习结果。
软件安全危机随着 1990 年代网络化软件的指数增长到来。1988 年的 Morris Worm 是第一个重大事件:它由 Cornell 研究生 Robert Morris 释放,利用 Unix 的 fingerd daemon 中的 buffer overflow 和 sendmail 中的弱点,传播到数千台计算机,并使大约 10% 的互联网崩溃。这个 worm 并非破坏性设计——它原本是一次展示——但它确立了一点:软件漏洞可以在大规模上被武器化。Aleph One 1996 年发表在 Phrack 上的文章 “Smashing the Stack for Fun and Profit”,系统性讲解了如何利用 buffer overflows,使这种技术被更广泛攻击者掌握。结果是此后二十年持续存在的 buffer overflow exploits,并加剧了 C 和 C++ 软件中的安全危机。
防御回应是一层一层累积起来的。Stack canaries(1998)在返回地址前加入随机值;buffer overflows 必须覆盖它,而程序会检测到这种破坏。Address Space Layout Randomization(ASLR)随机化代码和数据的加载位置,使目标地址更难预测。Non-executable stack and heap(NX/DEP)防止注入的 shellcode 执行。Return-oriented programming(ROP)通过把程序二进制中已有的 code gadgets 串接起来,绕过了 NX——这说明攻击者适应防御的速度快于防御本身。Buffer overflow 攻击与防御之间的军备竞赛,推动了 memory-safe languages 作为 C 的替代方案发展,并最终推动 Rust 的 ownership model 成为在系统语言中提供内存安全的一种方式。
Diffie 和 Hellman 于 2015 年获得图灵奖。相关引文指出,他们 1976 年的论文“被证明是现代互联网的基础”。DH key exchange、RSA、二者的 elliptic curve variants,以及建立在其上的 TLS protocol,构成了几乎每一个互联网上认证加密连接的安全基础设施——HTTPS、SSH、Signal、加密邮件。这一基础设施的安全性依赖计算困难性假设:即大整数分解和离散对数在当前计算机上不可行。这些假设被广泛相信,但并未被证明;这是一个具有重大实践含义的技术限制。
2018 年 1 月披露的 Spectre 和 Meltdown 造成了另一种震动。二者都利用了现代处理器为性能而使用的 speculative execution 机制,通过 timing side channels 从受保护内存中提取信息。这些漏洞并不是传统意义上的 bug——处理器是在按设计工作。安全失败来自 instruction-set architecture 规定的内容(进程之间的隔离)与 microarchitecture 为实现性能所做行为之间的差距。缓解 Spectre 需要修改操作系统、编译器、Web 浏览器和 CPU microcode——而一些缓解措施多年后仍不完整,因为彻底关闭漏洞需要会显著降低性能的体系结构变化。Spectre 证明,一个系统的安全取决于其硬件实现的安全,而不只是其 specification 的安全;几十年来面向性能的硬件优化,已经引入了软件层面看不见的安全漏洞。
后量子密码学迁移是当前主要关切。Shor 算法如果运行在足够大的量子计算机上,就能在多项式时间内分解整数并计算离散对数——从而破解 RSA、Diffie-Hellman 和 elliptic curve cryptography。问题在于这种规模的量子计算机何时会存在,甚至是否会存在。NIST 自 2016 年起运行后量子密码学标准化流程,并于 2024 年发布第一批后量子标准:ML-KEM,源自 CRYSTALS-Kyber,用于 key encapsulation;ML-DSA,源自 CRYSTALS-Dilithium,用于 digital signatures;二者都基于 lattice problems 的困难性,而不是基于整数分解或离散对数。组织现在正在规划并执行从 RSA 和 ECDSA 到这些后量子替代方案的迁移——这是一项多年基础设施工程,用来抵御可能在十年内出现,也可能几十年都不会出现的威胁。
密码学原语、系统安全与对抗性心智
密码学构件
现代密码工程建立在一组经过审查的 primitives 之上——symmetric ciphers、hash functions 和 public-key schemes——并按已在数学假设下证明安全的协议进行组合。实践者的角色不是设计新的 primitives(这是需要大量数学训练的密码学家的任务),而是正确使用已有 primitives。
对称加密使用同一个 key 进行加密和解密。AES(Advanced Encryption Standard)于 2001 年采用,是主导性的对称密码。AES 在 128-bit blocks 上运行,支持 128、192 或 256-bit keys,并被认为能抵抗所有已知实际攻击。对称加密很快——AES-NI 硬件加速可以达到每秒数 GB 吞吐量——但它需要共享 key,从而产生 key distribution problem。Block cipher modes(CBC、GCM、CTR)决定 AES 如何应用到超过 128 bits 的消息上;GCM(Galois/Counter Mode)是 authenticated encryption 的标准,在单次操作中同时提供机密性和完整性。
Cryptographic hash functions 把任意长度输入映射到固定长度输出,并具有几个安全性质:preimage resistance(给定 hash,无法找到产生它的输入)、second preimage resistance(给定一个输入,无法找到另一个具有相同 hash 的不同输入)和 collision resistance(无法找到任意两个具有相同 hash 的输入)。SHA-256 和 SHA-3 是当前标准。Hash functions 出现在整个密码学中:作为 message authentication codes(HMAC),作为 digital signature schemes 的组件,也作为 password storage functions(bcrypt、Argon2 使用故意缓慢的 hash functions 来增加 dictionary attacks 的成本)。
公钥密码学使用一对数学上关联的 keys:用 public key 加密的任何内容只能用 private key 解密;用 private key 签名的任何内容可以用 public key 验证。RSA 和 elliptic curve Diffie-Hellman(ECDH)提供 key encapsulation;ECDSA 和 Ed25519 提供 digital signatures。新系统更偏好 elliptic curve variants,因为它们可以在短得多的 key lengths 下提供与 RSA 等价的安全性,从而减少带宽和计算。
关键原则是:这些 primitives 应当通过设计良好的协议和库使用,而不是从零组装。TLS 1.3 是用于 authenticated key exchange 和加密通信的标准协议。Signal Protocol 是端到端加密消息的标准。libsodium 是在 TLS 覆盖之外实现密码学操作的标准库。每一个都由密码学家设计,经过广泛审查,并在发现弱点后更新。另一条路——设计新协议或直接实现 primitives——有一贯历史:即使单个组件本身是可靠的,也会因为微妙组合错误而破坏安全。
安全工程心智
安全工程区别于普通软件工程之处,在于它要求对抗性视角。构建可靠系统的工程师会问:什么可能意外出错?安全工程师还要问:如果对手完全知道系统设计,他能故意做什么?Kerckhoffs’s principle 于 1883 年为军事密码学提出,它认为一个密码系统即使除 key 以外的所有内容都公开,也应当保持安全。现代解释更宽:系统安全不应依赖于别人不知道系统如何工作。
Threat modeling 是系统性识别对抗性失败可能性的实践。STRIDE framework(Microsoft Research,1990 年代后期)把威胁分为 Spoofing(冒充)、Tampering(篡改)、Repudiation(否认行为)、Information Disclosure、Denial of Service 和 Elevation of Privilege。对任何系统组件应用 STRIDE,都可以生成一组系统性威胁类别。其输出不是 checklist,而是一组问题:哪些威胁相关,哪些缓解措施适用,以及还剩下什么 residual risk。
Least privilege 是一条设计原则:每个组件都应只拥有它所需的能力。一个只需要读取静态文件的 Web server process 不应以 root 身份运行;一个用于读取的 database connection 不应拥有写权限;一个只需要调用某个 API 的 microservice 不应拥有另一个 API 的 credentials。违反 least privilege 会使被攻破组件造成超出其预期范围的损害。Defense in depth 是互补原则:每条安全边界都可能失败,因此系统应当被设计成,只有多条边界同时失败时,最重要性质才会被破坏。
OWASP Top 10 记录了最常见的应用安全漏洞。Injection——尤其是 SQL injection,也就是把用户提供的输入解释为代码——利用的是未能区分数据与命令。Authentication 和 access control failures——弱密码、session management errors、缺少 authorization checks——会允许未授权访问。Cryptographic failures——使用过时算法、不足的 key lengths、不安全证书处理——会破坏机密性。Cross-site scripting(XSS)——向其他用户浏览的网页注入 JavaScript——利用的是未能 sanitize output。每一类都有标准缓解措施;这些失败仍然持续存在,是因为当开发者没有以对抗性方式思考时,它们很容易被引入。
发现漏洞:Fuzzing、渗透测试与代码审查
攻击性安全是在对手之前发现漏洞的实践。要足够理解攻击以便预防,就必须学习像攻击者一样思考。
Fuzzing——生成随机或结构化的无效输入,并观察程序是否崩溃或表现出意外行为——是最自动化、最可扩展的漏洞发现技术。American Fuzzy Lop(AFL)和 libFuzzer 等工具使用 coverage-guided mutation:它们追踪每个输入触发了哪些代码路径,并优先选择能到达新路径的变异。Fuzzing 已经在浏览器、codecs、parsing libraries 和 OS kernels 中发现了数千个严重漏洞。它的限制是,它发现的是 crashes 和 assertion failures,而不是逻辑漏洞或授权缺陷。
Static analysis tools 在不运行代码的情况下检查代码,标记与漏洞相关的模式:可能溢出的 buffer accesses、format string vulnerabilities、使用已废弃函数、null pointer dereferences。CodeQL(GitHub)、Semgrep 和商业 analyzers 等工具可以跨大型代码库识别这些模式。Static analysis 的 false positive rates 很高——多数被标记模式不是真实漏洞——但自动化工具可以扫描数百万行代码,识别人类审查会错过的模式。
Penetration testing 是由人类专家进行的系统性对抗测试,他们会使用攻击者会使用的技术尝试攻破系统。一次 penetration test 会规定哪些系统在范围内、允许哪些技术,以及成功条件是什么。其输出是一份报告,列出发现的漏洞、严重程度评级和修复建议。Penetration testing 能发现逻辑漏洞、business logic flaws 和自动化工具无法发现的 chained attack sequences。
学习这一部分会改变什么
安全会改变实践者设计和评估系统的方式。
第一个变化,是对抗性心智:习惯于不只问“这能不能工作?”,还问“它会如何被打破?” 在部署任何处理敏感数据的系统之前,受过安全训练的实践者会问:如果攻击者控制输入会怎样?如果一个已认证用户试图访问另一个用户的数据会怎样?如果数据库被攻破会怎样?这些问题不是假想,而是预期设计约束。从一开始就围绕这些问题设计的系统,比事后补安全的系统更安全。
第二个变化,是准确的信任模型。分布式系统有 trust boundaries——组件之间的接口,在这些接口处,一方不能完全信任另一方。受过安全训练的实践者会显式识别这些边界:这个组件相信自己从网络收到的是什么?从用户收到的是什么?从外部服务收到的是什么?从内部服务收到的是什么?在每条边界上保持适当怀疑——验证输入、认证来源、授权操作——可以防止这类失败:一个处于某个信任层级的被攻破或恶意组件,通过受信通道把损害传播到其他层级。
第三个变化,是密码学素养。理解哪些 cryptographic primitives 提供哪些保证的实践者,能够评估一个系统的密码学设计是否可靠:机密性是由 authenticated encryption 提供,还是只有没有完整性的 encryption?Key exchange 是否使用 forward secrecy?Password storage 是否使用带 per-user salt 的 slow hash?这些问题有具体、可验证的答案,而答错会产生严重后果。
第四个变化,是能够有成效地参与安全分析。Security reviews、threat models 和 penetration test findings,会在开发者理解每个发现为什么重要时更可操作。一条 “application does not validate JWTs on the API endpoint” 的发现,对理解 JWT validation 防止什么的开发者来说,要比对不理解的人更令人警惕。
资源
书籍与文本
Anderson 的 Security Engineering(第 3 版,2020,可在 cl.cam.ac.uk/~rja14/book.html 免费获取)是基础文本。它由 Cambridge 的 Ross Anderson 写成,覆盖密码学、系统安全、应用安全、人因、物理安全、心理学与安全,以及安全工作发生其中的组织语境。它的范围和平衡性很独特:它既是技术参考,也是对安全为什么在实践中失败的分析。全书超过一千页,更适合作为参考,而不是从头读到尾;其中关于密码学、协议、心理学与安全的章节最重要。
Katz 和 Lindell 的 Introduction to Modern Cryptography(第 3 版,2020)是密码学理论的严格学术处理。它发展计算安全定义,在标准假设下证明构造安全,并覆盖对称与非对称密码学、hash functions 和 digital signatures。数学水平是本科数论和概率;处理完整且谨慎。对于希望理解自己所用密码学构件背后理论的实践者来说,这是正确文本。
Aumasson 的 Serious Cryptography(2017)是 Katz-Lindell 的易读对应物——它覆盖相同的实践密码学主题(random functions、block ciphers、hash functions、public-key cryptography、TLS),但数学形式化更少,也更关注真实实现问题。对于需要密码学素养但不需要完整理论深度的实践者来说,这是正确起点。
对于 Web 应用安全,OWASP Testing Guide 和 OWASP Application Security Verification Standard(二者均可在 owasp.org 免费获取)是权威参考。Stuttard 和 Pinto 的 The Web Application Hacker’s Handbook(第 2 版,2011)提供攻击者视角,使防御指南变得可理解。Zalewski 的 The Tangled Web(2011)提供最深入的 Web 安全处理,以少见严谨性分析浏览器安全模型。
对于后量子密码学,NIST post-quantum cryptography standards(可在 pqcrypto.org 和 nist.gov 免费获取)是当前权威参考。Bernstein 和 Lange 关于后量子密码学的教程提供了易读入门。
| 书籍 | 作用 | 类型 |
|---|---|---|
| Anderson, Security Engineering(第 3 版,免费) | 综合基础参考 | 参考 |
| Katz & Lindell, Introduction to Modern Cryptography(第 3 版) | 密码学理论 | 深入 |
| Aumasson, Serious Cryptography | 易读的密码学实践 | 入门 |
| Crypto 101(免费) | 友好的实践密码学补充 | 辅助 |
| Boneh & Shoup, A Graduate Course in Applied Cryptography(免费) | 研究生密码学理论 | 深入 |
| OWASP Testing Guide(免费) | Web 应用安全 | 参考 |
| OWASP ASVS(免费) | 应用安全验证 | 参考 |
| Stuttard & Pinto, The Web Application Hacker’s Handbook(第 2 版) | Web 安全攻击视角 | 深入 |
| Zalewski, The Tangled Web | Web 安全深度 | 深入 |
| Saltzer & Schroeder, “The Protection of Information in Computer Systems”(1975,免费) | 安全设计奠基论文 | 深入 |
课程与讲座
Stanford CS255(Introduction to Cryptography,Dan Boneh,讲义和视频免费)是标准学术密码学课程,覆盖可证明安全、对称与非对称加密、message authentication 和协议。Boneh 的 Coursera cryptography course 以更易读形式覆盖类似材料。
MIT 6.858(Computer Systems Security,MIT OCW 免费)覆盖系统安全:buffer overflows、Web security、network security 和 TLS,并配有动手实验,用来实现和利用正在学习的漏洞。实验是发展安全所需对抗性直觉的最直接方式。
OWASP 的 WebGoat(免费,deliberately vulnerable application)和 HackTheBox(免费与付费层)提供在安全、合法语境中寻找和利用漏洞的动手练习。PortSwigger Web Security Academy(免费)提供带挑战的结构化 Web 应用安全训练。
Cryptopals(cryptopals.com,免费)是一组逐步变难的密码学编程挑战,通过实现对有缺陷密码系统的攻击来发展直觉。完成前两组,比单纯阅读更能产生实践密码学理解。
| 课程 | 平台 | 类型 |
|---|---|---|
| Stanford CS255 / Dan Boneh Coursera Cryptography(免费) | Stanford / Coursera | 入门 |
| MIT 6.858 Computer Systems Security(免费) | MIT OCW | 入门 |
| PortSwigger Web Security Academy(免费) | portswigger.net/web-security | 实践 |
| Cryptopals(免费) | cryptopals.com | 实践 |
| OWASP WebGoat / HackTheBox(免费层) | Various | 实践 |
| pwn.college(免费) | pwn.college | 实践 |
实践、工具与当前资料
Burp Suite Community Edition(免费,portswigger.net)是 Web 应用安全测试的标准工具——一个 intercepting proxy,可以让你检查并修改浏览器与服务器之间的 HTTP requests。做 PortSwigger labs 时同时运行 Burp Suite,会使 Web 攻击机制变得具体。
libsodium(免费,libsodium.org)是推荐给应用开发者的密码学库——它暴露一个小而安全的 API,使正确使用现代 cryptographic primitives 变得直接。阅读文档可以看到哪些 primitives 被推荐、哪些已废弃,以及为什么。在小项目中使用 libsodium,是进入密码工程实践的入口。
Wireshark(§4.3 已引用)对安全和对网络同样有价值:捕获并分析 TLS handshakes 可以揭示协议结构;捕获明文流量可以揭示未加密连接暴露了什么。在启用 HTTPS 前后对自己的流量运行 Wireshark,可以使 transport security 的价值变得具体。
AFL++ 和 libFuzzer(二者均免费)提供 fuzzing 基础设施。对任何 parser 或 protocol implementation 运行 fuzzer 几个小时,再检查 crashes,可以直接体验自动化漏洞发现是什么样子。
CVE database(cve.mitre.org,免费)和 NIST National Vulnerability Database(nvd.nist.gov,免费)提供公开披露漏洞的规范记录。阅读你所用软件的 CVE reports——理解漏洞是什么、如何被利用、如何被修复——是培养安全判断力最高效的方式之一。
| 资源 | 平台 | 类型 |
|---|---|---|
| Burp Suite Community Edition(免费) | portswigger.net | 实践 |
| libsodium documentation(免费) | libsodium.org | 实践 |
| Wireshark for security traffic analysis(免费) | wireshark.org | 实践 |
| AFL++ / libFuzzer(免费) | GitHub | 实践 |
| CVE / NVD databases(免费) | cve.mitre.org / nvd.nist.gov | 参考 |
| Google Project Zero blog(免费) | googleprojectzero.blogspot.com | 参考 |
| USENIX Security / ACM CCS / IEEE S&P proceedings(延迟后免费) | 当前安全研究会议 | 参考 |
陷阱
| 陷阱 | 为什么会误导 | 更好的回应 |
|---|---|---|
| 自己造密码学 | 密码学协议和 primitives 看起来简单,但其微妙之处在被人攻破前并不可见。许多由聪明工程师设计、并使用正确底层 primitives 的协议,都因为微妙组合错误、padding oracle vulnerabilities 或 timing side channels 被破解。被破解的密码学协议墓地里,也有专家的作品。 | 对认证加密信道使用 TLS。对消息通信使用 Signal Protocol。其他情况使用 libsodium。把密码学当成基础设施,而不是自己设计的东西。面对“我需要安全实现 X”时,正确回应几乎总是寻找一个经过充分审查的 X 库,而不是从零实现 X。 |
| 把安全当成 checklist | Checklists 覆盖的是预期语境中的已知问题。一个了解你 checklist 的对手,如果寻找 checklist 之外的问题,就可能找到它们。安全 checklists 可以作为起点,但不能作为终点。 | 用 threat modeling 超越 checklists:对任何系统组件都问,如果对手控制任意输入,如果对手攻破任意组件,如果对手拥有源代码,他能做什么?对抗性视角会生成 checklist 不会生成的问题。 |
| 把 obscurity 混同为 security | 如果你的系统只有在攻击者不知道它如何工作时才安全,那它并不安全。对手可以逆向工程软件,观察网络流量,阅读代码仓库,并研究系统行为。依赖无知的安全,一旦无知结束,就会失败。 | 应用 Kerckhoffs’s principle:即使攻击者知道除 keys 或 secrets 之外的所有设计细节,系统也应保持安全。这种保守做法会产生更真实的安全性。 |
| 把漏洞当成单个 bug,而不是系统性失败 | 大多数重大安全事故都涉及多个弱点链式组合。一个 SQL injection vulnerability 让攻击者进入数据库;不足的 privilege separation 使数据库用户可以读取配置文件;不足的 secrets management 使配置文件中包含生产 cloud credentials。每个单独弱点都似乎可控;组合起来就是灾难。 | 用 attack chains 思考,而不是用单个漏洞思考。对每个漏洞都问:攻击者获得 X 访问后能做什么?X 又会进一步开启哪些访问?Defense in depth 重要,是因为单个漏洞很难完全防止;你能控制的是每次破口是否会成为进一步破坏的 foothold。 |
| 因为利用看起来困难而否定安全发现 | “这要求攻击者已经拥有 X” 是一种常见否定方式,但它忽视了攻击者在实践中经常能获得 X。否定一个安全发现的标准,应当是利用在实践中不可行(以当前技术确实不可能),而不是它需要多个步骤或某些前置条件。 | 根据现实 threat models 评估发现,而不是根据理想化假设。问:现实对手是哪类攻击者?他们有什么资源?这些前置条件是否是有动机的攻击者现实中能够达成的? |
| 把后量子迁移当成未来问题 | “Harvest now, decrypt later” 攻击——今天收集加密流量,等量子计算机可用时解密——已经与长期敏感数据相关。国家级行为者很可能正在这样做。即使主动规划,后量子迁移也需要多年;等量子计算机出现后再开始,对敏感数据已经太晚。 | 评估哪些系统处理长期敏感数据。对这些系统,即使能够破解 RSA 的量子计算机仍然还有多年,也应现在开始规划后量子迁移。NIST 标准已经最终确定;迁移路径已经定义;剩下的问题是紧迫性,而不是方向。 |