The Art of Software Security Assessment: Identifying and Preventing Software Vulnerabilities
by Mark Dowd, John McDonald and Justin Schuh
Pearson Education 2007.
ISBN 0-321-44442-6. Amazon.com $54.99. Bookpool.com $43.50.
Reviewed by Richard Austin Mar. 11, 2007
One might think that after excellent books such as "Writing Secure Code" by Howard and LeBlanc (reviewed by Fred Cohen in Issue 55) and "19 Deadly Sins of Software Security" by Howard, LeBlanc and Viega, the waters of software security books were in danger of becoming over fished, but this book extends the conversation on software security by looking at how real software audits are conducted for identifying defects.
At over 1,100 pages this work offers broad coverage and opens in Part I with a comprehensive introduction to the review process itself. This introduction is welcome because too many of us when faced with the necessity of performing a software audit tend to jump directly into the technical process of reviewing the code without a clear plan of how we're going to conduct the assessment. Chapters that review design and operational aspects are followed by a presentation of the overall application review process to establish a firm foundation that helps to assure the ensuing examination will result in good coverage of both how the software is structured as well as how it is used in practice. This section concludes with a case study based on the popular SSH protocol that ties the preceding chapters together in the context of a real assessment.
Part II delves into the particular classes of vulnerabilities with examples drawn from real-world code (a noticeable benefit of the Open Source movement).
The chapter on memory corruption pays particular attention to buffer overflows and opens with a piece of sage advice that "all memory corruption vulnerabilities should be regarded as exploitable until proved otherwise" (p. 167) which is an excellent counter to the oft heard lament that developers would gladly fix the issue if the auditor will just provide them with an example of how it could be exploited. This is followed by a good introduction to stack layouts, procedure calling conventions and the actual process an attacker uses to exploit memory corruption vulnerabilities. Protective measures such as stack "cookies" (or "canaries") and DNX (Do Not Execute) are reviewed and their limitations assessed to point out that there is no such thing as a "silver bullet" for these types of problems.
The authors then delve into the details of some issues with C that have mystified your humble correspondent on more than one occasion despite 3 decades of software experience. Representation issues that can give rise to boundary value problems are followed by a clear explanation of the bewildering rules governing type conversions. Issues such as the myriad ways that pesky sign bits can cause trouble when converting between signed and unsigned types are clearly demonstrated.
Succeeding chapters cover how programs are assembled from building blocks and the ways assembly can go wrong including unexpected control flows and the perennial problem of side effects. The many potential issues with strings and metacharacters are covered in the contexts of format strings, shell metacharacters and SQL queries. The subtleties in attempting to filter or escape metacharacters are effectively demonstrated.
Succeeding chapters cover UNIX files and processes with clear description of the UNIX privilege model, file security and interprocess communication with clear demonstrations culled from actual vulnerabilities to illustrate what types of things the code auditor should be watching out for.
Windows is not neglected and the menagerie of Windows objects, permissions, security descriptors and interprocess communication are toured again with demonstrations and sage advice on auditing COM and DCOM interfaces.
Part II concludes with another personal favorite: synchronization and state. Race conditions and starvation are ably described and followed by a review of the common synchronization techniques from both UNIX and Windows.
Part III is entitled "Software Vulnerabilities In Practice" and surveys the landscape of technologies that make up the modern application infrastructure. Network protocols are briefly reviewed, followed by a good discussion of firewall technologies and how they can be bypassed or subverted. The main application protocols such as HTTP, ASN, and DNS are reviewed with attention paid to the ways an attacker can leverage the protocol to their advantage.
A chapter on web technologies gives a sound introduction to the way web applications work ranging from the simple static web content to the bewildering ways dynamic content is generated and presented. Vulnerability classes such as SQL injection, cross-site scripting, etc. are reviewed from the auditor's point of view with, again, good advice on what to watch for during testing and code review. The book concludes with a whirlwind tour of web technologies such as SOAP and AJAX, the venerable CGI interface, Perl, Java and ASP. Coverage is briefer here than in earlier chapters likely because of the complexity of the technologies (and the desire to keep the book under 5,000 pages).
Summarizing a book this large and with such a wide ranging subject is difficult but I think it makes a valuable contribution to the subject of software security by providing clear guidance and advice on the oft-neglected subject of how one conducts a software audit. With it, an auditor has some hope of getting both good coverage and meaningful recommendations that might improve the security of the software.
If auditing software for security vulnerabilities is of interest, either because you perform it or consume its results, this book is a valuable addition to your bookshelf. Developers might also find it of interest to better understand the viewpoint and processes of those "audit people" that descend on one's premises, usually in the late stages of the project and seemingly with the agenda of wreaking maximum havoc on the schedule and release train.
The technical details will mystify many managers that might attempt to read it. However, I think that time spend perusing Part I (Introduction to Software Security Assessment) will pay dividends in helping them to both understand the assessment process and better appreciate the motives and processes of the assessment team.
Richard Austin is a resident curmudgeon at a Fortune 100 company who continues to wage a battle with a tottering tower of new security tomes. Periodically he takes a break from the fray and shares his opinion of the latest book to migrate from the tower to the shelf. He can be reached at firstname.lastname@example.org