🛡️ Introduction
SQL Injection (SQLi) is one of the most dangerous and commonly exploited web application vulnerabilities. It occurs when an application unsafely includes user input in SQL queries, allowing attackers to tamper with database queries, extract sensitive data, bypass authentication, or even compromise the entire server.
In this tutorial, we’ll walk through the process of identifying and exploiting a basic SQL Injection vulnerability using DVWA (Damn Vulnerable Web Application) running on a local, isolated environment. Our target: a vulnerable input field that interacts directly with the backend database.
This hands-on guide is ideal for cybersecurity learners, ethical hackers, or developers who want to understand how SQLi works and how attackers abuse insecure database queries.
💡 If you’re unfamiliar with the basics of SQL Injection, including how SQL queries work and how attackers manipulate them, I highly recommend starting with the excellent TryHackMe SQL Injection room — it provides foundational knowledge before diving into this hands-on practice.
Testing SQL Injection Safely with DVWA
✅ Step 0: Initial Setup
Before testing, make sure of the following:
- Login default credentials as admin:password
- Security Level:
- Set the Security Level to Low.

Page to Test: http://localhost/vulnerabilities/sqli/ or http://127.0.0.1/vulnerabilities/sqli/

✅ Step 1: Understand the Page Behavior
On the SQLi page, you’ll see an input field asking for a User ID and a submit button.
Try inputting number 1

That tells us the backend is using something like:
SELECT first_name, surname FROM users WHERE id='1';
✅ Step 2: Basic SQL Injection Test
Now try entering a single quote ('
):
If the page returns a SQL error, like:

This confirms the field is vulnerable to SQL Injection.
✅ Step 3: Exploiting the Vulnerability (Low Level)
🎯 Example 1: Always True Statement
Try: 1' OR '1'='1

It may return all users because the SQL becomes:
SELECT first_name, surname FROM users WHERE id='1' OR '1'='1';
🎯 Example 2: Commenting the Rest of the Query
Try: 1' OR '1'='1 --
The --
comments out the rest of the SQL, preventing syntax errors.
✅ Step 4: Data Extraction
Let’s extract usernames step-by-step using blind injection.
If this works: 1' AND '1'='1 --
( In boolean logic, the AND operator returns True when combining True and True)

And this fails: 1' AND '1'='2 --
(In boolean logic, the AND operator returns False when combining True and False)

Then you know it’s blind SQLi capable.
To extract database version:
1' UNION SELECT 1, @@version --

🔍 Breakdown
1'
Closes the original query’s single quote (assuming it’s inside something like WHERE id = '1'
).
UNION SELECT 1, @@version
This appends a new query using UNION
, which allows combining the result of the original query with a new one.
1
is just a placeholder to match the first column.@@version
is a MySQL system variable that returns the database server version.
--
This is a SQL comment operator. It tells the database to ignore the rest of the original query, preventing syntax errors.
SELECT first_name, surname FROM users WHERE id='1' UNION SELECT 1, @@version -- ';
To extract all users (if 2 columns):
1' UNION SELECT user, password FROM users --

🔍 Breakdown of Each Part
1'
Closes the current string literal in the vulnerable SQL query. It assumes the application is doing something like:
SELECT first_name, surname FROM users WHERE id = '$id';
Injecting 1'
prematurely ends the id
value.
UNION SELECT user, password FROM users
UNION SELECT
allows you to combine the results of your injected query with the results of the original query — but only if the number and type of columns match.
user
andpassword
are assumed to be column names in the users table.- This returns rows from the
users
table with the values ofuser
andpassword
columns.
--
This is a comment sequence in SQL. It tells the SQL engine to ignore anything after it on that line, preventing syntax errors from the rest of the original query.
What Happens Internally?
Original query:
SELECT first_name, surname FROM users WHERE id = '1';
After injection:
SELECT first_name, surname FROM users WHERE id = '1' UNION SELECT user, password FROM users -- ';
Result:
- If the original query returns one row (like
admin
), the unioned query adds rows containing real usernames and password hashes from theusers
table.
⚠️ Important Notes
- This works only if:
- The original query has two columns in the
SELECT
. - The data types are compatible (e.g.,
user
andpassword
are strings).
- The original query has two columns in the
- In real-world apps, this might reveal hashed passwords or even plain text if security is poor.
Note: DVWA schema has a table called users
with user
and password
columns.
🧠 Final Thoughts
SQL Injection remains a top security risk in web applications, often caused by improper input validation or insecure database handling. In this tutorial, we demonstrated how a simple misstep—like directly embedding user input into a SQL query—can allow attackers to retrieve sensitive information or manipulate application behavior.
Practicing in a controlled lab like DVWA helps build a strong understanding of both the offensive and defensive sides of application security. As you progress, challenge yourself to try more complex injections, explore blind SQLi, and learn how prepared statements can defend against such attacks.
🎯 Remember: never test SQL Injection or any other vulnerability against systems you don’t own or have explicit permission to assess.
If you found this guide helpful, stay tuned for more hands-on security tutorials — and don’t forget to check out foundational training resources like TryHackMe to strengthen your core skills.