SQL injection occurs when three conditions are true simultaneously:
Remove any one of these conditions and the attack fails. The most reliable way to remove condition 2 is parameterized queries.
Normal usage: User enters Professor
SELECT * FROM users WHERE name = 'Professor'
Result: returns the one matching record. Expected and safe.
After injection: User enters Professor' OR '1'='1
SELECT * FROM users WHERE name = 'Professor' OR '1'='1'
Result: the OR clause makes the condition always true β the database returns every row in the users table. The attacker has disclosed the entire dataset without any special credentials or tools.
Authentication bypass: User enters ' OR '1'='1'-- in the username field
SELECT * FROM users WHERE username = '' OR '1'='1'-- ' AND password = '...'
Result: the double-dash comments out the password check entirely. The query returns the first user in the table β often an administrator β without any password being verified.
| Outcome | What the Attacker Does | Example SQL |
|---|---|---|
| View | Read data from any table | ' OR '1'='1 / UNION SELECT |
| Modify | Change records, prices, access levels | '; UPDATE users SET admin=1-- |
| Delete | Destroy tables or entire databases | '; DROP TABLE customers-- |
| Deny | Crash the database, deny access | Heavy queries, SHUTDOWN commands |
The actual impact depends on what SQL commands succeed β which depends on the permissions of the database account the application uses.
- Login forms β username and password fields that build authentication queries
- Search fields β product search, customer lookup, document search
- Registration forms β name, address, email fields written to the database via INSERT
- URL parameters β values passed in the URL query string (e.g.,
?id=5) that are used in a WHERE clause - Admin panels β lookup and management interfaces that query sensitive tables
- API endpoints β backend services that receive JSON or form data and build queries from it
Every field that communicates with the database is a potential injection point. Attackers test them all systematically.
| Layer | Control | How It Prevents SQLi |
|---|---|---|
| 1 β Primary | Parameterized queries | Separates SQL structure from user data β user input cannot become SQL code |
| 2 β Input | Input validation & sanitization | Rejects characters with SQL significance β apostrophes, semicolons, comment markers |
| 3 β DB Design | Stored procedures | Limits available SQL operations to pre-defined routines the application calls by name |
| 4 β Permissions | Principle of least privilege | Limits injection impact β a SELECT-only account cannot run DROP TABLE even if injected |
| 5 β Network | Web application firewall (WAF) | Detects and blocks known injection patterns at the network boundary before reaching the app |
β VULNERABLE β String Concatenation
query = "SELECT * FROM users WHERE name = '" + userInput + "'" db.execute(query)
User input is pasted directly into the SQL string. Any SQL the user types becomes part of the command.
β SAFE β Parameterized Query
query = "SELECT * FROM users WHERE name = ?" db.execute(query, [userInput])
The SQL structure is fixed. userInput is bound as data. The database engine cannot interpret it as SQL code.