Naar inhoud springen

SQL-injectie

Uit Wikipedia, de vrije encyclopedie
Dit is een oude versie van deze pagina, bewerkt door Wiki13 (overleg | bijdragen) op 5 mei 2012 om 17:04. (Wijzigingen door 86.81.190.79 (Overleg) hersteld tot de laatste versie door LaaknorBot)
Deze versie kan sterk verschillen van de huidige versie van deze pagina.

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 er voor 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 admin rechten aan te maken. Lukt dit, dan kan de hacker de totale controle over de computer overnemen, met alle gevolgen van dien.

Vermijden

Door middel van het geven van de minimaal noodzakelijke rechten zal het ongewenst aanpassen van de gegevens vermeden worden.

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 mysql_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 = mysql_query("SELECT * FROM persoon WHERE achternaam = '".mysql_real_escape_string($_POST['achternaam'])."'");
 ?>

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();
  • (en) Advanced SQL injection