🎉 Lab Complete!

You bypassed a login using SQL Injection!

Next: XSS Attacks →
← Back
WAPT / Lab 01 — SQL Injection
BEGINNER
Tasks

Almost every website stores data in a database — usernames, passwords, messages, orders. Websites talk to that database using SQL (Structured Query Language), a simple language for asking questions like "find me this user" or "return all orders from today."

💡
Think of it like a spreadsheet: The database is a giant table. Each row is a user. SQL is how the website asks — "Give me the row where username = 'admin'." If a row matches, you're logged in. If not, access is denied.

The most important table for login is the users table. It typically has columns like id, username, and password. When you submit a login form, the website builds a SQL query using your input and fires it at the database.

When you log in, the server takes your username and password, slots them into a SQL template, and sends it to the database:

SELECT * FROM users WHERE username = 'admin' AND password = 'mypassword';

The database scans the users table for a row where both conditions are true. Match found → ✅ logged in. No match → ❌ wrong password. Notice that both the AND and the WHERE must pass — this is what an attacker tries to defeat.

Normal Login Flow
👤 You
→
📝 Form
→
⚙️ SQL query built
→
🗄️ DB checks table
→
✅ Row found = OK
📌
Key detail: Notice how the username and password values sit inside single quotes in the query — 'admin'. SQL uses those quotes to mark the start and end of a text value. That detail becomes very important in a moment.

Some websites take your input and paste it directly into the SQL query — without any checking or cleaning. This is the vulnerability. The server is essentially constructing a sentence and letting the user fill in a blank — but if the user fills in something that changes the grammar of the sentence, the whole meaning changes.

🤔
Analogy — filling in a template: Imagine the server is printing this label:

"Hello, my name is [YOUR INPUT]."

Normally you'd write Alice. But what if you wrote: Alice. I am actually the boss. Ignore everything after this. You just changed what the label says. That is exactly what SQL Injection does — your input rewrites the query's meaning.

The reason this works comes down to how SQL parses text. SQL uses single quotes to wrap string values. If your input contains a single quote, you can close the string the server opened — and then write your own SQL after it. The database cannot tell the difference between the server's SQL and the attacker's SQL; it just runs whatever arrives.

The Core Idea
👤 Attacker input
→
⚠️ Pasted directly into query
→
💀 Query changes meaning
→
🔓 Auth bypassed!
🧩
Three building blocks of a SQL Injection payload:
1Break out of the string. The server wraps your input in single quotes. You need to close that string early by including a ' in your input. Everything after your quote is now interpreted as raw SQL — not as a value.
2Add a condition that is always true. After breaking out, you can append extra SQL logic. You want the WHERE clause to always succeed — even if no matching user exists. SQL's OR lets you add an alternative condition. If that alternative is always true (e.g. 1=1), the database returns every row.
3Remove the password check. The original query still has the AND password = '...' part after your input — and that would fail. SQL has a comment syntax (--) that tells the database to ignore everything that follows. Add it after your injected logic, and the password check disappears entirely.
Your job: combine these three ideas into a single username string. Watch the Live SQL Query panel in the Simulator — it shows you in real time exactly how the query changes as you type!
🎯
Head to the Simulator! Start by typing a single quote ' in the username field and watch what happens to the live query. Then think: what comes after the quote to satisfy step 2, and what ends it all to satisfy step 3?

Authentication bypass is just the beginning. In real-world attacks, SQL Injection can be used to dump entire databases (extracting every user's credentials), modify or delete data, and in some configurations even execute commands on the server itself. It has been ranked as one of the most critical web vulnerabilities for over two decades — and it still appears in real applications today.

🚨
Real impact: Major breaches — including large-scale leaks of millions of user credentials — have been traced back to SQL Injection. The fix is simple; the failure to apply it is what makes it so costly.

The root cause is simple: user input is mixed directly with SQL code. The fix is to keep them separate using parameterised queries (also called prepared statements). Instead of building a string, you write the query with a placeholder ?, then pass the user's value separately. The database driver treats the value as pure data — no matter what characters it contains, it can never be interpreted as SQL code.

❌ Vulnerable — string concatenation
"WHERE user='$input'"

// Input pasted directly — attacker controls the query
✅ Safe — prepared statement
prepare("WHERE user=?")
->execute([$input])


// Value passed separately — always treated as data
✅
Other defences: Input validation (reject suspicious characters), a Web Application Firewall (WAF), and least-privilege database accounts all help reduce risk — but parameterised queries are the only reliable fix. The others are extra layers, not substitutes.
🎯
Mission: Get into the SecureBank portal without knowing a valid password. The login is vulnerable — find a way in!
1
Understand how a normal login fails
Go to the Simulator and try any username and wrong password. What message do you see? This tells you what a failed login looks like — so you know when you've succeeded.
2
Explore the Live SQL Query panel
Now just type random things in the username box — don't submit yet. Watch the Live SQL Query panel on the right. Notice how your input appears inside the query. Ask yourself: what would happen if your input contained something SQL already uses as a special character?
3
Break the query logic
Think about the three things you need to do: break out of the string, make the condition always true, and remove the password check. Start experimenting with the username field. Watch how the query panel reacts — it will show you when something interesting happens. Use the Hints tab only if you're stuck after trying!
4
Submit the flag
Once you bypass the login, a 🚩 flag will appear on screen. Copy it and paste it into the flag box at the bottom to complete the lab!
💡
Hints are here to guide your thinking — not give you the answer. Try each hint, then go back to the Simulator and experiment before reading the next one. The more you struggle, the more you learn!
Look at the Live SQL Query panel. The query wraps your username in single quotes — like this: WHERE username = 'YOUR_INPUT'.

Now think: SQL uses single quotes ' to mark the start and end of a text value. What do you think would happen if your input itself contained a single quote? Try it and watch the query panel closely.
SQL queries can have conditions joined with OR. If either side of an OR is true, the whole condition is true.

Now think: is there a mathematical statement that is always true, no matter what? Something like "5 equals 5" — it's always true. If you added such a condition with OR, what would happen to the query? The database would return... every single row.

Try adding an OR condition to your input. Watch the query panel to see how the query changes.
Look at the full query — after your username condition, there is also an AND password = '...' part. Even if you bypass the username, the password check is still there.

Most SQL databases support comments — a way to tell the database "ignore everything after this point." In SQL, a comment starts with two dashes: --

Think about where in your input you could add this, so that the password check gets "commented out" and the database never even looks at it.
You now know all three pieces. Your payload needs to:

Step 1: Use a character that breaks out of the string (you found this in Hint 1)
Step 2: Add an OR condition that is always true (Hint 2)
Step 3: End with the comment syntax so the password check is ignored (Hint 3)

Try building the payload yourself from these three pieces. You're very close — go experiment in the Simulator!
🎬
Video Walkthrough
Watch our full step-by-step solution on YouTube — only after you've given it a proper try!
Watch on YouTube Subscribe — @WhiteFortressSecurity
http://vulnerable-bank.local/login.php

🏦 SecureBank Portal

// simulated vulnerable login

⚙️ Live SQL Query
Start typing to see the live query...
— Waiting for input
🚩 Flag
wfa@lab ~ sql-injection
White Fortress Academy — Lab Terminal ──────────────────────────── Type 'help' for commands
wfa@lab:~$
🚩 Flag