Software Security: Building Security In

In 2004 and 2005, a number of startups formed to address the software security space. Many of these vendors have built and are selling basic source code analysis tools. Major vendors in the space include the following:

  • Coverity <http://www.coverity.com>

  • Fortify <http://www.fortifysoftware.com>

  • Ounce Labs <http://www.ouncelabs.com>

  • Secure Software <http://www.securesoftware.com>

The technological approach taken by many of these vendors is very similar, although some are more academically inclined than others. By basing their tools on compiler technology, these vendors have upped the level of sophistication far beyond the early, almost unusable tools like ITS4.[8]

[8] Beware of security consultants armed with ITS4 who aren't software people. Consultants with code review tools are rapidly becoming to the software security world what consultants with penetration testing tools are to the network security world. Make sure you carefully vet your vendors.

A critical feature that currently serves as an important differentiator in the static analysis tools market is the kind of knowledge (the ruleset) that a tool enforces. The importance of a good ruleset can't be overestimated.

Commercial Source Code Analyzers

One of the main reasons to use a source code analysis tool is that manual review is costly and time consuming. Manual review is such a pain that reviewers regularly suffer from the "get done, go home" phenomenonstarting strong and ending with a sputter. An automated tool can begin to check every line of code whenever a build is complete, allowing development shops to get on with the business of building software.

Integrating a source code analyzer into your development lifecycle can be painless and easy. As long as your code builds, you should be able to run a modern analysis. Working through the results remains a challenge but is nowhere near as much trouble as painstakingly checking every line of code by hand.

Modern approaches to static analysis can now process on the order of millions of lines of code quickly and efficiently. Though a complete review certainly requires an analyst with a clue, the process of looking through the results of a tool and thinking through potential vulnerabilities beats looking through everything. A time savings of several hundred percent is not out of the question.

Several timesaving mechanisms are built into modern tools. The first is the knowledge encapsulated in a tool. Keeping a burgeoning list of all known security problems found in a language like C (several hundred) in your head while attempting to trace control flow, data flow, and an explosion of states by hand is extremely difficult. Having a tool that remembers security problems (and can easily be expanded to cover new problems) is a huge help. The second timesaving mechanism involves automatically tracking control flow, call chains, and data flow. Though commercial tools make tradeoffs when it comes to soundness (as discussed earlier), they certainly make the laborious process of control and data flow analysis much easier. For example, a decent tool can locate a potential strcpy() vulnerability on a given line, present the result in a results browser, and arm the user with an easy and automated way to determine (through control flow, call chains, and data flow structures) whether the possible vulnerability is real. Though tools are getting better at figuring out this kind of thing for themselves, they are not perfect.

The root cause of most security problems can be found in the source code and configuration files of common software applicationsespecially custom apps that you write yourself. Problems are seeded when vulnerable code is written right into the system, which is undeniably the most efficient and effective time to remove them. The way forward is to use automated tools and processes that systematically and comprehensively target the root cause of security issues in source code. Instead of sorting through millions of lines of code looking for vulnerabilities, a developer using an advanced software security tool that returns a small set of potential vulnerabilities can pinpoint actual vulnerabilities in a matter of secondsprecisely the same vulnerabilities that would take a malicious hacker or manual code reviewer weeks or even months to find. Of course, most bad guys know this and will use these kinds of tools themselves [Hoglund and McGraw 2004].

Key Characteristics of a Tool

