SQL Injection Examples on Known Vulnerable Web Applications

From Embedded Lab Vienna for IoT & Security
Jump to navigation Jump to search


This is a documentation of various SQL Injection attacks performed on well-known and also not so popular vulnerable web applications. DRAFT


  • Operating system:


Each example contains a link to the vulnerable web application or to a tutorial how to set it up, unless it is a vulnerable website that is just accessed online. Web applications used:

Each web application is listed below in separate chapters, providing some examples of the SQLi. This Wiki also offers a brief overview over the general types of SQL injection, another somewhat different overview can also be found here: SQL Injection.

Overview - Types of SQL injection [1]

In-band SQLi (Classic SQLi)

In-band SQL Injection is the most common and easy-to-exploit of SQL Injection attacks. In-band SQL Injection occurs when an attacker is able to use the same communication channel to both launch the attack and gather results [1]. There are two under categories of this SQLi type.

  • Error-based SQLi

Error-based SQLi is an in-band SQL Injection technique that relies on error messages thrown by the database server to obtain information about the structure of the database. While errors are very useful during the development phase of a web application, they should be disabled on a live site, or logged to a file with restricted access instead, so that no attacker can see error information displayed directly on the website.

  • Union-based SQLi

Union-based SQLi is an in-band SQL injection technique that uses the UNION SQL operator to combine the results of two or more SELECT statements into a single result which is then returned as part of the HTTP response.

Inferential SQLi (Blind SQLi)

Inferential SQL Injection, unlike in-band SQLi, may take longer for an attacker to exploit, however, it is just as dangerous as any other form of SQL Injection. In an inferential SQLi attack, no data is actually transferred via the web application and the attacker would not be able to see the result of an attack in-band (which is why such attacks are commonly referred to as “blind SQL Injection attacks”). Instead, an attacker is able to reconstruct the database structure by sending payloads, observing the web application’s response and the resulting behavior of the database server.

  • Boolean-based (content-based) Blind SQLi

This technique functions via sending an SQL query to the database which forces the application to return a different result depending on whether the query returns a TRUE or FALSE result. Depending on the result, the content within the HTTP response will change, or remain the same. This allows an attacker to infer if the payload used returned true or false, even though no data from the database is returned. This way, the attacker can ask "true" and "false" questions and in this way GUESS a lot of essential information about the database, such as table/column/attribute names, users, passwords and much more.

  • Time-based Blind SQLi

Sends an SQL query to the database which forces the database to wait for a specified amount of time (in seconds) before responding. The response time will indicate to the attacker whether the result of the query is TRUE or FALSE. Depending on the result, an HTTP response will be returned with a delay, or returned immediately. This allows an attacker to infer if the payload used returned true or false, even though no data from the database is returned. The reason why the previous category is called content-based compared to this, is that here the true/false questions are based on returning the same result with a delay, whilst the content-based returns a different result.

Out-of-band SQLi

Out-of-band SQL Injection is not very common, mostly because it depends on features being enabled on the database server being used by the web application. Out-of-band SQL Injection occurs when an attacker is unable to use the same channel to launch the attack and gather results. Out-of-band SQLi techniques would rely on the database server’s ability to make DNS or HTTP requests to deliver data to an attacker. Such is the case with Microsoft SQL Server’s xp_dirtree command, which can be used to make DNS requests to a server an attacker controls; as well as Oracle Database’s UTL_HTTP package, which can be used to send HTTP requests from SQL and PL/SQL to a server an attacker controls.


