Software Security

There are many dimensions of security, but one of the biggest is that of developing secure software.

Secure Software

We can come up with several dimensions of security:

Personal security (people)
Information security (data)
Computer security (systems)
Software security (code)

We have to practice security in hardware, in software, and at the human level. We can employ technical solutions such as passwords, tokens, encryption, access control lists, permission matrices, antivirus software, firewalls, whitelists, blacklists, and security zones. We can train users to be security conscious.

But did you know that malicious actors can often get around many of these technical security “solutions” and do way more damage just by exploiting poorly crafted and buggy code? Because that's where 90% of reported security incidents come from. NINETY. PERCENT.

Secure Software

A lot of people think that security is mostly about defenses such as those mentioned above. But attackers can get around those! Software security considers the code: it is about disciplined software design and development. Build the software right the first time: Prevention is the thing to shoot for; detection and reaction are more expensive.
Exercise: Research the Heartbleed bug. Could it have been stopped by malware detectors, DoS detectors, packet filters, antivirus scanners, smart routers, operating system permissions? No? What was the problem?

The field of secure software development is concerned with the software development lifecycle (requirements definition, analysis, design, development, testing, configuration, deployment, maintenance), and security concerns in each phase, namely:

And of course, knowledge of known vulnerabilities and classes of attacks (injection, denial-of-service, out-of-range values, buffer overflows) are important too. We’ll need to learn about:

The Software Security Mindset

There are three big ideas that comprise the proper mindset for successful secure software development:

Build Security In
Define Security Requirements Properly
Defend Deeply and Broadly

Build Security In

Security concerns must always be on your mind in everything you do. It is not separate from software development. It is an integral part of software development. Why?

Defining Security Requirements

Sometimes requirements definition is hard. It is a learned skill to understand which are the actual requirements and which are just technical details. You can learn it, though. Which of these sounds correct as a requirement?

drakesecurityrequirements.jpeg

That was easy, right? Here’s another way to look at this issue: Don’t get too caught up in the fancy crypto and fancy math and digests and hashing at the expense of forgetting some basics (like not authenticating each endpoint in a web service).

Story Time

There was this web app where users had to login to get to pages in the app, and these pages linked to all sorts of images and other assets, which, you guessed it, just used plain old img elements. So ... (story continues in class)

To check that the requirements have been satisfied, your development process should included simulated attacks (penetration testing), fuzz testing, and maybe even correctness proofs.

Defending in Depth and in Breadth

The idea of “defense in depth” is known in circles outside software security. Here’s the idea, from the Viega and McGraw book:

The idea behind defense in depth is to manage risk with diverse defensive strategies, so that if one layer of defense turns out to be inadequate, another layer of defense will hopefully prevent a full breach ... Security cameras alone are a deterrent for some. But if people don't care about the cameras, then a security guard is there to physically defend the bank with a gun. Two security guards provide even more protection. But if both security guards get shot by masked bandits, then at least there's still a wall of bulletproof glass and electronically locked doors to protect the tellers from the robbers. Of course if the robbers happen to kick in the doors, or guess the code for the door, at least they can only get at the teller registers, since we have a vault protecting the really valuable stuff. Hopefully, the vault is protected by several locks, and cannot be opened without two individuals who are rarely at the bank at the same time. And as for the teller registers, they can be protected by having dye-emitting bills stored at the bottom, for distribution during a robbery.

Layers in information security will include firewalls, anti-virus software, crypto, authentication mechanisms, authorization rules, signatures, and maybe even correctness proofs. Some of the defenses you will write yourself; others will come from libraries. If anything attacks do get though, you should have intrusion detection and forensic tools to help contain the breach and make repairs.

Exercise: Research canaries and honeypots. How do these help with intrusion detection? What else are they good for?

While depth defense is concerned with putting up a series of defenses that an attacker needs to break through, breadth defense understands an attack can go after many parts of a system. Fore example, think of ways can a denial of service, or a restriction in availability occur? This list can get you started:

Now, how many of these come from a poor architecture? Poor coding? Attacker knowledge? They might come from all three, so we need to guard against these at multiple levels. Profile the code. Fuzz test!

Principles

Part of the mindset of doing security involves living a few basic principles that will become self-evident to you over time. These include:

✅ Set Trust Boundaries
Protect resources with a series of gates, e.g., “this resource (database entity, API endpoint, private subsystem, etc.) is gated by X.” Gates include things like “only logged in users,” or “users with a particular permission” or “packets originating from a given IP range.” You can set up zones, too, and distinguish, say code on-the-edge (user-facing, untrusted) from code on-the-inside (data you control and can trust).
✅ Design for Least Privilege
Give every user, subsystem, object, function, the absolute least privilege (permission) necessary to do its job. Always make secure the default, and open up little by little explicitly as needed.
✅ Maintain Integrity
Restrict the domain of entities, e.g., a plain old int or string is often bad. Have preconditions, postconditions, and invariants enforced in the code. Treat every piece of input as a threat.
✅ Fail Fast
Identify problems right away! Don’t let inconsistencies worm their way through the data. If something can’t be done, don’t do it. If you crash in the middle of an operation, clean up!
✅ Audit
Log everything that happens, but don’t log any secrets. Also keep the logs secure!
✅ Don’t Rely on Secrets
The more secrets you have, the more likely they will leak or be guessed. People might even divulge them (accidentally, maliciously, or because they are physically threatened).
✅ Keep It Simple
Complexity introduces more possibility for errors and makes it hard to reason about security. All added bits of complexity introduces new attack vectors. The more inputs you have, the greater the attack surface. The more complex of inputs you allow (e.g., markup or formatted text or documents), the greater the attack surface. Attackers love going after your inputs.
✅ Prevent Leaks
Don't leak error information. No PHP or SQL dumps on a user-visible error pages. Don’t let error information allow attackers to guess. Never say “Incorrect password” since that might imply the attacker guessed a user name. Prefer errors like “Not found” for permission errors (since an attacker might be trying to guess user names or resource ids).
Exercise: Research the phrase “Security Through obscurity” and make a list of all the reasons it is a bad thing.
Did you notice

None of these principles mentioned specific attacks like XSS or DDoS or Billion Laughs or SQL Injection.

That’s the point.
Exercise: The list of principles above is not the only one out there. Here are three others to read: Which if any of principles from these lists are left out of the list above?

Tactics

Getting impatient wth all this high-level stuff? Wondering what to do in practice? Hang on, we’ll get there. In the meantime, here’s a list of some lower-level strategies and tactics:

See this amazing OWASP Secure Coding Practices Quick Reference Guide. It has a great checklist.

How about details? Where can we find examples of good (compliant with security guidelines) and bad (non-compliant) code? Next section!

Guidelines and Standards

It’s good to familiarize yourself with publications made by the pros. These can be (1) collections of known vulnerabilities and weakness, or (2) guidelines and coding standards that you follow so that the code you write is secure. Some are language-specific and some are pretty general. Here are some good ones:

Many organizations provides summaries of many of these sources, which can be nice to browse before diving into the dense publications themselves. For example, Perforce has useful summaries and overviews of Software security standards in general, The CWE, The CVE, OWASP, CERT C, ISO 26262, and MISRA C and C++.

Learning Software Security

Here are a few places to learn about Software Security as a discipline:

Learning by Doing is Crucial

Therefore you are expected to create an account on a CTF site and capture a few dozen flags throughout this course.

Although designed for high school students, PicoCTF is just fine! After signing up and becoming acquainted with the site, head over the playlists page and work through the playlist called “The Beginner's Guide to the picoGym”.

You should also ready the entirety of The CTF Primer.

Recall Practice