To be useful and cost effective, a source code analysis tool must have six key characteristics.

  1. Be designed for security. Software security may well be a subset of software quality, but software security requires the ability to think like a bad guy. Exploiting software is not an exercise in standard-issue QA. A software defect uncovered during functionality testing might be addressed in such a way that the functional issue is resolved, but security defects may still remain and be reachable via surprising execution paths that are not even considered during functionality testing. It almost goes without saying that software security risks tend to have much more costly business impacts than do standard-issue software risks. Security impact is payable in terms of loss of business data, loss of customer trust and brand loyalty, cost of downtime and inability to perform business transactions, and other intangible costs. Simply put, software quality tools may be of some use when it comes to robustness, but software security tools have more critical security knowledge built into them. The knowledge base built into a tool is an essential deciding factor.[9]

    [9] While more general quality tools will not pinpoint security issues, they can be used by a seasoned reviewer to identify "smells" in the complexity, cohesion, coupling, and effort/volume relationship of code modulesall good starting points for identifying possible security weak spots. In many cases, security errors arising from sloppy coding don't appear as rare blips among otherwise pristine code. They are usually the consequence of a larger, more pervasive carelessness that can sometimes be seen from high up in terms of quality errors. Don't rely on quality metrics to identify security issues, but keep an eye out for quality weak modules. Vices tend to roll together

  2. Support multiple tiers. Modern software applications are rarely written in a single programming language or targeted to a single platform. Most business-critical applications are highly distributed, with multiple tiers each written in a different programming language and executed on a different platform. Automated security analysis software must support each of these languages and platforms, as well as properly negotiate between and among tiers. A tool that can analyze only one or two languages can't meet the needs of modern software.

  3. Be extensible. Security problems evolve, grow, and mutate, just like species on a continent. No one technique or set of rules will ever perfectly detect all security vulnerabilities. Good tools need a modular architecture that supports multiple kinds of analysis techniques. That way, as new attack and defense techniques are developed, the tool can be expanded to encompass them. Likewise, users must be able to add their own security rules. Every organization has its own set of corporate security policies, meaning that a fixed "one-size-fits-all" approach to security is doomed to fail.

  4. Be useful for security analysts and developers alike. Security analysis is complicated and hard. Even the best analysis tools cannot automatically fix security problems, just as debuggers can't magically debug your code. The best automated tools make it possible for analysts to focus their attention directly on the most important issues. Good tools support not only analysts but also the poor developers who need to fix the problems uncovered by a tool. Good tools allow users to find and fix security problems as efficiently as possible. Used properly, source code analysis tools are excellent teaching tools. Simply by using them, developers can learn about software security (almost by osmosis).

  5. Support existing development processes. Seamless integration with build processes and IDEs is an essential characteristic of any software tool. For a source code analysis tool to become accepted as part of an application development team's toolset, the tool must properly interoperate with existing compilers used on the various platforms and support popular build tools like make and ant. Good tools both integrate into existing build processes and also coexist with and support analysis in familiar development tools.

  6. Make sense to multiple stakeholders. Software is built for a reasonusually a business reason. Security tools need to support the business. A security-oriented development focus is new to a vast majority of organizations. Of course, software security is not a product; rather, it is an ongoing process that necessarily involves the contributions of many people across an organization. But good automated tools can help to scale a software security initiative beyond a select few to an entire development shop. Views for release managers, development managers, and even executives allow comparison using relative metrics and can support release decisions, help control rework costs, and provide much-needed data for software governance.

Three Characteristics to Avoid

Source code analysis is not easy, and early approaches (including ITS4) suffered from a number of unfortunate problems. Some of these problems persist in source code analysis tools today. Watch out for these characteristics.

  1. Too many false positives. One common problem with early approaches to static analysis was their excessive false positive rates. Practitioners seem to feel that tools that provide a false positive rate under 40% are okay. ITS4 would sometimes produce rates in the range of 90% and higher, making it a real pain to use. Glorified grep machines have an extremely low signal-to-noise ratio. Modern approaches that include data flow analysis capability dramatically reduce false positives, making source code analysis much more effective.

  2. Spotty integration with IDEs. Emacs may be great, but it is not for everyone. Developers already have an IDE they like, and they shouldn't have to switch to do a security analysis. Enough said.

  3. Single-minded support for C. Canonical security bugs are pervasive in C. However, modern software is built with multiple languages and supports multiple platforms. If your system is built of more than C, make sure you don't skip the "non-C" parts when you review code.

The Fortify Source Code Analysis Suite[10]

[10] Full disclosure: I am the chairman of Fortify Software's Technical Advisory Board. Part of Fortify's code analysis technology (in the form of SourceScope) was invented and developed by Cigital.

