[Ed Felten says: Please welcome Gary McGraw as guest blogger for the next week. Gary is CTO at Cigital and co-author of two past books with me. He’s here to post excerpts from his new book, Software Security: Building Security In, which was released this week. The book offers practical advice about how to design and build secure software – a problem that is hugely important and often misunderstood. Now here’s Gary….]
The Trinity of Trouble: Why the Problem is Growing
Most modern computing systems are susceptible to software security problems, so why is software security a bigger problem now than in the past? Three trends—together making up the trinity of trouble—have a large influence on the growth and evolution of the problem.
Connectivity. The growing connectivity of computers through the Internet has increased both the number of attack vectors and the ease with which an attack can be made. This puts software at greater risk. More and more computers, ranging from home PCs to systems that control critical infrastructure, such as the supervisory control and data acquisition (SCADA) systems that run the power grid, are being connected to enterprise networks and to the Internet. Furthermore, people, businesses, and governments are increasingly dependent on network-enabled communication such as e-mail or Web pages provided by information systems. Things that used to happen offline now happen online. Unfortunately, as these systems are connected to the Internet, they become vulnerable to software-based attacks from distant sources. An attacker no longer needs physical access to a system to exploit vulnerable software; and today, software security problems can shut down banking services and airlines (as shown by the SQL Slammer worm of January 2003).
Because access through a network does not require human intervention, launching automated attacks is easy. The ubiquity of networking means that there are more software systems to attack, more attacks, and greater risks from poor software security practices than in the past. We’re really only now beginning to cope with the ten-year-old attack paradigm that results from poor coding and design. Ubiquitous networking and attacks directly related to distributed computation remain rare (though the network itself is the primary vector for getting to and exploiting poor coding and design problems). This will change for the worse over time. Because the Internet is everywhere, the attackers are now at your virtual doorstep.
To make matters worse, large enterprises have caught two bugs: Web Services and its closely aligned Service Oriented Architecture (SOA). Even though SOA is certainly a fad driven by clever marketing, it represents a succinct way to talk about what many security professionals have always known to be true: Legacy applications that were never intended to be internetworked are becoming inter-networked and published as services.
Common platforms being integrated into megasolutions include SAP, PeopleSoft, Oracle, Informatica, Maestro, and so on (not to mention more modern J2EE and NET apps), COBOL, and other ancient mainframe platforms. Many of these applications and legacy systems don’t support common toolkits like SSL, standard plug-ins for authentication/authorization in a connected situation, or even simple cipher use. They don’t have the builtin capability to hook into directory services, which most large shops use for authentication and authorization. Middleware vendors pledge they can completely carve out the complexity of integration and provide seamless connectivity, but even though they provide connectivity (through JCA, WBI, or whatever), the authentication and application-level protocols don’t align.
Thus, middleware integration in reality reduces to something ad hoc like cross-enterprise FTP between applications. What’s worse is that lines of business often fear tight integration with better tools (because they lack skills, project budget, or faith in their infrastructure team), so they end up using middleware to FTP and drop data globs that have to be mopped up and transmogrified into load files or other application input. Because of this issue, legacy product integrations often suffer from two huge security problems:
1. Exclusive reliance on host-to-host authentication with weak passwords
2. Looming data compliance implications having to do with user privacy (because unencrypted transport of data over middleware and the middleware’s implementation for failover and load balancing means that queue cache files get stashed all over the place in plain text)
Current trends in enterprise architecture make connectivity problems more problematic than ever before.
Extensibility. A second trend negatively affecting software security is the degree to which systems have become extensible. An extensible system accepts updates or extensions, sometimes referred to as mobile code so that the functionality of the system can be evolved in an incremental fashion. For example, the plug-in architecture of Web browsers makes it easy to install viewer extensions for new document types as needed. Today’s operating systems support extensibility through dynamically loadable device drivers and modules. Today’s applications, such as word processors, e-mail clients, spreadsheets, and Web browsers, support extensibility through scripting, controls, components, and applets. The advent of Web Services and SOA, which are built entirely from extensible systems such as J2EE and .NET, brings explicit extensibility to the forefront.
From an economic standpoint, extensible systems are attractive because they provide flexible interfaces that can be adapted through new components. In today’s marketplace, it is crucial that software be deployed as rapidly as possible in order to gain market share. Yet the marketplace also demands that applications provide new features with each release. An extensible architecture makes it easy to satisfy both demands by allowing the base application code to be shipped early, with later feature extensions shipped as needed.
Unfortunately, the very nature of extensible systems makes it hard to prevent software vulnerabilities from slipping in as unwanted extensions. Advanced languages and platforms including Sun Microsystems’ Java and Microsoft’s .NET Framework are making extensibility commonplace.
Complexity. A third trend impacting software security is the unbridled growth in the size and complexity of modern information systems, especially software systems. A desktop system running Windows XP and associated applications depends on the proper functioning of the kernel as well as the applications to ensure that vulnerabilities cannot compromise the system. However, Windows XP itself consists of at least forty million lines of code, and end-user applications are becoming equally, if not more, complex. When systems become this large, bugs cannot be avoided.
The figure above shows how the complexity of Windows (measured in lines of code) has grown over the years. The point of the graph is not to emphasize the numbers themselves, but rather the growth rate over time. In practice, the defect rate tends to go up as the square of code size. Other factors that significantly affect complexity include whether the code is tightly integrated, the overlay of patches and other post-deployment fixes, and critical architectural issues.
The complexity problem is exacerbated by the use of unsafe programming languages (e.g., C and C++) that do not protect against simple kinds of attacks, such as buffer overflows. In theory, we could analyze and prove that a small program was free of problems, but this task is impossible for even the simplest desktop systems today, much less the enterprise-wide systems used by businesses or governments.
Of course, Windows is not alone. Almost all code bases tend to grow over time. During the last three years, I have made an informal survey of thousands of developers. With few exceptions (on the order of 1% of sample size), developers overwhelmingly report that their groups intend to produce more code, not less, as time goes by. Ironically, these same developers also report that they intend to produce fewer bugs even as they produce more code. The unfortunate reality is that “more lines, more bugs†is the rule of thumb that tends to be borne out in practice (and in science, as the next section shows). Developers are an optimistic lot.
The propensity for software systems to grow very large quickly is just as apparent in open source systems as it is in Windows. The problem is, of course, that more code results in more defects and, in turn, more security risk.
Hi James,
Thanks for the kind words. This blogging thing is too relentless for me! I find I’m busy enough with the production of monthly columns for the soon-to-go-away IT Architect and the bi-monthly science articles for IEEE Security & Privacy magazine (not to mention book writing and my job at Cigital).
For some of my more recent writings (other than the book, which I encourage all of you to rush out and buy), see:
http://www.cigital.com/resources/gem/
gem
Why a guest blogger. Why not have your own blog that you blog on a regular basis?
I have to disagree that “SOA is certainly a fad”. I thought so, too, until this year when I did some quick transactional analysis –
http://www.realmeme.com/roller/page/realmeme?entry=soa_j2ee_revisited_in_more
I agree that SOA will be a security problem, but for the moment, the “Internet Market” doesn’t agree –
http://www.realmeme.com/roller/page/realmeme?entry=soa_security_meme
Ok, maybe SOA is not a fad. Probably the best thing about SOA is that during a “rearchitecting” exercise, you get a chance to design things to be secure. Should be an excellent opportunity to correct architectural flaws in software design.
For an article I wrote on SOA for IEEE Security & Provacy magazine, see http://www.cigital.com/papers/download/bsi12-soa.doc.pdf
Subscribe to IEEE Security & Privacy magazine (without becoming a member of the IEEE) at http://www.computer.org/security/bsisub.
Hi all,
With respect to the languages question, modern languages that use reference-based memory management and are type safe (like Java and C#) are far superior and “safer” than those that don’t like C and C++. Type safety is no guarantee of security, but it does help.
One of the biggest disappointments I have surrounding the Java Security work with Ed is that we did not do enough at the time to emphasize the GOOD THING that is type safety. Given a choice, choose a type safe language for your work.
With regard to the Prefix comment (hi david!), Microsoft’s use of Jon Pincus’ excellent toolset is a good thing too. There are a number of static analysis tools now available on the market. In fact, use of a tool to scan security source code for vulnerabilities is the subject of Chapter 5 (and is touchpoint number one). My favorite tool is the Fortify Source Code Analysis tool. A demo version of that tool comes with the book.
Incidentally, the Trinity of Trouble is also responsible for the rise in malicious code.
gem
In addition to the items listed above, the market has not yet demanded security. Although this is probably because the consumer market does not (and probably will not) understand security. In addition, when just about any software can hook operating system calls and install drivers, the efforts of the OS vendor to provide security can be quickly nullified.
Not only is there complexity, but there is insuffucient effort to control that complexity to limit its scope and arena.
I think that there are two further factors that are relevant.
1 For every gullible label looking for a miracle product that is unachievable, there is an unscrupulous salesman promising to sell it to him.
2 Not only do labels not learn from their own mistakes, they copy other people’s. Take a look at:
http://www.techworld.com/security/news/index.cfm?NewsID=5386
How many lines of code does DOS have?
>Are there any languages that do? Which ones?
More modern languages like C# and Java support type safety that largely eliminate many classes of common programming errors like buffer overflows.
Although it is true that C and C++ code is quite vulnerable to these classes of problems, the rise of static analysis tools like prefix has mitigated some of the potential problems that result from writing code in those languages. These static analysis tools are constantly improving, and while that surely do not mean that more code with less bugs will always happen, they do facilitate the creation of less buggy code.
>The complexity problem is exacerbated by the use of unsafe programming languages (e.g., C and C++) that do not protect against simple kinds of attacks, such as buffer overflows
Are there any languages that do? Which ones?
Thank you.
Wow. What an astounding change — ten years and ten times as many lines of code.
[Makes me wonder if I am insane to be a programmer.]
I’d love to see the figure the article mentions.