Lesson 2 · Reading · 30 min
SQL injection: finding it
SQL injection is the highest-impact common web bug: reach a database query and you can often read every user, every password hash, every record. But before extraction comes detection, proving that your input reaches the query and can change it. This lesson is how to find SQL injection.
Where SQL injection lives
Any input the application uses to build a database query is a candidate, and almost every app queries a database on almost every page. So the surface is huge:
- Search boxes:
?q=laptopbecomesWHERE name LIKE '%laptop%'. - Filters and sorting:
?category=5,?sort=price. - Login forms:
WHERE user='...' AND pass='...'. - URL path ids:
/product/42. - Anything numeric or textual that selects, filters, or looks something up. Also headers and cookies the app logs or queries.
Your job in detection is to send input that would be harmless as data but meaningful as SQL, and watch for a reaction.
The first probe: a single quote
The classic test is one character: '. If your input is dropped into a quoted string in the query and not handled safely, a lone quote unbalances the SQL and the database throws an error. So:
?q=laptop'
Watch the response. Three things can happen:
- A database error appears ("SQL syntax", "unclosed quotation mark", "SQLite3::query"). Strong signal: your quote reached the query and broke it. This is error-based detection.
- The page breaks silently: a
500, a blank result, a different layout. Also a signal: something choked on your quote even if the error is hidden. - Nothing changes. Either it is not injectable, the input is numeric (try without quotes), or errors are suppressed (you will need blind techniques, lesson 4).
Confirming with true and false
An error proves the query broke; the sharper confirmation proves you can control the logic. Send a payload that should always be true, and one that should always be false, and show the results differ in a way only SQL could cause.
For a string context (your input sits inside quotes):
?q=laptop' AND '1'='1 → normal results (condition true) ?q=laptop' AND '1'='2 → no / different results (condition false)
For a numeric context (no quotes around your input):
?id=42 AND 1=1 → normal ?id=42 AND 1=2 → different
If the "true" version behaves like the original and the "false" version changes the results, your input is being evaluated as part of the query's logic. That is SQL injection, confirmed, without needing an error message.
Reading the context
To exploit it you need to know how your input sits in the query, and the probes tell you. If ' causes an error but ' AND '1'='1 fixes it, you are inside single quotes. If a bare AND 1=1 works without quotes, you are in a numeric context. If quotes do nothing but a different character (a backtick, a parenthesis, a %) misbehaves, adjust. You are reverse-engineering the shape of the surrounding query so your next payload closes it cleanly.
A note on -- and comments
Once you inject, the rest of the developer's query is still there after your input and can get in the way. SQL comment syntax lets you cut it off: -- (with a trailing space) or # in MySQL comments out everything after your payload. So a real detection/exploitation payload often ends in a comment:
?q=laptop' OR '1'='1' --
which turns the query into your logic followed by a comment that swallows the developer's trailing quote and clauses.
Login bypass, the famous one
The reason SQL injection is legendary: applied to a login, WHERE user='...' AND pass='...', sending the username admin' -- comments out the password check entirely:
SELECT * FROM users WHERE user='admin' -- ' AND pass='whatever'
The database sees "find user admin" and ignores the commented-out password clause. If the app logs you in as the first returned row, you are admin without a password. Try it wherever you find a login you are authorised to test.
Keep it honest and gentle
Detection payloads should be read-only and harmless. AND 1=1 reads; it changes nothing. Never test with OR 1=1 on an UPDATE or DELETE endpoint, and never with DROP/DELETE payloads, you could wipe real data. On a real target, confirm with the gentlest boolean probe, then stop; you have proven injection without touching a row. On this lab, you are safe to go further.
Your lab
BookNook search (SQL injection) is a search feature that builds its query from your input. Start with a single quote and read the reaction, then confirm with true/false probes and work out the context. When you can make the search return results it should not, you have found and confirmed SQL injection in a realistic app, the "identify" half of the exam objective. The next lesson is the "exploit" half: pulling real data out with UNION.
Where this goes next
Finding injection is the start. The next lesson turns a confirmed injection into data on your screen using UNION SELECT: appending your own query to read tables that were never meant for you.
This lesson has 2 labs to try what you just read.