SQL
Injection Complexe website gebruiken vaak databases om
gebruikersnamen, wachtwoorden en andere gegevens van gebruikers op te slaan. Er
wordt gebruik gemaakt van formulier met gebruikersnaam/wachtwoord om een
gebruiker te identificeren.
Een eenvoudig inlogpagina kan er als volgt uitzien:
Wanneer een gebruiker inlogt met als gebruikersnaam "Piet" en wachtwoord
"autosleutel" zal de query er als volgt uitzien:
SQL = "SELECT * FROM gebruikers WHERE gebruikersnaam='Piet' AND
wachtwoord = 'autosleutel'"
Wanneer de recordset leeg is krijg je een foutmelding en anders wordt je
doorgestuurd naar de admin pagina. Wat gebeurt er nu wanneer je als
gebruikersnaam ' OR ' invult en als wachtwoord ' OR '. De query wordt dan:
SQL = "SELECT * FROM gebruikers WHERE gebruikersnaam='' OR ''
AND wachtwoord = '' OR ''"
Op deze manier selecteer je alle records waardoor je toegang krijgt tot
admin.asp. Wanneer je dit zelf probeert en je komt in het admin gedeelte
terecht, is je pagina niet beveiligd tegen SQL injection. Dit is te verhelpen
door de quotes te vervangen door twee quotes:
Het is natuurlijk ook mogelijk om meer statements uit te voeren zoals het
verwijderen van alle gegevens uit de tabel. Dit kan bijvoorbeeld wanneer je met
behulp van een ID het juiste artikel uit de database wilt halen
(artikel.asp?ID=34):
SQL = "SELECT * FROM artikelen WHERE artikelID = " &
request.querystring("ID")
Bepaalde databases ondersteunen het uitvoeren van meerdere statements
achterelkaar. Als de gebruiker de volgende URL intypt: "artikel.asp?ID=25;DELETE
* FROM artikelen" is het mogelijk om alle gegevens uit de tabel te verwijderen.
De query ziet er dan als volgt uit:
SQL = "SELECT * FROM artikelen WHERE artikelID = 25;DELETE *
FROM artikelen"
Om dit te voorkomen is het belangrijk om eerst te kijken of de ID numeriek
is. Dit kan bijvoorbeeld met de functie isNumeric. Dit soort functies zijn erg
belangrijk om de gebruiker ook geen foutmeldingen te laten zien.
Foutmeldingen Een ander belangrijk aspect is de afhandeling van
fouten. Een foutmelding geeft vaak gedetailleerde informatie weg over hoe de
fout is ontstaan. Dit kan interessante informatie voor "hackers" opleveren.
Een veel gebruikte methode om artikelen te tonen is het doorgeven van de ID
via de URL. Afhankelijk van de ID wordt het juiste artikel uit de database
gehaald. Wanneer je bijvoorbeeld in plaats van "artikel.asp?ID=34",
"artikel.asp?ID=Dit geeft een foutmelding" intypt, dan kan er een foutmelding
worden gegeven over bv de locatie van de database.
Enkele tips:
Controleer eerst of de ID in de database voorkomt. Komt de ID niet voor, dan
weet je dat de invoer ongeldig is en kan je de gebruiker naar een andere pagina
doorsturen of de ID vervangen door een geldig ID (bv de ID van het laatste
artikel). Komt de ID wel voor in de database, dan kan het script verder
uitgevoerd worden. Op deze manier hoef je eigenlijk niet eens te controleren
of de ID wel numeriek is, hij komt dan immers niet in de database voor.
Controleer de gegevens op het juiste type voordat ze in de database worden
weggeschreven. Wanneer iemand in plaats van een getal een string opgeeft kan dit
een foutmelding opleveren bij het toevoegen in de database.
Controleer of het aantal karakters van de invoer, niet groter is dan het
maximaal aantal karakters van het veld in de database. In Access is het aantal
karakters van een tekstveld standaard op 50.
Controleer voordat je gegevens uit de database toont of er gegevens in de
recordset staan (if objRec.eof = True then ...).
Raden van
URLs Door het raden van URLs kan er gevoelige informatie achterhaald
worden. Wanneer de website goed is opgezet zal dit niet zo'n probleem zijn.
Helaas blijven er webmasters die dit niet doen en hosters die niet de juiste
faciliteiten aanbieden. Zo moet je de database nooit in een directory plaatsen
die vanaf het internet te bereiken is. Zo kunnen mensen gewoon de complete
database downloaden met alle wachtwoorden, e-mailadressen en persoonlijke
gegevens erin.
Als je bijvoorbeeld de volgende website hebt: www.website.com/mijnnaam. Nu
kan je proberen om het path van de database te raden, bv
www.website.com/mijnnaam/database/database.mdb,
www.website.com/mijnnaam/db/data.mdb of
www.website.com/mijnnaam/database/mijnnaam.mdb. Als je geluk hebt kan je op
deze manier de complete database downloaden. Het is daarom HEEL
belangrijk om de database buiten de webstructuur te bewaren.
Vaak hebben hoster een aparte directory met de juiste rechten om de database
in te plaatsen (hierover kan je contact opnemen met de hoster). Mocht het toch
zo zijn dat je hoster deze mogelijkheid niet heeft (niet echt een goed host!)
dan kan je het nog oplossen door het verzinnen van een moeilijke naam.
Deze is natuurlijk veel moeilijker (oke, bijna onmogelijk) om te raden, maar
als je je scripts niet beveiligd hebt tegen errors zou dit hele path nog zo in
een foutmelding te zien zijn.
Include bestanden
Bij een ASP site zal er veel gebruik worden gemaakt van includes.
Dit zijn bestanden die op meerdere pagina's geïnclude kunnen
worden zodat de code maar op één plaatst hoeft te
staan. Dit is ook makkelijk met wijzigen van bestanden.
Vaak wordt aan een include bestand de extentie .inc gegeven. Dit
is gevaarlijk, omdat je een tekstbestand (zoals bv functies.inc)
gewoon in de browser kan opvragen.
Als de gebruiker als URL intypt: "www.website.com/inc/functions.inc"
kan hij op deze manier de ASP code van het include bestand bekijken.
Zo kan de gebruiker achter gevaarlijke informatie, zoals het path
naar de database, komen.
Alle include bestanden moet de extentie ASP krijgen. Functions.inc
wordt dan Functions.inc.asp. Op deze manier kan niemand de code
van de include bestanden zien.
Maar wanneer ik een invoerveld die ik gebruik voor een zoekfunctie wil beveiligen op deze manier beveilig krijg ik dan bij invoer <i>'s morgens 'sjonge</i>
Na de replace deze waarde: ''smorgens ''sjonge
en dus bij de query gebruikersnaam='''smorgens ''sjonge'
Zoeken op de waarde <i>''smorgens ''sjonge</i> is heel wat anders als <i>'smorgens 'sjonge</i>