SQL Injectie is een van de meest voorkomende beveiligingsproblemen bij websites die een database gebruiken. Het werkt als volgt:
Stel je hebt een inlogformulier. De gebruiker vult een gebruikersnaam in en jouw PHP-code bouwt een query:
$query = "SELECT * FROM users WHERE username = '" . $_POST['username'] . "'";
Als de gebruiker netjes jan invult, wordt de query:
SELECT * FROM users WHERE username = 'jan'
Maar wat als iemand dit invult als gebruikersnaam?
' OR 1=1 --
Dan wordt de query:
SELECT * FROM users WHERE username = '' OR 1=1 --'
OR 1=1 is altijd waar, dus alle rijen worden teruggegeven-- is commentaar in SQL, dus de rest van de query wordt genegeerdNog erger: iemand kan '; DROP TABLE users; -- invoeren en je hele tabel verwijderen.
De oplossing is prepared statements (ook: parameterized queries). Hierbij scheidt je de SQL-structuur van de data:
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ?");
$stmt->execute([$_POST['username']]);
Nu wordt de invoer van de gebruiker altijd als data behandeld, nooit als SQL-code. Zelfs als iemand ' OR 1=1 -- invult, zoekt de database letterlijk naar een gebruiker met die naam.
Regel: Gebruik altijd prepared statements wanneer je gebruikersinvoer in een query verwerkt. Bouw nooit queries door strings aan elkaar te plakken.
Je PHP-code bouwt een query: "SELECT * FROM users WHERE username = '" . $_POST['username'] . "'". Een gebruiker vult in: ' OR 1=1 --. Wat wordt de uiteindelijke query en wat is het effect?
Een kwaadwillende gebruiker vult als gebruikersnaam in: '; DROP TABLE users; --. Wat kan er gebeuren?
Hoe voorkom je SQL Injectie in je code?
Waarom werkt SQL Injectie niet bij prepared statements, zelfs als de gebruiker ' OR 1=1 -- invoert?