Hacking: Example of SQL Injection into a C++ Program

By Stephen R. Davis

Code injection occurs when the user entices your C++ program to execute some piece of user-created code. “What? My program would never do that!” you say. Consider the most common and, fortunately, easiest to understand variant of this little scam: SQL injection.

Here are a few facts about SQL:

  • SQL (often pronounced “sequel”) stands for Structured Query Language.

  • SQL is the most common language for accessing databases.

  • SQL is used almost universally in accessing relational databases.

If you don′t already know SQL, it′s sufficient to say that SQL is often interpreted at runtime. Very often, C++ statements will send an SQL query to a separate database server and then process and display whatever the server sends back. A typical SQL query within a C++ program might look like the following:

char* query = "SELECT * FROM transactions WHERE accountID=′123456789′;"
results = submit(query);

This code says, “SELECT all of the fields FROM the transactions table WHERE the accountID (presumably one of the fields in the transaction table) is equal to 123456789 (the user′s account id).” The submit() library function might send this query off to the database server.

The database server would respond with all of the data it has on every transaction that the user has ever made on this account, which would get stored into the collection results. The program would then iterate through results, probably displaying the transactions in a table with each transaction on a separate row.

The user probably doesn′t need that much data. Maybe just those transactions between startDate and endDate, two variables that the program reads from the user′s query page. This more selective C++ program might contain a statement like the following:

char* query = "SELECT * FROM transactions WHERE accountID=′123456789′"
        " AND date > ′" + startDate + "′ AND date < ′" + endDate + "′;";

If the user enters 2013/10/1 for a startDate and 2013/11/1 for endDate, then the resulting query that gets sent to the database is the following:

SELECT * FROM transactions WHERE accountID=′123456789′ AND
          date > ′2013/10/1′ AND date < ′2013/11/1′;

In other words, show all the transactions made in the month of October 2013. That makes sense. What′s the problem?

The problem arises if the program just accepts whatever the user enters as start and end dates and plugs them into the query. It doesn′t do any checking to make sure that the user is entering just a date and nothing but a date. This program is far too trusting.

What if a hacker were to enter 2013/10/1 for the startDate, but for the endDate he were to enter something like 2013/11/1 OR accountID=′234567890. (Notice the unbalanced single quotes.) Now the combined SQL query that gets sent to the database server would look like

SELECT * FROM transactions WHERE accountID=′123456789′ AND
          date > ′2013/10/1′ AND date < ′2013/11/1′ OR
          accountID=′234567890′;

This says, “Show me all the transactions for the account 123456789 for the month of October 2013, plus all the transactions for some other account 234567890 that I don′t own for any date.”

This little example may raise a few questions: “How did the hacker know that he could enter SQL statements in place of dates?” He doesn′t know — he just tries entering bogus SQL into every field that accepts character text and sees what happens. If the program complains, “That′s not a legal date,” then the hacker knows that the program checks to make sure that input dates are valid and SQL injection won′t work here.

If, on the other hand, the program displays an error message like Illegal SQL statement, then the hacker knows that the program accepted the bogus input and shipped it off to the database server which then kicked it back. Success! Now all he has to do is formulate the query just right.

So how did the hacker know that the account ID was called accountID? He didn′t know that either, but how long would it take to guess that one? Hackers are very persistent.

Finally, how did the hacker know that 234567890 was a valid account number? Again, he didn′t — but do you really think that the hacker′s going to stop there? Heck no. He′s going to try every combination of digits he can think of until he finds some really big accounts with really big balances that are worth stealing from.

Remember three things:

  • SQL injection was very common years ago.

  • It was just this simple.

  • With a better knowledge of SQL and some really tortured syntax, a good hacker can do almost anything he wants with an SQL injection like this.