Summary
Highlights
The lecturer introduces James Mickens as a co-lecturer and four TAs. The course aims to teach students how to build secure systems, understand why systems are insecure, and how to improve them. Lectures will often revolve around research papers, which students are expected to read and submit questions about prior to class discussions. The importance of asking questions during lectures is stressed, as security is detail-oriented. Lab assignments, using a variety of programming languages, will provide hands-on experience in exploiting and defending web servers. The first lab focuses on C and Assembly for exploiting buffer overflows. Lectures are being videotaped and will be available online. Piazza is used for online questions. Students are cautioned that not all technically possible actions are legal, especially when conducting security research, and should consult with instructors if in doubt.
Security is defined as achieving a goal in the presence of an adversary. A secure system functions regardless of a 'bad guy's' attempts to disrupt it. Security is broken down into three main components: policies (the goals to achieve, e.g., confidentiality, integrity, availability), threat models (assumptions about the adversary's capabilities), and mechanisms (the software or hardware implementations that enforce policies under the defined threat model). The iterative nature of security design, involving fixing weakest links and refining threat models and mechanisms, is highlighted. The course will push systems to their breaking points to understand their limitations and appropriate use cases. Good security mechanisms can enable new functionalities, such as running native code securely in web browsers without explicit user permission.
Security failures often stem from errors in policy definition. Account recovery questions are a prime example: they weaken security by expanding the conditions under which an account can be accessed beyond just knowing the password. The case of Mat Honan's account compromise is used to illustrate how policies can interact across different systems (Gmail, Apple's me.com, Amazon) to create vulnerabilities. Each system, in isolation, seemed to implement reasonable policies, but their combined effect allowed an attacker to chain weaknesses, ultimately compromising his accounts. This highlights the complexity of reasoning about security in interconnected systems.
Threat models can be flawed in several ways. Human factors, such as users picking weak passwords or clicking malicious links, are often overlooked assumptions. Threat models also change over time; an assumption that was valid in the past (e.g., 56-bit DES keys) may become invalid as technology advances. Modern examples include the revelation of government hardware backdoors, which fundamentally alter assumptions about system trust. The reliance on hundreds of certificate authorities (CAs) in SSL/TLS, where compromising just one CA can undermine the security of many websites, is presented as a design based on a flawed threat model assuming all CAs are trustworthy. The DARPA secure OS project of the 1980s showed how overlooking the security of source code storage could lead to system compromise, emphasizing the need to consider all possible attack vectors.
Mechanism failures are the most pervasive problems in security. The recent iCloud vulnerability is discussed: different interfaces to the service had varying security implementations. The 'Find My iPhone' interface lacked brute-force protection, allowing attackers to guess passwords and access sensitive user data. Another example is Citibank's website, which failed to verify user ID against logged-in credentials when accessing account information, demonstrating a missing access control check. The Bitcoin key generation vulnerability on Android devices is explained, where a bug in the SecureRandom() Java API (specifically, not seeding the pseudo-random number generator) led to predictable private keys, allowing theft of Bitcoins. These examples underscore how even minor programming errors can have catastrophic security implications.
Buffer overflows are a classic mechanism failure, particularly prevalent in C-language software. The lecture demonstrates a simple C program with a `gets()` function that allows a buffer overflow when processing overly large input. Using a debugger, the overflow is shown to overwrite the stack, including the return address of the function. This allows an attacker to control the program's execution flow. The potential to redirect execution to arbitrary code (shellcode) injected by the attacker into the buffer is explained. The concept of non-executable stacks as a defense mechanism is introduced, but also how it can be bypassed using 'return-to-libc' attacks, where execution is redirected to existing code within the program or system libraries. The importance of minimizing the 'trusted computing base' is suggested as a solution to these persistent mechanism problems.