Half of all software security defects are design flaws, not bugs. Here are 10 do’s and don’ts to help you avoid the most common software security flaws.
Half of the software-related security defects that provide entry to threat agents aren’t bugs found in code; rather, they’re flaws embedded in software design. The IEEE Center for Secure Design brought together some of the foremost experts in software security in a working group to tackle the issue of secure software design.
Based on their findings, here are 10 powerful do’s and don’ts examining the most common software security flaws.
1. Earn or give trust, but never assume it.
- Do make sure all data from an untrusted client are validated.
- Do assume data are compromised.
- Don’t use authorization, access control, policy enforcement, and use of sensitive data in client code.
2. Use an authentication mechanism that can’t be bypassed.
- Do prevent users from changing identity without re-authentication after they’re authenticated.
- Do consider the strengths of the user’s provided authentication before taking action.
- Do make use of timeouts.
- Don’t stray past the big three: something you know, something you have, and something you are
- Don’t share resources like IP numbers and MAC addresses.
- Don’t use predictable tokens.
3. Authorize after you authenticate.
- Do perform authorization as an explicit check.
- Do reuse common infrastructure for conducting authorization checks.
- Don’t forget that authorization depends on the context of the request, not just a given set of privileges.
4. Strictly separate data and control instructions, and never process control instructions received from untrusted sources.
- Do utilize hardware capabilities to enforce separation of code and data.
- Do know and use appropriate compiler/linker security flags.
- Do expose methods or endpoints that consume structured types.
- Don’t co-mingle data and control instructions in a single entity.
- Don’t use APIs prone to injection such as XSS, SQL injection, and shell injection.
- Don’t use (eval).
5. Define an approach that ensures all data are explicitly validated.
- Do ensure that comprehensive data validation actually takes place.
- Do use whitelisting.
- Do use a centralized validation mechanism and canonical data forms.
- Do make security review of the validation scheme possible.
- Don’t make assumptions about data.
- Don’t use blacklisting.
- Don’t use strings.
6. Use cryptography correctly.
- Do use standard algorithms and libraries.
- Do centralize and reuse.
- Do design for crypto agility.
- Do get help from real experts.
- Don’t roll your own crypto. It’s too hard to get it right.
- Don’t ignore key management issues.
- Don’t implement nonrandom “randomness.”
7. Identify sensitive data and how they should be handled.
- Do know where your sensitive data are.
- Do classify your data into categories.
- Do consider data controls such as file, memory, and database protection.
- Do plan for change over time.
- Don’t forget that data sensitivity is often context-sensitive.
- Don’t mistake confidentiality for data protection.
- Don’t ignore trust boundaries.
8. Always consider the users.
- Do think about deployment, configuration, use, and updates.
- Do know that security is an emergent property of the system.
- Do consider user culture, experience, biases, etc.
- Do make things secure by default.
- Don’t treat security as a feature.
- Don’t impose too much security.
- Don’t assume users care about security.
- Don’t let users make security decisions.
9. Understand how integrating external components changes your attack surface.
- Do test your components for security.
- Do include external components and dependencies in review.
- Do isolate components.
- Do keep an eye out for public security information about components.
- Don’t forget that composition is dangerous.
- Don’t underestimate the amount of security risk that can be inherited.
- Don’t assume open source is secure.
- Don’t trust until you have applied and reviewed controls.
10. Be flexible when considering future changes to objects and actors.
- Do design for change.
- Do consider security updates.
- Do make use of code signing and code protection.
- Do allow isolation and toggling.
- Do have a plan for “secret compromise” recovery.
- Don’t ignore fragile and/or brittle security.
- Don’t underestimate code signing and system administration/operation.
- Don’t forget that keeping secrets is hard.
- Don’t forget that crypto breaks.