“Exploration is the engine that drives innovation.” —Edith Widder
This appendix contains some ideas for further exploration, open questions, and challenges for readers who want to go beyond the material covered in this book.
Chapter 1, Foundations
- The book focuses on information security in conventional computer systems, but appliances and devices also run on software, and these are increasingly connected to the internet. How do we extend principles such as C-I-A to secure software that interacts with the physical world?
Chapter 2, Threats
- Threat model an existing software design, or just one component of a large system.
- For fun, threat model a favorite movie or scene from a book where adversaries battle over a prized asset.
Chapter 3, Mitigations
- Write helper functions to limit the exposure of sensitive data in memory as described in “Minimize Data Exposure” on page XX.
- Intentionally code a Confused Deputy and try to exploit it, or challenge a colleague to do so. Fix the vulnerability and confirm the code is secure.
- Design a library to enforce an extensible access policy for an existing data access API.
Chapter 4, Patterns
- Take an existing design, or undertake a new one, and see how many of the chapter’s patterns you can use to make it as secure as possible.
- What additional security patterns and anti-patterns can you think of? Keep a running list, adding to the ones presented in the chapter, and share them with colleagues.
- Are allow lists always better than block lists? Think of an exception, or explain why none exist.
Chapter 5, Cryptography
- An easy way to play around with real crypto tools is with the OpenSSL command line (https://wiki.openssl.org/index.php/Main_Page). You can use it to experiment with symmetric and asymmetric crypto, as well as MACs (called digests in
openssl(1)
), or even create and check your own certificates. - Find a high-quality crypto library and try using it to implement the basic operations described in the chapter. How was the API in terms of ease of use, and how confident are you that your implementation is secure?
- If the previous exercise proved difficult, how could you redesign the API to be easier to use, as well as more foolproof?
- Code the crypto API improvements you thought of, or wrap the original library to provide a better API.
Chapter 6, Secure Design
- Explore Google’s design document writing guidance (https://www.industrialempathy.com/posts/design-docs-at-google/).
- If you haven’t written a software design document before, try it out the next time you get an opportunity to do so (making it as informal and high level as you like).
- If you work on a codebase that has no written design document, retroactively create one. For large systems, create designs for one component at a time, focusing on whatever components are most important to security or otherwise of interest.
Chapter 7, Design Reviews
- Find existing designs and review them as a learning exercise. Don’t just look for vulnerabilities; create a broad assessment of both strengths and weaknesses, including places where security matters most, ways the design enhances security, mitigation alternatives, and ways in which security could be improved or made more usable.
- Share and discuss your findings from the preceding exercise with colleagues.
Chapter 8, Secure Programming
- To get a feel for realistic examples of security vulnerabilities, look for security bugs that have already been found and fixed in your codebase or in open source software projects. I suggest focusing on open source projects because vulnerabilities are usually described in detail and you can see the code. The US Department of Homeland Security sponsors a large database of publicly known vulnerabilities (https://cve.mitre.org/). The Chromium bug database (https://bugs.chromium.org/p/chromium/issues/list/) is another good source of public vulnerabilities. A good starting point is to filter these databases for fixed security bugs so you can see the actual code changes.
- Underhanded coding, also known as obfuscated coding, is the fine art of using footguns and other trickery to write code that works differently from what anyone inspecting the code would expect. Underhanded coding contests challenge programmers to show off their creativity in pushing programming languages to their limits. But the same techniques used to camouflage malicious code as benign can also, if stumbled upon inadvertently, become footguns. Check out these sites for a start, or try to craft your own: http://www.underhanded-c.org/ and https://underhandedcrypto.com/.
Chapter 9, Low-Level Coding Flaws
- Why don’t languages that provide fixed-width integer types provide any mechanism to detect overflow? Would it help? If so, how would you extend the C language to take advantage of it?
- Explore how analysis tools such as Valgrind detect issues with memory management (see https://valgrind.org/docs/manual/mc-manual.html).
- Write a little program that includes a few kinds of memory management vulnerabilities, such as both read and write buffer overflows. Use a tool like Valgrind to see if it detects the bugs. Try varying the code to make it harder for the tool to analyze, and see if you can sneak a bug past it.
Chapter 10, Input Validation
- Identify the untrusted inputs on the main attack surface of the system you work on and see how thoroughly input validation is implemented and tested.
- If you find that untrusted inputs may represent vulnerabilities, implement input validation.
- Often, input validation for a system is repetitive. Look for opportunities to use common code or helper functions to handle it reliably. Consider ways of baking input validation into frameworks so it cannot be accidentally forgotten.
Chapter 11, Web Security
- Write security requirements for a component that creates and authenticates a web session. Design and threat model it, and find a friend to security review it.
- Build an implementation of your web session into a simple web app. Try to impersonate another session, or steal the necessary session state. Better yet, find a friend to “attack” your implementation.
- Add a CSRF protection mechanism to the component and test it in your web app.
- Explore ways of securing web sessions without the use of cookies as an experiment to understand the essence of the security challenge.
- Find the source code (and ideally, a written design document) for a web framework and learn how it implements sessions, prevents XSS and CSRF vulnerabilities, and ensures that HTTPS secures all web interactions. By threat modeling or other means, can you find any vulnerabilities? If you want to try attacking it, put up your own test server to do that.
Chapter 12, Security Testing
- In the codebase of your choice, locate some area where security is important and look for additional security test cases that should be added. Write and contribute new security test cases.
- Consider this alternative example of a vulnerability in GotoFail that the security tests we wrote wouldn’t catch—in place of the extra
goto fail;
, instead insert the line:if (expected_hash[0] == 0x23) goto fail;
This sort of technique might be used to secretly include a vulnerability that requires a specific trigger as a kind of backdoor. Detecting this would require a test case with an expected hash whose first byte was 0x23. How could you write tests to detect this sort of vulnerability without knowing the specifics? - Check out an old version of an open source software project with a known vulnerability. Run the test suite and ensure that all tests pass. Write a security regression test to confirm the vulnerability. Sync up to the next version that fixes the vulnerability, merging in your regression test. Your security regression test should now pass; if not, fix it. Then check for additional, related vulnerabilities in the latest version.
Chapter 13, Secure Development Best Practices
- Explore easy ways to make incremental code quality improvements, such as using lint or code scanning tools, as well as checking the test coverage of error and exception handling.
- See how well the security aspects of your codebase are documented and make needed improvements.
- Whenever you do code reviews, put on your security hat for another pass when applicable.
- Consider security when you do bug triage, or perhaps browse your bug database with security in mind to see if bugs that have security implications are being punted.
Chapter 14, Looking Ahead
- Look for opportunities to make improvements along the lines mentioned in the chapter, even if this means taking small steps: broader security participation, earlier integration of a security perspective and strategy, reduction or management of complexity, improving transparency about security practice, and so on.
- Identify a unique security challenge and design and develop a reusable component that addresses it.
- Pursue other ideas of your own to raise the security bar and spread the word.