Programmers often like to talk about how a new tool or a new version of their favorite platform will make coding faster, easier, or more elegant. Although this may be true, it ignores just how difficult and painstaking the process of developing quality software actually is, no matter what tools are used.
Case in point: the CWE/SANS list of the top 25 most dangerous software errors. Each year, the list's editors draw upon the experience of leading software security experts to rank programming errors by frequency, severity, and the likelihood that they will lead to exploitable vulnerabilities. This year's list was published this week, and the bad news is how few surprises it contains.
Not only is this year's list predictable, it's redundant. Of the 25 errors cited, far too many can be chalked up to the same fundamental misdeeds -- mistakes that have been around almost since the dawn of programming itself. Will we never learn?
The same errors, over and over
Topping the list is "improper neutralization of special elements used in an SQL command," also known as the dreaded SQL injection vulnerability, the bane of Web applications everywhere. According to IBM's annual X-Force Trend and Risk Report, the frequency of SQL injection attacks increased 200 times between 2008 and 2009, and IBM's researchers have seen at least one "globally scaled" SQL injection attack each summer for the past three years.
SQL injection is usually the result of improperly validated user input, where the application parses form data into a SQL query without checking to see whether it contains potentially harmful SQL code. But SQL injection isn't the only way user input can go wrong. Of the top 25 errors list, roughly a quarter of them can be attributed to inadequate input validation, including OS command injection, buffer overruns, cross-site scripting, failure to validate directory paths, and uncontrolled output formatting strings.
Even more than input validation errors, this year's top 25 list is rife with application security blunders of all kinds. Some of them sound fairly esoteric, such as "inclusion of functionality from untrusted control sphere." But of all such errors, the highest-ranking one on the list is "missing authentication for critical function" -- in other words, the attacker was able to gain access because there was no lock on the door to begin with.
Developers make such errors for two main reasons. First, they may be operating under the mistaken assumption that a given function is too obscure to be vulnerable; they fail to grasp the extent to which attackers may be willing to analyze their application flows to find weaknesses. More often, however, they simply haven't considered how important a given function might be to the overall security of their application. As applications grow more complicated and their functions are distributed across multiple systems and resources, it's particularly easy to lose track of the big security picture.