A SQL injection occurs when a server builds an SQL query by string-concatenating user input, so attacker-supplied metacharacters such as ' (string delimiter), -- (inline comment), or ; (statement separator) are parsed by the database as code rather than as data.
<?php$query = "SELECT * FROM users WHERE email = '" . $_POST["email"] . "' AND password = '" . $_POST["password"] . "'";$sth = $db->query($query);?>
Authentication Bypass
Example
Submitting email=admin@localhost' -- turns the query into
SELECT * FROM usersWHERE email='admin@localhost' -- ' AND password='foobar'
The -- comments out the password check, so the attacker authenticates as admin without a password.
Data Exfiltration via UNION
Column-count probing
The attacker does not know the number of columns of the original SELECT, so they probe with UNION SELECT null, null, … until the query no longer errors. null is type-compatible with every column. Then a second UNION SELECT lifts real columns out of the database:
' UNION SELECT null, mail, password FROM people -- -
Every column in a UNION must have the same count (and, depending on the DBMS, compatible types); LIMIT applies to the whole result set.
Exfiltrating Database Metadata
Enumerate the schema via information_schema
The attacker generally does not know the schema. Relational databases expose their metadata through the information_schema: information_schema.tables and information_schema.columns list every database, table, and column name. A UNION SELECT against these lets the attacker map the schema and then read sensitive tables column by column.
' UNION SELECT table_schema, table_name FROM information_schema.tables -- -' UNION SELECT null, column_name FROM information_schema.columns WHERE table_name = 'users' -- -
Obs
SQLi enables authentication bypass, data exfiltration, data loss and corruption, denial of service, and — through privilege escalation — RCE on the database host.