I think it is important to give you a feel for what a real commercial tool looks like (especially if you read about the use of RATS in Building Secure Software [Viega and McGraw 2001]). This section is about one of the leading software security tools. Others exist. Make sure that you pick the tool that is right for you.

That said, Fortify Software produces a very successful source code analysis suite that many organizations will find useful. It includes the five components outlined in Table 4-1.

Table 4-1. The Five Components of the Fortify Source Code Analysis Suite

Component

Description

Source Code Analysis Engine

The Fortify code analysis and vulnerability detection engine performs basic semantic, data flow, control flow, and configuration analysis.

Secure Coding Rulepacks and Rules Builder

Secure Coding Rulepacks provide coverage of 2,000+ base language and third-party functions and over 50,000 vulnerability paths. Rules Builder allows creation of custom rules.

Audit Workbench

Fortify's visual interface enables rapid analysis of software vulnerabilities in order to prioritize the remediation of defects.

Developer Desktop

Fortify integrates critical vulnerability detection directly into popular IDEs (including JBuilder, Visual Studio .NET, Rational Application Developer for WebSphere Software, and Eclipse).

Software Security Manager

Fortify centralizes analysis and reporting of vulnerability trend data across people and projects.

The Source Code Analysis (SCA) Engine searches for violations of security-specific coding rules in source code. An intermediate representation in the form of an AST built using advanced parser technology enables a set of analyzers in the SCA Engine to pinpoint and prioritize violations. This helps to make security code reviews more efficient, consistent, and complete, especially where large code bases are involved.

The SCA Engine determines the location of security vulnerabilities in source code and computes vulnerability relevance based on the relationship of the vulnerability to the surrounding code. The analyzers built into the tool provide multilanguage analysis across multiple tiers, allowing developers to determine which path or paths through a piece of code are actually vulnerable.

The SCA Engine includes four analyzers: semantic, data flow, control flow, and configuration. These analyzers locate security defects across the entire code base, including problems that span multiple tiers. The tool, which supports Java, C, C++, C#, JSP, XML, and PL/SQL, produces an XML results file that is consumed by the results browser. Figure 4-2 shows a basic architecture.

Figure 4-2. Components making up the Fortify Source Code Analysis Suite.

The SCA Engine uses the Secure Coding Rulepacks as the expandable knowledge base for analysis. The prepackaged Secure Coding Rulepacks that come with the tool encapsulate years of security knowledge about anomalous constructs and vulnerable functions in software. The rules can identify dozens of vulnerability categories, including buffer overflows, log forging, cross-site scripting, memory leaks, and SQL injection. The Fortify toolset is extensible and allows automated creation of new application-specific, third-party library, and corporate-standardsbased custom rules using the Rules Builder (Figure 4-3).

Figure 4-3. The Fortify Rule Details Editor in the Rules Builder allows creation of custom rules.

