SQLi (SQL Injection)
In short: An attack technique where attackers inject their own SQL code into a database query via unsecured input fields — can read, alter or delete data.
In more detail: Arises when user input is inserted directly into an SQL query unchecked (string concatenation instead of parameterised queries). A classic example: a login field into which ' OR '1'='1 is entered can bypass the password check. The standard defence is parameterised queries/prepared statements, where user input can never be interpreted as executable SQL code.
In Depth
A vulnerable login query might naively look like this (string concatenation, user input inserted directly):
-- Vulnerable code (NEVER write it like this):
query = "SELECT * FROM users WHERE username = '" + input + "' AND password = '" + pw + "'"
-- Input: username = admin' --
-- Resulting query:
SELECT * FROM users WHERE username = 'admin' --' AND password = '...'
-- The password check is simply commented out by "--" (SQL comment)!Through such manipulations, an attacker can not only bypass the login check, but, depending on the database connection’s privileges, also read entire tables (UNION SELECT to smuggle data from other tables into the output), alter or delete data, or in bad cases even execute commands on the database server itself.
The reliable defence is structural, not “filtering out dangerous characters”:
// Secure: parameterised query - input is NEVER interpreted as SQL code
db.query("SELECT * FROM users WHERE username = $1", [input])With parameterised queries (also “prepared statements”), the application sends the structure of the query and the user input to the database separately — the database itself thereby always knows which part is “code” (the query structure) and which part is pure “data” (the input), no matter what the user types. Modern ORMs (see Drizzle ORM) use parameterised queries internally by default, which is why SQL injection is practically ruled out when an ORM is used correctly — raw SQL with string concatenation remains possible and dangerous in every language/framework regardless.
Blind SQL injection
A vulnerable application doesn’t always output database errors or query results directly — with “blind SQL injection”, the attacker sees no direct feedback, but can still extract information by formulating conditions that visibly influence the application’s behaviour (e.g. a different response time or a different page depending on whether a condition is true or false). An example: ' AND (SELECT SUBSTRING(password,1,1) FROM users WHERE username='admin')='a — if the application gives the same response as without the condition, the guess was correct, otherwise not. Character by character, a complete password can theoretically be extracted this way, even without any visible error messages — considerably slower than classic SQLi, but just as dangerous.
Additional layers of protection
Parameterised queries are the most important, but not the only, line of defence. The principle of least privilege limits the damage even from a successful injection: the database user a web application connects with should only have the permissions actually needed (e.g. no DROP TABLE right for a pure read endpoint). A web application firewall (WAF) can additionally recognise and block known injection patterns in incoming traffic before they even reach the application — as an extra safeguard, not a replacement for secure database access in the code itself. Regular automated security scans (e.g. with tools like sqlmap as part of your own tests) help find accidentally introduced injection holes early, before a real attack does.
See also: SQL, Forged Cookies