Discovering SQL Injection Vulnerabilities
Within a couple of hours, an experienced Internet attack specialist can bring your server infrastructure to its knees. In many cases, the barn door through which the attackers gain entry is a classic bug in a web application: an SQL injection vulnerability. SQL injection, which has been known for around 12 years, is still one of the hacker’s most popular tools.
This article presents real-life examples of SQL injection attack vectors, explains how carelessness can cause them, and shows how far-reaching the impact can be. I will start by demonstrating these SQL attack techniques manually, then I'll show how to use the SQLmap tool to look for vulnerable code.
Typical Attack Vectors
One feature that nearly all web applications have in common is the connection to one or multiple databases. Whether it is used for retrieving email, shopping on the web, or reading news, there will always be at least one database back end. And, no matter which programming language the web application was written in, communication with the database always follows the same principle. The script stored on the server passes in the SQL queries to the database, evaluates the return values, and serves them up to the user.
Security holes in web applications can result from a lack of security awareness on the part of the developers. The larger issues mainly arise from a lack of input validation. The following PHP script, which is part of a popular login screen, demonstrates a typical programming error.
$query = "SELECT * FROM users WHERE user='" . $_POST['username'] . " ' AND password=' " . $_POST['password'] . " ' "; $response = mysql_query($query) ;
The expected values are the username and password. The script checks whether the input data matches the credentials stored in the database. If the user is found in the database, and the password matches, the user is legitimate. The SQL statement that handles this is passed in as follows:
SELECT * FROM users WHERE user='...' AND password='...'
In other words, the two variables, user and password , are added to the database query. This approach works in theory, but imagine an attacker changing the query like this:
Password = ' OR 'a' = 'a'
The query to the database is now:
SELECT * FROM users WHERE user = 'Patrik' AND password = ' ' OR 'a' = 'a'
This SQL query first checks the OR condition and then the AND condition. The OR condition checks whether at least one of the two arguments is true – the logical question is whether 'a' = 'a' , will always be true. The AND condition checks whether the username Patrik exists in the database: If this is the case, a value of true is returned. Because both arguments turn out to be true, the attacker is authenticated on the system without needing a password. Instead of simple strings, the attacker has injected SQL commands into the original query, which explains the term SQL injection.
You can prevent an attack of this kind by making sure that web applications validate all input and by using prepared statements instead of simple string concatenation. The scripting language then ensures that only desired data types, such as strings, are passed into the query.
To demonstrate attack methods for SQL, the remainder of this article uses a potentially vulnerable lab environment comprising an XAMPP web server with a deliberately buggy application by the name of DVWA (Damn Vulnerable Web Application). This web application is built with PHP and MySQL and specially designed for security specialists to gives users the option of testing various attacks on web applications in a legitimate way.
After installing Microsoft Windows Server 2003 and setting up the DVWA web application, the user first needs to log into the system via the login field with a username of Admin and a password of Password . DVWA offers three different difficulty levels that simulate different server security setting scenarios. To demonstrate SQL injection, you need to choose the Low setting in DVWA Security to make sure that all the security mechanisms that could prevent an SQL injection are disabled.
You can now choose the vulnerable module on the left in the tab. In this article, I will be using the SQL Injection module (Figure 1).
To check for a potential SQL injection vulnerability, you then enter a quote in the field. SQL injection is only possible if an application passes in user input to the server as part of a SQL query without checking the user input for metacharacters (backslash, apostrophe, quote, semicolon). In this case, the database returns the following error message:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''''' at line 1
This is the first hint of a potential SQL injection vulnerability.
The aim of many a SQL injection attack is to extract sensitive information from a database, but attacking a database can have far more wide-reaching consequences. SQLmap is an open source program that provides the perfect basis for comprehensive attacks on database systems. It is written in Python and is thus system-independent, and it is extensible through the addition of modules. SQLmap needs Python version 2.6 or newer.
The Takeover function also requires the Metasploit framework. SQLmap supports any popular database system, such as MySQL, PostgreSQL, Oracle, or Microsoft SQL Server. Additionally, it supports five different SQL injection methods: Boolean-based blind, time-based blind, error-based, UNION query, stacked queries, and out-of-band. The python sqlmap.py command launches the tool.
The URL to be checked follows the -u parameter in quotes. Safe in the knowledge that the SQL injection vulnerability is hiding behind the ID input field, you can add the --forms parameter to the command line. This tells SQLmap to test all input fields for SQL injection vulnerabilities. The user already has a session cookie from a previous login attempt. You need to tell SQLmap about this cookie for the attack to succeed, and you can discover this, for example, using the Firefox “Tamper Data” plugin. The complete line now looks like this:
sqlmap.py -u "http://127.0.0.1/dvwa/ vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie="PHPSESSID=ce0aa7922720f3190bf9bbff7f24c434;security=low" --forms
After a short while, SQLmap finds the matching ID field and asks whether you want to check it. After you confirm the prompt, SQLmap will begin the analysis.
GET http://127.0.0.1:80/dvwa/vulnerabilities/sqli/?id=&Submit=Submit Cookie: PHPSESSID=ce0aa7922720f3190bf9bbff7f24c434;security=low do you want to test this form? [Y/n/q]
After a successful scan, SQLmap presents the potential attack vectors in the form of prebuilt SQL statements. At that point, the user can decide whether to continue the attack manually or to let SQLmap have a go at exploiting the vulnerability. After confirming the prompt, SQLmap terminates because there are no further parameters.
SQLmap can output the complete, unfiltered content of the database (--dump-all ) or just individual records (--dbs ). Because a database can contain much irrelevant information, it makes sense to target the most important data to speed up the process. Add --dbs to the command and you will see the available databases.
available databases : [*] cdcol [*] dvwa [*] information_schema [*] mysql [*] test
The information_schema and dvwa databases are worth closer attention. information_schema tells the user about the metadata in the database, such as data types or access privileges. This metadata can be very valuable in the case of a targeted attack. In this case, suppose dvwa appears to be the most interesting database. To retrieve the records from the dvwa database, you would add the -D dvwa option to the command line.
Database: dvwa [2 tables] +-----------+ | guestbook | | users | +-----------+
The output of the command now offers an overview of the tables in the database. To access valuable information, take a closer look at the users table by adding -T users to the command line. The output lists the available columns and their data types (Listing 1).
Listing 1: Users Table
Table: users [6 columns] +------------+-------------+ | Column | Type | +------------+-------------+ | avatar | varchar(70) | | first_name | varchar(15) | | last_name | varchar(15) | | password | varchar(32) | | user | varchar(15) | | user_id | int(6) | +------------+-------------+
To retrieve the table content, now add --dump to the command line. The final command looks like this:
python sqlmap.py -u "http://127.0.0.1/dvwa/vulnerabilities/sqli/?id=1&Submit= Submit#" --cookie="PHPSESSID=ce0aa7922720f3190bf9bbff7f24c434;security=low" --forms -D dvwa -T users --columns --dump
Sqlmap has detected that the password hashes are located in the password table; the program can then run a dictionary attack against them. A few seconds the attack executes, Sqlmap reveals the clear text passwords (Figure 2).
Within just 35 seconds, SQLmap extracted sensitive data from the database.
In combination with Metasploit, SQLmap gives attackers the option of hijacking the underlying system. Users can choose from various modules. Depending on the database, various exploits will give command of the server. The --os-pwn option is used here; it can give an attacker a remote shell on servers that are running Windows 2003 R2.
After adding --os-pwn to the command, select, for example, Option 1 (TCP : Metasploit Framework ) when the program asks you what kind of tunnel to create. SQLmap now attempts to drop a file onto the server and then call the file (Figure 3).
The attacker then needs to choose the payload (i.e., the function to call after executing the exploit). The possible payload options are Meterpreter, Shell, or VNC. Meterpreter is a collection of functions that you can run on the system (Figure 4).
Shell gives you a system shell on the hijacked server, and VNC creates a remote VNC connection to the server that the attacker can use to gain access to the desktop of the target system.
In the lab attack, I restricted the test to a shell option, although Meterpreter would be more useful for a wide-scale attack. Meterpreter can, for example, migrate into processes to gain more extended rights or hide deep in the system as a back door for the attacker to use when accessing the system later. This advanced functionality is beyond the scope of this article.
After selecting Shell , SQLmap uses Metasploit to open a connection to the server; the user is given a remote shell and thus is free access to the server.
SQL injection has thus given the attacker administrative privileges on the server. The attacker now has complete access to all of the server’s system resources and can control, manipulate, and even totally disable the server.
SQL injection is still one of the most dangerous vulnerabilities that web administrators face on today's networks. The development of tools such as SQLmap makes it very easy for hackers to break into systems and cause enormous damage. Thus, developers and administrators must carefully validate the code running on the server and rule out any vulnerabilities.
A strict ruleset for programmers can help close down security holes caused by SQL and other similar programming languages. Also, regular auditing of web applications can improve the overall security of your network; Security experts recommend monthly checks for large-scale applications that are under constant development. Regular inspection of logfiles is also important for revealing traces of any recent intrusion attempts.
Patrik Fehrenbach is currently a student of Computer Networking at the Hochschule Furtwangen University. Fehrenbach is a self-admitted nerd, who is also one of the co-founders of IT-Securityguard.