The Audit Workbench (Figure 4-4) is a visual interface allowing detailed and efficient analysis of potential software vulnerabilities in order to prioritize and fix problems. Human interface concerns are critical in these kinds of tools because the human analyst plays a central role in the process of automated code review. Without a smart human in the loop, the tool is not very useful. The Audit Workbench provides a summary view of security problems with detail related to the defect in focus. The data displayed include information about particular vulnerabilities, the rules that uncovered them, and what to do about them. (This kind of information is extremely useful in context and is available to interested readers at <http://vulncat.fortifysoftware.com>. See Chapter 12 for a taxonomy of vulnerability information.) Potential problems are displayed with surrounding source code and a call tree. Results are categorized into customizable buckets of defects and can be annotated with resolution severity, priority, and status.

Figure 4-4. The Fortify Audit Workbench window supports in-depth analysis.

The Developer Desktop (Figure 4-5) is a collection of software components for a developer's desktop. It includes the SCA Engine, Secure Coding Rulepacks, and plug-ins for common IDEs. Because it is integrated into standard development tools, adoption is fairly painless. Integration of the toolset enhances a standard IDE with detailed and accurate security vulnerability knowledge. This is an effective way to train developers about secure coding practices as they do their normal thing. Fortify supports Eclipse, Rational Application Developer for WebSphere Software, and Microsoft Visual Studio .NET Add-in.

Figure 4-5. Developer Desktop components have a familiar look and feel.

The Software Security Manager is a Web-based security policy and reporting interface that enables development teams to manage and control risk across multiple projects and releases. The Software Security Manager helps to centralize reporting, enable trend analysis, and produce software security reports for management. The Software Security Manager includes a number of predefined metrics that cover the number and type of vulnerabilities, policy violations, and severity. Figure 4-6 shows the Software Security Manager Dashboard.

Figure 4-6. The Software Security Manager Dashboard helps bring source code analysis up out of the weeds.

The Fortify Knowledge Base

The most critical feature of any static analysis tool involves the knowledge built into it. We've come a long way since the early days of RATS and ITS4 when a simple grep for a possibly dangerous API might suffice. Today, the software security knowledge expected to drive static analysis tools is much more sophisticated.

A complete taxonomy of software security vulnerabilities that can be uncovered using automated tools is discussed in Chapter 12. Software security rules knowledge has progressed much further than other more subtle knowledge categories such as secure coding patterns and technology-specific guidelines.

The vulnerability descriptions powering the Fortify SCA Engine are far more sophisticated than the early ITS4 database mentioned earlier in this chapter. For the complete taxonomy, see the Fortify Web site at <http://vulncat.fortifysoftware.com>.

Coder's Corner

What follows is an example of one of 78 basic vulnerability descriptions identified and described by Brian Chess and Jacob West. This description shows the kind of knowledge available to developers when they use a sophisticated static analysis tool. Note the similarity between the vulnerability description here and the complete rule shown earlier in the chapter.

Security Functionality: Authentication

(getlogin)

Abstract

The getlogin() function is easy to spoof. Do not rely on the name it returns.

Explanation

The getlogin() function is supposed to return a string containing the name of the user currently logged in at the terminal, but an attacker can cause getlogin() to return the name of any user logged in to the machine. Do not rely on the name returned by getlogin() when making security decisions.

Example 1: The following code relies on getlogin() to determine whether or not a user is trusted. It is easily subverted.

pwd = getpwnam(getlogin()); if (isTrustedGroup(pwd->pw_gid)) { allow(); } else { deny(); }

Recommendations

You should rely on a user's ID, not the username, for identification. The previous example can be rewritten as follows:

pwd = getpwuid(getuid()); if (isTrustedGroup(pwd->pw_gid)) { allow(); } else { deny(); }

If multiple users are allowed to share the same user ID (a dubious proposition from a security standpoint), a bit more care is required. The following example checks to see whether the username returned by getlogin() matches the username associated with the user ID; the check ensures that if two users share the same ID, one user cannot act on behalf of the other.

pwd = getpwuid(getuid()); pwdName = pwd->pw_name; /* Bail out if the name associated with the uid does not match the name associated with the terminal. */ if (strncmp(pwdName, getlogin(), MAX_NAM_LEN)) { printf("shared uid not supported\n"); deny(); return; } if (isTrustedGroup(pwd->pw_gid)) { allow(); } else { deny(); }

Note: If the process is not being run from a terminal, getlogin() returns NULL.

Using Fortify

A special demonstration version of the Fortify Source Code Analysis product is included with this book. Please note that the demonstration software includes only a subset of the functionality offered by the Source Code Analysis Suite. For example, this demonstration version scans for buffer overflow and SQL injection vulnerabilities but does not scan for cross-site scripting or access control vulnerabilities.

Appendix A is a tutorial guide reprinted with permission from Fortify Software. If you would like to learn more about how the Fortify Source Code Analysis Suite works in a hands-on way, check out the appendix. The key you will need to unlock the demo on the CD is FSDMOBEBESHIPFSDMO. To prevent any confusion, this key is composed of letters exclusively. There are no numbers.

Категории