This is a web application (http://testphp.vulnweb.com/) created by Acunetix as a test and demonstration site for Acunetix Web Vulnerability Scanner [2][3]. Following are some examples categorized by the previously listed SQLi types on this vulnerable web application.

  • Error-based SQLi

The URL we are targeting is http://testphp.vulnweb.com/artists.php?artist=1, which we want to manipulate. Somehow we want to pass a wrong SQL query to the backend database, to see if we receive an error message. A vulnerable web application will show one, while a secure server should never show error messages to regular website visitors.
Now we try adding a single quote to the SQL query, which generates an error message as shown in the following screenshot.

Next, we try inserting an ORDER-BY clause into the query, which will tell us how many columns there are in the current table and will display the corresponding column. The URL used is http://testphp.vulnweb.com/artists.php?artist=1+order+by+50, estimating the column number at 50. This will generate the same error message as the above screenshot shows, which tells us there are less than 50 columns. By trial and error, the correct number of columns is 3, seen as http://testphp.vulnweb.com/artists.php?artist=1+order+by+3 no longer displays an error (as can be seen in the following screenshot), but the contents of the first column of the artists table.

Conclusion: This SQLi example demonstrated responses of the web application via producing error messages and using these to gather information about the backend database.
  • Union-based SQLi

We will now utilize the UNION query, which allows us to access values from other tables as well by appending the UNION query to our original query. First, we can try using a negative ID, as it is unlikely to be an actual used ID n a database, and append the UNION query, enumerating the values we want. The number of values must be equal to the actual number of columns of the table, otherwise it won't work. From the previous example we know the number of columns to be three, so we must use three values in our query, which will then look like this: http://testphp.vulnweb.com/artists.php?artist=-1+union+select+1,2,3.

In the above screenshot, we can see where our values will be shown (the numbers 2 and 3). These may also be hidden, in which case the page needs to be inspected in the browser to reveal hidden text. Now that we know where to look for the values, we can try to extract some useful information, like database name, version or current user.

We can also insert a whole new statement instead of one of the values, to extract more information. An example would be http://testphp.vulnweb.com/artists.php?artist=-1+union+select+1,2,(SELECT+group_concat(table_name)+from+information_schema.tables+where+table_schema=database()) to view all tables.

You could also view all columns of a specified table once you know the table names:

To view what information is saved about each user in the "users" table, it would look like this:

Conclusion: These SQLi examples demonstrated responses of the web application via extracting information from the backend database utilizing the UNION query. This allowed inserting database functions and separate SELECT statements to formulate new queries and effectively extract column/table names and values.
  • Boolean-based/Blind SQLi

This type of SQLi does not display the actual content from the database like the previous examples, but rather displays two different views depending on whether the query sent to the database returns true or false. We start by determining how the web application reacts with a true query. For this, we use an "always true" query, such as http://testphp.vulnweb.com/artists.php?artist=1+AND+1=1. Afterward, we use an always false query, such as http://testphp.vulnweb.com/artists.php?artist=1+AND+1=2. This offers two different outcomes, as seen in the following figure.

Knowing how the database reacts to a true/false query now allows us to ask it specific questions:
- How long is the name of the database? We can guess the number of letters.
- What is the name of users/tables/columns/the database itself? We can guess each letter.

Such a query to guess the length of the database name would look like this: http://testphp.vulnweb.com/artists.php?artist=1+AND+(length(database()))=6
To guess each letter of i.e. the first table would look like this: http://testphp.vulnweb.com/artists.php?artist=1+AND+(ascii(substr((select+table_name+from+information_schema.tables+where+table_schema=database()+limit+0,1),1,1)))%3E100. Here, ASCII values are used, i.e. 100. The question is whether the first letter is bigger than 100. This query is false, telling us the first letter is in fact smaller than 100 and turns out to be 97, which corresponds to letter "a".

Conclusion: This type of SQLi is more exhausting to execute, as the server can only answer YES or NO. It won't just provide a list of items like the UNION-based. The previous examples demonstrate some of the "questions" the attacker can ask, however the sky is the limit. Any yes/no question is possible here and offers a great way to gather information.
  • Time-based/Blind SQLi

To test against this vulnerability, use the SLEEP() function like this: http://testphp.vulnweb.com/artists.php?artist=1-SLEEP(5). If the response from the web application is delayed, the application is vulnerable. When a query is true, the database lags, and when it is false, there won't be a delay. This way the attacker can ask specific true/false queries just like with the boolean-based SQLi. A true query would be http://testphp.vulnweb.com/artists.php?artist=1-IF((length(database()))=6,SLEEP(5),0), as the database name is 6 letters long. Therefore a false query could be for example http://testphp.vulnweb.com/artists.php?artist=1-IF((length(database()))=7,SLEEP(5),0), which loads right away without delay.

Conclusion: To exploit this vulnerability is a somewhat slower process than the boolean-based SQLi, as it always takes some time to get a response from a database. The "sleep" function also looks different for each kind of database, so the knowledge of the used server is necessary.

OWASP Mutillidae

A dedicated wiki article with an explanation of this vulnerable web application can be found here: OWASP Mutillidae. We will now focus on the SQL injection in the "OWASP 2017" category, which looks like this:

  • Overview of SQL injection in OWASP Mutillidae
  • SQLi - Extract Data

We will try for an error-based SQLi, inserting a false query. The error-message that is displayed afterwards gives us a lot of information about the backend structure, and how the SQL query looks like.

  • Error message

Now we insert ' OR 1=1 -- (with whitespace behind the double dash) which executed the query SELECT * FROM accounts WHERE username= OR 1=1, which always returns true, thus returns the "accounts" table

  • Extracts all entries from the "accounts" table

We will try the union-based SQLi now. To do this we must match the number of columns. Let's first try this query: ' union select null -- . We get this error:

error: The used SELECT statements have a different number of columns

We keep appending values to increase the number of columns until we get no error with the query ' union select 1,2,3,4,5,6,7 -- :

  • Mutillidae4.png

Now that we know which values are displayed, we can replace 2,3,4 with the data we want to extract.

  • Get database name and version

To extract information about the tables, use the query ' union select 1,table_name,null,null,5,6,7 from information_schema.tables where table_schema = 'mutillidae' -- :

  • Get database name and version
  • SQLi - Reading and writing data on the Webserver

We can use the “LOAD_FILE()” operator to read out the contents of any file contained within the webserver [4]. We will typically check for the “/etc/passwd” file to see if we get lucky and scoop usernames and passwords to possibly use in brute force attacks later. Below is a list of some sensitive files on Linux systems:


To read the contents of the “/etc/passwd” file, we enter the query ' union select 1,load_file('/etc/passwd'),3,4,5,6,7 -- :

  • Read data from webserver's /etc/passwd

To write into a file on the server, use "into outfile". An example query would look like this: ' union select 1,'PS: This is a hacker',3,4,5,6,7 into outfile '/tmp/hello.txt' -- We can verify the created file.

  • Read data from webserver's /etc/passwd
  • SQLi - Bypass Authentication

This category lands us on the login page. When we enter an always true query, such as ' OR 1=1 -- , we get logged into the web application.

  • SQLMap

SQLMap is a tool for detecting and taking advantage of SQL injection vulnerabilities in web applications. Once it detects one or more SQL injections on the target host, the user can choose among a variety of options to perform an extensive back-end database management system fingerprint, retrieve DBMS session user and database, enumerate users, password hashes, privileges, databases, dump entire or user’s specific DBMS tables/columns, run his own SQL statement, read specific files on the file system and more [5]. To execute SQLMap, first we want to enter false credentials onto the Mutillidae login page, and copy the URL that this query creates. Then we use this URL in our SQLMap command, which looks like this (the IP is no longer localhost, because the SQLMap was executed on the Mutillidae that is on the Metasploitable VM by default):

sudo sqlmap -u ""


WebGoat is a deliberately insecure web application maintained by OWASP designed to teach web application security lessons [6]. The documentation wiki can be found here: WebGoat. For details please refer to the official GitHub.

There are four under-categories in the SQLi category:

  • SQLi intro
  • SQLi advanced
  • SQLi mitigation
  • Path traversal

In the screenshot below, the overview of different challenges/lessons is available:

  • Home page

We will be focusing on SQL injection, which is the A1 category above. The following screenshots are examples from the SQLi intro category:

  • String SQL injection
  • Numeric SQL injection
  • Compromising confidentiality
  • Compromising integrity, Authentication TAN: 3SL99A'; UPDATE employees SET salary=10000000 WHERE auth_tan='3SL99A' --
  • Action contains: update'; drop table access_log --

Following are examples from the category SQLi advanced:

  • Name: update'; select * from user_system_data;--
  • An alternative solution--> ' union select user_name, password, cookie, 4, 5, 6, 7 from user_system_data; --

    When working with the UNION operator, there are two rules that need to be kept in mind, which also explain the syntax of the injected command:

    * The number of columns selected in each statement must be the same.

    * The datatype of the first column in the first SELECT statement, must match the datatype of the first column in the second (third, fourth, …​) SELECT Statement. The Same applies to all other columns.


The VM can be downloaded here[7]. After setting up the VM, you need to find its IP address to be able to access the web interface from another VM. In our case, Badstore's IP address is

Landing page of Badstore

We navigate to the login page first. To try for a basic SQL injection vulnerability, we will try entering a hyphen. This shows the following error message from the database, revealing a vulnerability to error-based SQLi.

DBD::mysql::st execute failed: 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  'd41d8cd98f00b204e9800998ecf8427e at line 1 at /usr/local/apache/cgi-bin/badstore.cgi line 1144.

We now test the search field, and search for "test1". Below can be seen the reaction of the server, which reveals the whole SQL query.

Landing page of Badstore

Here it can be experimented with all the previously mentioned techniques. We will focus on gaining access to the database via finding the user login data.

Now let's look at the "userdb" table, whose name can be guessed based on the name of "itemdb" table. This has 4 columns, as can be seen below with the query 1’=’0’ UNION SELECT 100, 200, 300, 1000 from userdb #.

query 1’=’0’ UNION SELECT 100, 200, 300, 1000 from userdb # revealing where to look for extracted values from the database

To find out the field names, we can inspect the login page, which reveals the following information:

Inspect register form of login page

We will extract the users with their emails, full names and password hashes:

Users list with xx' IN (itemnum,sdesc,ldesc) union select email,fullname,passwd,123 from userdb --

This is an MD5 hash, which can be cracked with the tool "John" in Kali Linux.

Revealed passwords


The so-called damn vulnerable web app (DVWA) is a vulnerable PHP / MySQL web service [8][9]. For the wiki article with a tutorial on how to set up the DVWA and specific SQLi examples, please refer to DVWA wiki.


The BWAPP, the so-called buggy web application, is a PHP application that uses a MySQL database. It is documented in the wiki article BWAPP. There is a tutorial on installation and examples of the SQLi.


  1. Acunetix, Types of SQL Injection (SQLi), 2022, accessed on: 05.01.2022. [Online]. Available: https://www.acunetix.com/websitesecurity/sql-injection2/
  2. Acuart test and demonstration site, 2022, accessed on: 05.01.2022. [Online]. Available: http://testphp.vulnweb.com/
  3. Acunetix web vulnerability scanner, 2022, accessed on: 05.01.2022. [Online]. Available: https://www.acunetix.com/
  4. David Artykov, Exploiting SQL injection vulnerabilities, July 2020, Purple Team, accessed on: 05.01.2022. [Online]. Available: https://medium.com/purple-team/exploiting-sql-injection-vulnerabilities-76df9b85dd7
  5. Kali Tools Page, sqlmap, accessed on: 05.01.2022. [Online]. Available: https://www.kali.org/tools/sqlmap/
  6. WebGoat Github, WebGoat, 2022, accessed on: 08.01.2022. [Online]. Available: https://github.com/WebGoat/WebGoat
  7. Vulnhub, Badstore: 1.2.3, 24 Feb 2004, Badstore, accessed on: 25.01.2022. [Online]. Available: https://www.vulnhub.com/entry/badstore-123,41/
  8. DVWA, 2022, accessed on: 05.01.2022. [Online]. Available: https://dvwa.co.uk//
  9. DVWA Github, 2022, accessed on: 05.01.2022. [Online]. Available: https://github.com/digininja/DVWA