Adobe, eBay, Microsoft UK, Racing Post, Sony PSN and TalkTalk … what have these companies got in common? Answer: each of them has, as a result of being hacked, suffered brand damage and loss of customer trust.
Big names, big costs
Some companies, such as TalkTalk, suffered a drop in share price as a result of hacking. In fact, hacking costs victim companies a great deal of money generally, and the threat is constant and real. Even Pirate Bay – a business considered by many to be associated with the underworld of the Internet – has suffered at the hands of hackers!
If these names aren’t big enough for you to worry about, in 2012, security company Imperva reported than on average a web-facing application received 4 attacks every month. In each case, the confirmed or suspected method was SQL Injection attacks.
An SQL Injection attack uses a very straightforward idea to abuse or gain access to a system. Typically, the system provides a web interface through which the user interacts with a database, for example, allowing them to log in to access restricted content, or perform lookups of some nature.
Generally, the data entered by the user on the web page, such as their username or password, is merged into an SQL query, sufficient to carry out the users request. This is then executed by the database, which returns a result that is then used to form some response back to the user.
However, a malicious user will abuse this by perhaps entering what amounts to additional SQL rather than the expected username. The exploitable weakness of some systems then comes into play in that the code processing the user’s data does little or no validation of the data. Instead, it assumes a valid username has been entered which is merged unchecked into the mentioned SQL statement.
With enough knowledge of SQL, patience, and a system that doesn’t flag up such attempts (why should it, if it already assumes all users are trustworthy?), sensitive information can easily be obtained.
So what does the typical code look like that harbours such a vulnerability? Here’s an example:
void lookup_by_email (SQLHSTMT hstmt)
printf("Enter your email address.");
if (!fgets(useremail, 64, stdin)) return;
querylen = sprintf(query,
"SELECT * FROM userinfo WHERE email = %s",
rc = SQLExecDirectA(hstmt, query, querylen);
/* ... remainder of function */
Here the program acquires input from the user via the gets() function – obviously, in the case of a web application, it will be a read() of some sort from a network connection. It merges that input into an SQL statement with sprintf(), and then calls a suitable API to execute that query on the database.
So, the key pre-emptive action that a company can take to avoid these problems is to write code without assumptions about the honesty of their users. In other words, companies need to insert code between the data acquisition and SQL statement execution to validate the data.
But even with this mindset in place, mistakes can occur, for the same reasons that programs contain well-known types of bugs such as memory leaks, buffer overruns and uninitialized variables – developers are only human.
In each of these cases (but focusing on SQL Injection), using static analysis tools such as Codesonar, SCL’s preferred static analysis tool for C & C++, can be very sensible, and save a lot of time and money.
In the above code snippet, Codesonar would have reported an SQL Injection type of error on the SQLExecDirectA() call. All that’s required to discover this problem is to allow Codesonar to monitor a typical build of your codebase with your compiler. It requires no changes to your code or how you build your code. Doing this means Codesonar automatically and transparently builds your code (to accurately understand your code).
It then analyses that output for a multitude of problems, SQL Injection issues included. The ensuing warning report would have contained a clearly marked path of execution through your code, and a plain English annotation on the SQLExecDirectA () call, stating that following the highlighted path reveals an SQL Injection exploit.
Using Codesonar to detect vulnerabilities
Codesonar is sensitive to a variety of programmatic methods of acquiring data from the outside world, known as taint sources, out of the box. They include reads of files and sockets, environment, command line, registry and others. Codesonar is also able to identify a number of APIs associated with executing SQL statements, known as taint sinks.
Codesonar’s analysis is powerful enough to track the acquired data from the source, potentially through multiple API call stacks and variable reassignment, right through to the point of use in the sink – all elements would be highlighted and annotated. In addition, you’re able to easily extend the set of sources and sinks for custom, unrecognised APIs.
Rather usefully, you can also define a set of taint validation functions that need to be called on your program’s execution path between the tainted source and taint sink to vet the data. This means Codesonar will only report the execution paths between the source and sink where you forget to validate the data.
Cost effective automated analysis
In summary, SQL Injections can be statically detected with relative ease. The code structure necessary for such faults to exist is typically straightforward in its implementation, though often hard for a code reviewer to identify if the key steps (external data acquisition and SQL execution) are separated by many lines of code or function calls. Reliance on automated analysis tools can quickly prove very cost effective.