Wat is SQL-injectie (SQLi), hoe werken verschillende soorten kwetsbaarheden voor SQL-injectie en kun je ze vinden en misbruiken, hoe je SQL-injectie kunt voorkomen.
SQL-injectie (SQLi) is een beveiligingslek op het web waardoor een aanvaller de query's van een toepassing in de database kan verstoren. Het stelt een aanvaller over het algemeen in staat om gegevens te bekijken die ze normaal gesproken niet kunnen ophalen. Dit kunnen gegevens van andere gebruikers zijn, of andere gegevens waartoe de toepassing zelf toegang heeft. In veel gevallen kan een aanvaller deze gegevens wijzigen of verwijderen, waardoor de inhoud of het gedrag van de toepassing blijvend verandert.
In sommige situaties kan een aanvaller een SQL-injectieaanval escaleren om de onderliggende server of andere back-endinfrastructuur te compromitteren, of een denial-of-service-aanval uitvoeren.
Een geslaagde SQL-injectieaanval kan leiden tot ongeoorloofde toegang tot gevoelige gegevens, zoals wachtwoorden, creditcardgegevens of persoonlijke gebruikersgegevens. Veel spraakmakende datalekken in de afgelopen jaren waren het resultaat van SQL-injectieaanvallen, wat leidde tot reputatieschade en boetes. In sommige gevallen kan een aanvaller een blijvende backdoor in de systemen van een organisatie verkrijgen, wat leidt tot een langdurig compromis dat gedurende een langere periode onopgemerkt kan blijven.
SQL-injectie kan handmatig worden gedetecteerd door een systematische reeks tests te gebruiken voor elk ingangspunt in de applicatie. Dit omvat meestal:
' en op zoek naar fouten of andere anomalieën.
OR 1=1 en OR 1=2, en op zoek naar verschillen in de reacties van de applicatie.
Denk aan een applicatie waarmee gebruikers kunnen inloggen met een gebruikersnaam en wachtwoord. Als een gebruiker de gebruikersnaam opgeeft Tom en het wachtwoord 1234qwer, de toepassing controleert de inloggegevens door de volgende SQL-query uit te voeren:
SELECT * FROM users WHERE username = 'Tom' AND password = '1234qwer'
Als de query de gegevens van een gebruiker retourneert, is de login geslaagd. Anders wordt het afgewezen.
Hier kan een aanvaller inloggen als elke gebruiker zonder wachtwoord door simpelweg de SQL-commentaarreeks te gebruiken -- om de wachtwoordcontrole uit de Tom clausule van de vraag. Bijvoorbeeld het invullen van de gebruikersnaam administrator'-- en een leeg wachtwoord resulteert in de volgende query:
SELECT * FROM users WHERE username = 'administrator'--' AND password = ''
Deze query retourneert de gebruiker wiens gebruikersnaam is administrator en logt de aanvaller met succes in als die gebruiker.
Testomgeving: SQL Injection.
De meeste gevallen van SQL-injectie kunnen worden voorkomen door geparametriseerde query's (ook wel voorbereide instructies genoemd) te gebruiken in plaats van tekenreeksaaneenschakeling binnen de query.
De volgende code is kwetsbaar voor SQL-injectie omdat de gebruikersinvoer rechtstreeks in de query wordt samengevoegd:
String query = "SELECT * FROM products WHERE category = '"+ input + "'";
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(query);
Deze code kan eenvoudig worden herschreven op een manier die voorkomt dat de invoer van de gebruiker de querystructuur verstoort:
PreparedStatement statement = connection.prepareStatement("SELECT * FROM products WHERE category = ?");
statement.setString(1, input);
ResultSet resultSet = statement.executeQuery();
Query's met parameters kunnen worden gebruikt voor elke situatie waarin niet-vertrouwde invoer wordt weergegeven als gegevens in de query, inclusief de WHERE clausule en waarden in een INSERT or UPDATE stelling. Ze kunnen niet worden gebruikt om niet-vertrouwde invoer in andere delen van de query af te handelen, zoals tabel- of kolomnamen, of de ORDER BY clausule. Toepassingsfunctionaliteit die niet-vertrouwde gegevens in die delen van de query plaatst, moet een andere aanpak volgen, zoals toegestane invoerwaarden op een witte lijst plaatsen of andere logica gebruiken om het vereiste gedrag te leveren.
Om een geparametriseerde query effectief te laten zijn in het voorkomen van SQL-injectie, moet de tekenreeks die in de query wordt gebruikt altijd een hardgecodeerde constante zijn en mag nooit variabele gegevens van welke oorsprong dan ook bevatten. Laat u niet verleiden om van geval tot geval te beslissen of een gegevensitem vertrouwd is, en blijf tekenreekssamenvoeging gebruiken binnen de query voor gevallen die als veilig worden beschouwd. Het is maar al te gemakkelijk om fouten te maken over de mogelijke oorsprong van gegevens, of om veranderingen in andere code aannames te schenden over welke gegevens besmet zijn.