SQL-injectie

De term SQL-injectie (Engels: SQL injection) wordt gebruikt voor een type kwetsbaarheid van computerapplicaties, meestal webapplicaties. Applicaties die informatie in een database opslaan maken vaak gebruik van SQL om met de database te communiceren. SQL-injectie kan gebeuren als invoer van gebruikers (op onvoldoende gecontroleerde wijze) wordt verwerkt in een SQL-statement. Om de precieze werking van SQL-injectie te begrijpen is het belangrijk om te weten hoe SQL werkt.

Rol van de apostrof in SQL

In SQL heeft de apostrof een belangrijke functie, namelijk het afbakenen van niet-numerieke gegevens. Om bijvoorbeeld alle personen met de naam "Jansen" te selecteren uit een tabel wordt het volgende statement gebruikt

 SELECT * FROM persoon WHERE achternaam = 'Jansen'

In een applicatie waar gezocht kan worden naar personen, zal de gebruiker in het zoekveld uitsluitend "Jansen" invullen. In de applicatie wordt op basis van deze invoer bovenstaande code naar de database gestuurd.

Interessant wordt het als de gebruiker een apostrof in het zoekveld invult, bijvoorbeeld "'t Hart". In een correct statement moet dan namelijk de apostrof worden verdubbeld, of voorzien van een backslash (\).

 SELECT * FROM persoon WHERE achternaam = '''t Hart'
 SELECT * FROM persoon WHERE achternaam = '\'t Hart'

Als dat niet gebeurt, dan levert het een incorrect SQL-statement op, en volgt een foutmelding van de database. Maar het betekent ook dat de applicatie niet beschermd is tegen SQL-injectie.

SQL-injectie

SQL-injectie bestaat er uit dat een gebruiker in het invoerveld tekens invoert die ervoor zorgen dat een ongewenste SQL-query wordt uitgevoerd. Daarbij wordt vaak gebruikgemaakt van de apostrof. Dit kan alleen als bij het genereren van de SQL-code op basis van gebruikersinvoer de apostrof niet goed wordt afgevangen.

De gebruiker typt bijvoorbeeld "Jansen' OR 'a' = 'a" in het zoekveld. Het resulterende statement is dan

 SELECT * FROM persoon WHERE achternaam = 'Jansen' OR 'a' = 'a'

Omdat "'a' = 'a'" altijd waar is, voldoet nu elk record aan de gestelde voorwaarde.

Met bovenstaand voorbeeld kan de hacker extra informatie ophalen uit de database. Dezelfde methode levert ook de mogelijkheden om nieuwe informatie aan de database toe te voegen, bestaande informatie aan te passen en informatie te verwijderen. Daarvoor is informatie nodig over de structuur (namen van tabellen en kolommen) van de database. De naamgeving van tabellen en kolommen is meestal logisch om werken met de database voor een reguliere gebruiker eenvoudig te houden en daardoor voorspelbaar. Daarnaast kan de hacker ook diverse zaken uitproberen om bijvoorbeeld een gebruikersaccount met beheerders-rechten aan te maken. Lukt dit, dan kan de hacker de totale controle over de webserver overnemen, met alle gevolgen van dien.

Preventie

Door middel van het geven van de minimaal noodzakelijke rechten van de gebruiker en de SQL-server kan het ongewenst aanpassen van gegevens en het uitvoeren van ongewenste commando's op het systeem moeilijker gemaakt worden.

Afwijzen van verkeerde invoer

Men kan alleen bepaalde tekens en strings toestaan in de invoer en alles wat een betekenis heeft in een SQL-commando afwijzen (bijvoorbeeld de tekens en strings: insert drop ' -- ; enzovoorts, maar ook char zodat niet via een omweg een ' in de invoer kan voorkomen). Zuiver numerieke gebruikersnamen en wachtwoorden moeten afgewezen worden, omdat die automatisch omgezet kunnen worden in strings met ongewenste betekenissen.

Backslash

De injectie met SQL-code kan eenvoudig tegengegaan worden door het juist verwerken van informatie die door een gebruiker wordt aangeleverd. In de programmeertaal PHP kan dat bijvoorbeeld via mysqli_real_escape_string(). Deze functie vangt (my)SQL-specifieke karakters af door er een backslash (\) voor te plaatsen. Hierdoor weet het systeem dat enkel het letterteken bedoeld wordt, en niet meer de scheidende functie van het afbakenen van gegevens. Een stukje voorbeeld-programmeertaal in PHP kan er als volgt uitzien:

 <?php
 $result = mysqli_query($verbinding, "SELECT * FROM persoon WHERE achternaam = '" . mysqli_real_escape_string($verbinding, $_POST['achternaam']) . "'");
 ?>

Statement

Een andere methode om injectie tegen te gaan is door middel van een voorgedefinieerd statement. Hierbij wordt in het aanroepende programma het statement opgebouwd met een variabele. De inhoud van de variabele wordt dan gekoppeld aan de gebruikersinvoer.

Bijvoorbeeld (in de taal Java):

In plaats van

  1. Connection con = (maak verbinding met de database)
  2. Statement stmt = con.createStatement();
  3. ResultSet rset = stmt.executeQuery("SELECT * FROM persoon WHERE achternaam = '" + invoer + "';");

is het beter om het volgende te gebruiken

  1. Connection con = (maak verbinding met de database)
  2. PreparedStatement pstmt = con.prepareStatement("SELECT * FROM persoon WHERE achternaam = ?");
  3. pstmt.setString(1, invoer);
  4. ResultSet rset = pstmt.executeQuery();

Databasepermissies

Schade kan beperkt worden door alleen de strikt nodige permissies te verlenen. Bijvoorbeeld kan men het op SQL-server onmogelijk maken bepaalde tabellen te lezen:

deny select on sys.sysobjects to webdatabaselogon;
deny select on sys.objects to webdatabaselogon;
deny select on sys.tables to webdatabaselogon;
deny select on sys.views to webdatabaselogon;
This article is issued from Wikipedia. The text is licensed under Creative Commons - Attribution - Sharealike. Additional terms may apply for the media files.