SQL as a language is vulnerable to injection attacks because it allows mixing of instructions and data, which attackers can conveniently exploit to achieve their nefarious objectives.
The root cause behind successful SQL injection attacks is the execution of user-supplied data as SQL instructions. This classic cartoon illustrates the perils oftrusting user inputs, and how they can lead to a successful SQLi attack:
From the webcomic xkcd :
Contents
In this blog post, I describe some different types of SQLi attacks and their effects, and I show some ways to protect against them and to prepare your systems to minimizedamage in casethey do occur.
The Rise in SQLi Attacks Defenses Against SQLi Mitigation of SQLi Impact The Rise in SQLi AttacksSQLi attacks are on the rise. According to Akamai’s most recent State of the Internet Security Report , there was an 87% increase in SQLi attacks in this year’s first quarter compared with 2015’s fourth quarter.
According to the latest IBM X-Force data report, 170 SQLi attacks have been reported since 2011 through mid-2016. In thelast 18 months over 20 million records have been leaked by exploiting SQLi attacks.
SQLi attacks can have severe consequences. For example, an attacker can gain control over your organization’s entire database server.
There have been several high profile SQLi attacks recently:
Just this week, Epic Games warned users of a breach attributed to a SQLi attack that impacts 800,000 user accounts. In April a SQLi flaw present in a CMS used by the law firm Mossack Fonseca most likely allowed hackers to steal 11.5 million confidential documents. Many of the documents contained information about dubious offshore tax affairs of current and former world leaders, an embarrassing scandal that became known as The Panama Papers. A few months ago, SoftPedia found a SQLi vulnerability in the Cardio Server ECG Management System, a data management system used by many hospitals and clinics. Late last year, hackers exploited a SQLi vulnerability to steal the login credentials of officials attending a climate summit in Paris. About SQL InjectionSQLi is a form of command injection vulnerability exploited with the aid of malicious input. For example, the following SQL query echoes the transaction history of a logged-in user for a given month:
SQL query = "SELECT date, branch_code, vendor, dr_cr, amount, balance FROM transactions WHERE user_id = " + session.getCurrentUserId() + " AND transaction_month = " + request.getParameter("month");In a valid case, the user would enter a month and the SQL query would look like this:
SELECT date, branch_code, vendor, dr_cr, amount, balance FROM transactions WHERE user_id = bob AND transaction_month = 12;A malicious user might enter 0 OR 1 = 1 , resulting in this query:
SELECT date, branch_code, vendor, dr_cr, amount, balance FROM transactions WHERE user_id = bob AND transaction_month = 0 OR 1 = 1;In the above query, the “where” condition will always evaluate to true, giving an attacker unauthorized access to other users’ transaction history.
A More Serious AttackLet’s consider a UNION-based attack, which is more serious because it allows the attacker to extract information from any field in any table in the database, not just from the fields specified in the query.
In this attack, the malicious user enters transaction_month as 0 AND 1 = 0 UNION SELECT 1, expiration_month, 1, 1, expiration_year, card_number FROM credit_cards .
Then, the malicious query will look like the following:
SELECT date, branch_code, vendor, dr_cr, amount, balance FROM transactions WHERE user_id = bob AND transaction_month = 0 AND 1 = 0 UNION SELECT 1, expiration_month, 1, 1, expiration_year, card_number FROM credit_cards;In the above query AND 1 = 0 will result in false, and the attacker will proceed to extract data from another table and to combine the resultset of the primary query with the union injected query.
In order to successfully combine the resultset, the number of fields and associated data types of the union injected query must be identical to the base query. That’s because the SQL union operator can only be used if both queries have the exact same structure.
A Destructive AttackAn attacker could set transaction_month equal to 0 ; DROP Table credit_cards; to make the SQLi more destructive.
This is how the SQLi query would look:
SELECT date, branch_code, vendor, dr_cr, amount, balance FROM transactions WHERE user_id = bob AND transaction_month = 0 ; DROP TABLE credit_cards;As a result of the above query, the credit_cards table is removed from the database.
Blind SQLiBlind SQLi is a technique to extract information from the database schema via a series of binary (yes/no) questions. Blind SQLi relies on the database returning different responses depending on the result of the SQL fragment injected into the query being used by the web app. Then the query result can tell you if your guess is correct (the injected fragment returns true) or if it’s incorrect (fragment returns false). By iterating through a series of such guesses, an attacker can perform a binary search on some part of the database.
For example, blind SQLi can be used to determine the structure of the database by repeatedly querying the data dictionary. The attacker can inject SQL that tests if the first letter of a tablename entry in the data dictionary starts in the first half of the alphabet; if true, then test if the first letter is in the first quarter of the alphabet, and so on until the attacker has guessed the first letter of the table name; and then do the same for the second letter and so on, until the attacker has guessed the table name. Some loop statements (binary search techniques) and an automated script make this simple. Once the attacker understands the database schema, it becomes possible to create follow-on attacks to extract specific data from the database.
Blind SQLi attacks can also be useful for guessing password hashes for specific user accounts.
A typical blind SQLi attack iterates over a query that looks like this:
SELECT date, branch_code, vendor, dr_cr, amount, balance FROM transactions WHERE user_id = bob AND transaction_month = 12 AND [true/false test g