Learning SQLi with Damn Vulnerable Web Application
SQL injection (SQLi) is an attack which involves taking advantage of improper/non-existent SQL user input validation.
With SQLi, attackers can communicate with the back-end server database using standard SQL commands (SELECT
, UPDATE
, DELETE
, JOIN
, etc) from any standard input HTML element that communicates with a database server; for example, a standard account login form.
Mitigation of SQLi can be any of the following:
- User input sanitation/validation
- Avoiding dynamic SQL - only allowing users a preset block of query statements prevents potential information disclosure at the risk of having a slightly less adaptable web application as a whole
- Use of up-to-date versions of SQL database technologies
- And many more..
Fortunately, packaged web applications exist that serve as educational tools for things like SQLi, such as Damn Vulnerable Web Application (DVWA); what I’m using today. To make things simple, I downloaded the LiveCD and loaded it up in VMware Player.
When you first startup your VM, you’ll reach the following screen at first, simply press enter to continue the install:
That will give you the LiveCD GRUB menu, at which I chose “install - start the installer directly”:
Once the VM boots, run a quick ifconfig
to see what IP it grabbed (if you’re using DHCP):
Now that the DVWA is up and running, let’s switch over to our Kali system and verify connectivity with the web app. I ran a simple SYN scan with nmap
to fingerprint the open ports on the DVWA VM:
nmap -sS 192.168.1.105
PORT STATE SERVICE
21/tcp open ftp
22/tcp open ssh
80/tcp open http
443/tcp open https
3306/tcp open mysql
...snip..
That tells us that it is serving HTML on port 80, so let’s visit the site using our browser:
That will take us to the main DVWA logon page. This is the web application login; login with the default creds admin
and password
. That will take you to the main page, at which we select DVWA Security.
The security level is set to High by default. Set the security level to Low for now.
Navigate to the SQL Injection page, and take note of the User ID field. This field accepts an integer value, which identifes the UserID
variable in a standard SQL query to the database. If we enter in 1
into the field, it will return the following (as it should):
The above query to the database loosely followed this syntax:
SELECT firstname, surname FROM users WHERE id='$id'
When we specified the id of 1
, the database returned the firstname/surname values of the element at that index (1). This is the correct behavior.
Now, we can test if the web application is truly sanitizing user inputs, by crafting the following statement:
%' or 1=1#
Let’s dissect that input.
%
symbol is the wildcard symbol for MySQL, telling the database server to treat our UserID equal to any value'
closes the quotations around the wildcard symbol in the SQL statement (this is for valid syntax purposes)or
continues the SQL statement, and tells the SQL server to also evaluate the next statement (as opposed to simply checking if the index of % is valid)1=1
is the statement that essentially is always true, meaning that the SQL server evaluates this statement, and returns all requested information at all given indexes because that statement is always true.#
ensures that all following parts of the SQL statement are treated as a comment (this prevents syntax errors)
The statement would be interpreted by the database as:
SELECT firstname, surname FROM users WHERE id='%' OR 1=1#
We can see the following output from the database:
It worked, there is no/improper input validation.
With this information, we can manipulate our statement to return different elements in the table, and potentially elements in columns of the table that hold sensitive information.