Basic SQL Injection for Web CTFs

Tutorial · Web

A login form usually checks your credentials by building a database query out of whatever you typed and running it. When that query is built by directly pasting your input into a string instead of treating it as data, the boundary between "instructions" and "input" disappears — and what you type can change what the query actually does. That's SQL injection, and a login bypass is the simplest version of it to understand.

1. How the vulnerable query is built

A naive login check often looks like this on the server:

SELECT * FROM users WHERE username = '$username' AND password = '$password'

If $username and $password are inserted straight from the form with no escaping, whatever you type becomes part of the SQL itself — not just a value being compared.

2. Breaking the query with a single quote

Typing a single quote (') into the username field closes the string early from the database's point of view. Everything after it in the query is now interpreted as SQL syntax rather than plain text:

Username: ' OR '1'='1
Password: anything

Substituted into the template, the query becomes:

SELECT * FROM users WHERE username = '' OR '1'='1' AND password = 'anything'

'1'='1' is always true, so the OR makes the whole condition true regardless of the actual username or password on file — the query returns a row, and the login logic treats that as a successful authentication.

3. Comment it out entirely

A more reliable version skips needing the password to line up at all by commenting out the rest of the query:

Username: admin' --
Password: anything

SQL's -- starts a comment, so everything after it — including the AND password = '...' check — is ignored:

SELECT * FROM users WHERE username = 'admin' --' AND password = 'anything'

This logs in as admin without needing to know their password at all, which is usually exactly what a login-bypass challenge is asking for.

4. When the filter blocks the obvious payloads

Challenges often strip or block quotes, spaces, or the word OR outright. Common workarounds: replace spaces with /**/ (an inline comment that acts as whitespace to the parser), swap OR for || where the database supports it, or use a numeric field instead of a string field, where no quote is needed to inject in the first place. Every filter bypass here follows the same principle — find syntax that means the same thing to the database but doesn't match whatever pattern the filter is checking for.

Wrapping up

SQL injection at its core is about noticing where user input crosses into being treated as code, then shaping that input to change the query's logic rather than just its data. Login bypass with OR '1'='1 or a trailing -- comment is the entry point; from there the same idea extends to extracting entire databases via UNION SELECT. Our PicoCTF Web Gauntlet writeup walks through bypassing a real filtered login form end to end, and intercepting requests with Burp Suite is the tool workflow you'll usually pair this with.

Back to Blog