Tuesday, December 30, 2014

Software Engineering Security Part 2: Secure Development

To build secure software, integrate secure development practices into your existing software development lifecycle.
This article covers four general lifecycle areas: design, construction, test and vulnerability response. Developing secure software is complicated, but when broken down phase by phase, actionable plans can be created.

Design
Studies show that the cost of bugs increases drastically as the bugs progress through the lifecycle. This is especially true of security issues, which can be extremely expensive. Design-time security reviews, including threat modeling, can be very effective. Start simple. Identify assets. Identify the threats against these assets, then find mitigations against the threats. For example, configuration data is an asset. Loss of confidentiality or integrity of that data is a threat. The threat can be mitigated by using TLS to protect the data. Engineers and QA engineers should be involved and security test cases should be written based on the threats identified.

Construction
The design may be airtight, but the implementation may be poor. Use appropriate and effective tools during construction; peer review, unit testing, static code analysis, binary analysis, and enabling security features of the operating system (ASLR, stack protection).

Test
Consider each of the mitigations from the design review and write test cases that ensure design principles are not violated. Run one or more fuzz testing tools. Run any available security test tools against the software. Nothing is more embarrassing than a customer scanning their shiny new software and finding glaring security holes. Finally, consider running external penetration tests. Be sure to feed any vulnerabilities back into the lifecycle.

Vulnerability Response
This final phase is very important and cannot be overlooked. See my earlier article on vulnerability tracking. Define severity and policy in advance. Internal communication and external communication about vulnerabilities must be timely and correct.

A lifecycle is part of every development shop. Integrating security into each phase of the lifecycle will create a secure development lifecycle and greatly improve the security of the software.

Links to other articles in this series:

Sunday, December 28, 2014

Software Engineering Security Part 1: Identify and Track Vulnerabilities in Software

This is the first in a series of articles about building a secure software engineering shop. These articles are applicable either to traditional dev shops creating software or to shops hosting software or services in the cloud.
Inevitably, there are vulnerabilities in code. To avoid confusion in the organization, vulnerabilities must be prioritized and worked just like any other issue.  This is the core to building secure software.

Step One: Gather data and assign severity
This is the most important step. There is always a cone of uncertainty around every vulnerability. The team should gather the evidence and determine severity.
Enhance the issue tracking system to track vulnerabilities as a special case of defect. Assign a severity to any vulnerability tracked. Keep it simple; five severities level are enough:
  • Critical - Any vulnerability that results in remote code execution or denial of service. Examples include ShellShock and Heartbleed.
  • Severe - Any vulnerability that results in remote code execution or denial service, but has mitigations. Examples include POODLE (disable SSLv3) and BEAST (disable CBC ciphers).
  • Important - Any vulnerability that allows an attacker to escalate his privileges. Examples include an XSS attack against management users, or an XSRF that allow a lower privileged user to escalate their privileges.
  • Minor - Similar to Important, but mitigations may be in place. This could also be an information leak or other relatively minor issue.
  • Not Vulnerable - This is self explanatory, but is a good way to track a vulnerability and the work that has been done to identify and research it.
Track all vulnerabilities by a unique number; CVE numbers work well. See a later article for information on fetching CVE identifiers and working with vulnerability databases.
Assign CVSS scores to all vulnerabilities. This can help clarify the response.


Step Two: Respond  based on severity
Once a vulnerability severity is assigned, actions should be clear based on policy. The policy needs to written and understood by the entire organization. For example, a critical vulnerability invokes an immediate change window. A severe vulnerability invokes a mitigation change request; possibly scheduled for the next change window. An important issue must be fixed within the next month. All vulnerabilities in a software distribution should be documented externally with mitigation information and recommendations for avoiding the issue.

Step Three: Enforce the policy
Build reports so that all engineers and managers will know the importance of an issue. Priority should be assigned based on the severity. That priority should be understood by all parties.

Step Four: Gather metrics
Gather data about which vulnerabilities are deferred or incomplete. Track where in the code vulnerabilities are found. Escape analysis or root cause analysis should be performed on all severe or higher vulnerabilities. This information should feed back into the dev and test cycle.

Using these principles should greatly reduce confusion, improve communication and increase productivity when vulnerabilities arise.