Much of cumulative application security knowledge and tools are aimed at detection, rather than prevention, of vulnerabilities. This is a natural consequence of the fact that the primary job of many information security analysts is to look for security vulnerabilities and provide high level remediation suggestions rather than be involved in detailed remediation efforts. Another reason is that most organizations want to get a grip on what security exposures they currently have before focusing their efforts on preventing future exposures.
The consequence for application owners is that many of the tools that we have at our disposal are focused on vulnerability detection:
- Static analysis tools
- Runtime vulnerability scanning tools
- Verification standards such as the ASVS
Luckily, application security experts have long argued the case for focusing on prevention rather than relying solely relying on detection of security vulnerabilities. Building-in security early in the SDLC is a matter of cost effectiveness. Efforts such as OWASP's Enterprise Security API deal with this issue head-on at the code level. At a higher level, some organizations have developed Secure Software Development Life Cycle models such as the Software Assurance Maturity Model, Building Security In Maturity Model, or Microsoft's SDL.
Most SDLC security initiatives treat security requirements engineering as a foundational activity. The challenge in an Agile/Scrum context is that requirements (i.e. product backlog) are constantly shifting. Iterations are short, intense, and there is little time to introduce new processes such as an architectural analysis, threat risk assessments, or week-long penetration testing.Moreover, if we start with a minimal functionality system as Agile methodologies suggest then we can rarely, in practice, introduce all security requirements at one time. As an agile product owner, you are confronted with mountains of secure SDLC best practices that work best when you have a complete set of requirements up front: the antithesis of agile processes.
The Security Burden
Suppose you're near the inception of a new product or major re-release and you have short iterations. Looking at your product backlog, you likely have several months of tickets/detects/stories that represent mostly functional requirements. Ideally you've carefully groomed the backlog and prioritized items according to their importance in building a minimally functional system and their perceived benefit to end users.
Now let's say you want to add security requirements. Based on personal experience consulting at Security Compass and researching for SD Elements, I'd estimate that most large-scale enterprise web applications will have security requirements with a cumulative total of several months of effort. Simply put, you'll be unable to fulfill all security requirements in one shot. In addition, excessive focus on a non-functional concern like security makes it challenging to show incremental value to stakeholders (unless your stakeholders care deeply about security). As a result, you'll be faced with a somewhat ugly reality of agile development on new projects: Given sufficient visibility into security requirements, an agile application will have known security gaps in its early iterations.
You could defy the odds by focusing on security and not releasing the product until all known security gaps have been addressed. The reality, particularly for anyone operating in a competitive environment where security is not one of the top organizational priorities, is that time-to-market pressures make this infeasible.
Like everything else in the product backlog you must prioritize security requirements. The Software Assurance Maturity Model spells this fact out explicitly:
"It is important to not attempt to bring in too many best-practice requirements into each development iteration since there is a time trade-off with design and implementation. The recommended approach is to slowly add best-practices over successive development cycles to bolster the software's overall assurance profile over time."
There are a couple of caveats you should keep in mind when prioritizing security requirements:
- Choose risk reduction over perceived customer utility: When developers demonstrate their increment of progress at the end of the iteration, the security requirements will generally be about as visible as refactoring class names unless you actually perform penetration testing. I say generally because there are some cases where security is visible. For example, you might be tempted to add OAuth support in the names of both security and usefulness for end users. The problem is that while OAuth might help improve your security posture, you may have a much more pressing security risk such as ensuring your confidential data is sent over SSL. If you've resolved to build security into your product, choose risk reduction over customer utility for security requirements.
- Differentiate between features: In the nomenclature of security defects, Dr. Gary McGraw provides a useful distinction between flaws and bugs: "Bug (implementation) A software security defect that can be detected locally through static analysis [code language="review"][/code]
[/code]. Flaw (design). A software security defect at the architecture or design level. Flaws may not be apparent given only source code of a software system."The way you treat the corresponding controls is important:
- a)Bug mitigations generally don't belong on your product backlog because they don't have one-time acceptance criteria; these mitigations have to be addressed in every iteration. You ought to be thinking of them at all times. These are issues like proper output escaping, safe library usage, variable binding in SQL statements, or making sure you don't log confidential data; they are cross-cutting concerns that amount to following coding conventions. Developer education and code review / static analysis are the best ways to eradicate bugs.
- b)Flaw mitigations do belong in a product backlog. They have acceptance criteria and they need to be prioritized amongst all other requirements. These include issues such as authentication, centralized authorization routines, and session management.Once you've figured out which requirements are flaw mitigations you can perform a second level of differentiation: which requirements prevent an exploitable vulnerability versus which requirements provide defense in depth. Block brute force attacks prevents an exploitable vulnerability. Hiding verbose error messages is a measure of defense in depth. You should set your sights on the first group as a priority. Strive for your application to not be vulnerable to any remotely exploitable vulnerabilities as soon as it stores, processes, or transmits production data. Depending on your risk profile, you may also need to consider locally exploitable vulnerabilities to the server and/or compliance-driven requirements that may not accurately reflect risk. If you're lucky enough to start with non-production data then you have the latitude to build these controls across several iterations. However, once your application has production data you are knowingly putting your organization and (if applicable) your clients data at risk if the application lacks known security controls. If you must accept that you'll have exploitable security vulnerabilities, always compare the levels of risk that each security control provides and prioritize for the most significant risk reduction.
As a product owner you have scores of tools and processes to help you find vulnerabilities after they've been coded. Adopting security throughout the SDLC is cost effective, but difficult in practice to implement for agile shops. Security requirements, in particular, are difficult to prioritize or scope in early iterations. You can make the task more manageable by prioritizing requirements that prevent exploitable flaws, sorted by risk.