In dit artikel ga je erachter komen wat een SQL-injectie (SQLi) is, ook wel SQL injection in het Engels genoemd. Door de makkelijke uitleg en de SQL-injectie voorbeelden ga je het goed begrijpen. Ook leer je welke soorten SQL-injecties er zijn en hoe je het kan voorkomen met PHP. Tot slot geven we tips hoe je meer over SQL en PHP kan leren. Lees lekker verder!
Wat is een SQL-injectie?
Een SQL-injectie is iets waar websitebeheerders niet blij van worden. Gelukkig kan je een SQL-injectie voorkomen en je website ertegen beschermen.
Maar wat is een SQL-injectie dan precies? Een SQL-injectie is een aanval waarbij de hacker instructies via SQL geeft.
Dit gebeurt vaak via een invoerveld, waarbij bijvoorbeeld om een gebruikersnaam wordt gevraagd, of via een URL.
Op deze manier kan de hacker een database aanpassen en zelfs helemaal kapot maken. De hacker kan eventueel zelfs de server overnemen.
Veel websites gebruiken SQL als taal om te communiceren met een database. Vandaar dat hackers ook vaak SQL-injecties uitvoeren.
Je leest weleens op het nieuws dat hackers data hebben gestolen van een bedrijf en gevoelige informatie op straat komt te liggen. Vaak komt dit door SQL-injecties.
Voorbeelden van SQL-injecties
Als het goed is weet je nu (iets) beter wat SQL-injecties zijn. Echter ga je het met voorbeelden van SQL-injecties nog beter begrijpen. Je krijgt er een beter beeld bij.
Vaak worden SQL-injecties uitgevoerd via invoervelden. Ook bijvoorbeeld via een URL is het mogelijk om een SQL-injectie uit te voeren.
Aan de hand van deze twee methodes krijg je voorbeelden van SQL-injecties te zien. Als je nog geen kennis hebt van SQL, dan is het verstandig om eerst het artikel “SQL leren” te lezen.
Via een invoerveld
Stel dat je op een website jouw gegevens kan zien door een nummer in te vullen dat aan jouw account is gekoppeld. In een invoerveld vul je dan je persoonlijke nummer in en de server verwerkt dit met de volgende query:
SELECT * FROM Gebruikers WHERE id = 547825;
Uit de database worden met deze query onder andere je voor- en achternaam, leeftijd en adres gehaald. Dit krijg je te zien op het scherm.
Hier is in principe niks mis mee als alleen jij je persoonlijke nummer weet en het invoerveld is beschermd tegen SQL-injecties.
In dit geval stellen we even voor dat het invoerveld niet is beschermd tegen SQL-injecties. Hierdoor kan een hacker bijvoorbeeld ook “547825 OR 1=1” invullen.
De query komt er dan zo uit te zien:
SELECT * FROM Gebruikers WHERE id = 547825 OR 1=1;
“OR 1=1” is altijd waar en daardoor krijg je alle rijen uit de “Gebruikers” tabel te zien. Hier kan gevoelige informatie tussen zitten.
Met deze gevoelige informatie kunnen hackers slechte dingen doen, zoals de data verkopen of andere accounts hacken.
Ook kan een hacker bijvoorbeeld de hele tabel uit de database verwijderen, door bijvoorbeeld “547825; DROP TABLE Gebruikers” in te vullen. De query ziet er dan zo uit:
SELECT * FROM Gebruikers WHERE id = 547825; DROP TABLE Gebruikers;
Op deze manier kunnen hackers verschillende instructies via SQL meegeven in een invoerveld. Echter houden we het nu bij deze twee simpele voorbeelden, zodat je het goed begrijpt.
Via een URL
Stel dat een hacker erachter is gekomen dat een website niet beschermd is tegen SQL-injecties en het mogelijk is om aanvallen te doen via een URL.
Dan is er van alles met de database van de website mogelijk. Als voorbeeld nemen we een (niet bestaande) website die op deze manier een product laat zien: https://ergzwakkewebsite.nl/products.php?id=1
De hacker is ook achter de naam van de tabel gekomen waarin alle producten staan en de namen van de kolommen van de tabel.
Op deze manier kan de hacker dan de prijs van een product aanpassen via de URL: https://ergzwakkewebsite.nl/products.php?id=1;UPDATE%20products%20SET%20price=100%20WHERE%20id=1
De hacker heeft nu het product dat 1 als id heeft naar 100 (euro) geüpdatet. Voor websitebeheerders is het natuurlijk een horrorscenario als hackers dit kunnen doen.
De hacker zou zelfs met deze URL alle producten uit de database kunnen verwijderen: https://ergzwakkewebsite.nl/products.php?id=1;DELETE%20FROM%20products
Net zoals bij een invoerveld kunnen hackers hier ook uit de voeten met verschillende instructies via SQL. We laten het hier ook bij deze twee voorbeelden, zodat het goed te begrijpen is.
Soorten SQL-injecties
Er zijn verschillende soorten SQL-injecties. Hieronder bespreken we kort de drie soorten, zodat je daar een beeld bij krijgt.
In-band SQLi
In-band SQLi is de meest voorkomende soort, doordat het ook niet lastig is om uit te voeren. De hacker kan SQL-injecties uitvoeren en het resultaat daarvan zien op dezelfde server.
Inferential SQLi
Inferential SQLi staat ook wel bekend als “blind SQL injection”. De hacker krijgt niet direct resultaten te zien, vandaar “blind SQL injection”.
De bedoeling is om achter de structuur van een database te komen. Op deze manier probeert de hacker erachter te komen waar de zwakke plekken liggen.
Out-of-band SQLi
Out-of-band SQLi is een ernstige soort, omdat de hacker data uit een database stuurt naar een andere server, die in zijn beheer is.
SQL-injecties voorkomen met PHP
SQL-injecties zijn een nachtmerrie voor websitebeheerders, maar gelukkig zijn ze wel te voorkomen. Je ziet hieronder een voorbeeld met prepared statements om SQL-injecties te voorkomen met PHP.
Als voorbeeld gebruiken we de to-do list die je kan maken hier op ProgrammeerPlaats. Als je de to-do list hebt gemaakt, dan kan je lokaal op je computer via deze URL een taak updaten: http://localhost/to-do-list-php-pdo-mysql-database/update.php?id=2
In dit geval moet je dan wel een taak met 2 als id hebben. De applicatie is niet beschermd tegen SQL-injecties.
Via deze URL kan je dan bijvoorbeeld de naam aanpassen van degene die een taak met 4 als id heeft: http://localhost/to-do-list-php-pdo-mysql-database/update.php?id=2;UPDATE%20taak%20SET%20naam=%27Merel%27%20WHERE%20id=4
Je ziet nu dat er een instructie in SQL achter de URL staat, waarin de naam van degene die een taak met 4 als id heeft wordt geüpdatet naar Merel.
Je wil natuurlijk niet dat dit mogelijk is in je applicatie. Op deze manier kan iedereen zomaar data veranderen in de database.
Met deze code in PHP voorkom je SQL-injecties, zoals de SQL-injectie via een URL die hierboven beschreven is:
// Statement voorbereiden met :id als placeholder $select = $conn->prepare("SELECT * FROM taak WHERE id=:id"); // Placeholder :id koppelen aan variabele $id $select->bindParam(':id', $id); // Query uitvoeren $select->execute();
Je ziet nu dat de variabele $id
niet direct in de query staat. In plaats daarvan staat er een placeholder :id
in de query.
In regel 2 wordt de query met de placeholder alvast naar de server gestuurd en vindt de voorbereiding plaats. De query wordt alvast opgeslagen.
De bindParam()
function koppelt de placeholder :id
aan de variabele $id
in regel 5. In de laatste regel wordt de query uitgevoerd, nadat de placeholder en variabele aan elkaar gekoppeld zijn.
Doordat de variabele $id
pas later wordt toegevoegd aan de query, wordt de logica van de query niet meer aangepast. Dus als een hacker een extra instructie in SQL achter de URL zet, dan kan dat geen kwaad.
In het “update.php” bestand van de to-do list kan je de code aanpassen, als je bezig bent geweest met deze applicatie. Dan is dat gedeelte in ieder geval beschermd tegen SQL-injecties.
Als dat gelukt is, probeer daarna om de gehele applicatie te beschermen tegen SQL-injecties. Op GitHub kan je zien hoe de rest van de applicatie is beschermd tegen SQL-injecties.
Leer meer over SQL en PHP
Hopelijk begrijp je nu beter wat een SQL-injectie is. Aan de hand van voorbeelden en soorten SQL-injecties zal het vast duidelijker voor je zijn geworden.
Ook erg leerzaam is om SQL-injecties te voorkomen met PHP, vooral als je al met PHP bezig bent of je jezelf daarin meer wil verdiepen.
Het artikel “SQL leren” is een aanrader om meer te leren over SQL en het artikel “PHP leren” is interessant om meer over PHP te leren.
Blijf vooral niet stilzitten en ga lekker verder met leren!
Heb je nog vragen en/of opmerkingen? Laat dan hieronder een reactie achter of neem contact op.