Here are some questions useful for your spaced repetition learning. Many of the answers are not found on this page. Some will have popped up in lecture. Others will require you to do your own research.

  1. How does software security relate to computer (cyber) security?
    Software security is a subset of computer security.
  2. What kinds of things are computer security but not software security?
    access control lists, permission matrices, antivirus software, firewalls, whitelists, blacklists, and security zones.
  3. What percentage of reported security incidents result from exploits against defects in the design or code of software?
    90%.
  4. What are the phases in the software development lifecycle (SDLC)?
    Ideation • Planning • Requirements Analysis and Definition • Architecture and Design • Implementation • Static Analysis and Code Reviews • Testing • Documentation • Integration • Deployment • Maintenance • Evaluation • Retirement • Disposal.
  5. What are the two broad areas of software security?
    (1) Low-level security, concerned with memory attacks, and (2) system security, concerned with large-scale, multi-user applications like webapps.
  6. What are the three pillars of the software security mindset?
    Build security in. Define security requirements properly. Defend deeply and broadly.
  7. What does it mean to “build security in”?
    It means to design and implement the core domain objects and core business logic to prevent exploits, rather than leaving security concerns to separate libraries with ad-hoc solutions.
  8. “Secure software is better than ________________ software.”
    Security.
  9. Why might you not even need specific security solutions like, say, an XSS Sanitizer?
    If you define your domain objects to be restricted to certain character patterns, XSS attacks can be completely avoided.
  10. What might happen if you don’t build security in, and you give the system to the security experts and pen testers after you finish development?
    The pentesters will find a ton of problems and tell you not to release the project without a massive overhaul.
  11. What might happen if you don’t build security in, and you end up just deploying the system as-is?
    You will get hacked and destroyed.
  12. Secure software development is not really about ethical hacking and penetration testing, but rather about ________________.
    Disciplined software design and development.
  13. What are some coding constructs that increase security?
    Immutability, encapsulation, error isolation, validation.
  14. What are techniques for making sure improving your confidence that your code is secure?
    Manual code reviews and Linters.
  15. What kind of problems do people make when defining security requirements?
    They sometimes mistake a technique or use case for a bigger concern, e.g., saying a login page is a requirement, when the actual requirement is not to divulge information to the wrong user.
  16. Give an example of an exploit stemming from an improperly defined security requirement.
    A requirement that says “users must log in to access a page with links to their photos” says nothing about authenticating the actual service that fetches the photos, so an attacker might easily guess the URLs of anyone’s photos.
  17. What is the meaning of “defense in depth”?
    Having a series of defenses so that if an attack isn't caught by one, it will probably be caught by the next one on the chain, and so on.
  18. What some examples of layered protections that would appear in depth defense?
    Firewalls, anti-virus software, crypto, authentication mechanisms, authorization rules, signatures, correctness proofs.
  19. What is an example of the need to apply defenses broadly, as well as in depth?
    An available attack can exploit flaws stemming from, say, insufficient network bandwidth, filling up hard drives, excessive memory paging or cache invalidations, hash collisions, deadlocks livelocks, bad database queries that don’t use indexes, or slow algorithms.
  20. What are the fancy terms for (1) trusted code in your security zone whose input you can trust, and (2) code from untrusted zones?
    (1) Code-on-the-inside, (2) Code-on-the-edge.
  21. What is the concept of designing for least privilege?
    Having the default situation being that any user or process is able to do the minimum possible to carry out its task, and no more.
  22. What do we define to help maintain integrity?
    Preconditions, postconditions, and invariants.
  23. Why do we have to fail fast?
    An unhandled failure can propagate an inconsistency in state leading to horrifying situations down the line.
  24. Auditing is important for security, especially for forensics and intrusion detection, but we have to be careful when logging. What are the two main concerns?
    Never log secrets, and keep the logs themselves secure.
  25. Why should you not rely on secrets?
    They can be accidentally or maliciously leaked, or divulged by a person who is under threat.
  26. Why should code be kept simple?
    The more complex your code, the greater the attack surface, and the greater chance for the introduction of bugs and flaws.
  27. Why should you be somewhat coy when reporting errors to users?
    The user may be an attacker looking for opportunities so being too-specific about error messages (e.g., distinguishing not found and found-but-you-don’t-have-access, or distinguishing bad-password from unknown-username-OR-password) may leak useful information to an attacker.
  28. What is the difference between security principles and tactics?
    Principles are high level, like “defend in depth, ”fail fast,” “don’t rely on secrets”, and “prevent leaks”. Tactics are specific programming practices like “don’t double-free pointers” or “avoid global variables.”
  29. What are some organizations that publish guidelines and standards for secure software development?
    CERT, OWASP.
  30. What is Capture-The-Flag (CTF) in security?
    A exercise or game where you try to find and exploit vulnerabilities in a system.
  31. Why should you take part in CTF exercises or competitions?
    To learn by doing.

Summary

We’ve covered:

  • Why secure software matters
  • Building security in
  • Defining security requirements
  • Defending deeply and broadly
  • General principles
  • Specific tactics
  • Important guidelines and standards to know about
  • A few good resources