Tutorials

Mysql Injection

Een uitleg over het fenomeen SQL injection en wat je ertegen kunt doen

Pagina 1

Inleiding

SQL-Injection

SQL-Injection: iets waar veel mensen nog niet van gehoord hebben, en waar ikzelf ook nog geruime tijd nooit gehoord had. Toch is dit een van de grootste beveiligingslekken in de webwereld.
Waarom? Veel sites gebruiken een dynamische website die samenwerkt met een database, veelal (My)Sql. Dit is heel handig als sites vaak ge-update moeten worden zonder de broncode aan te hoeven passen, maar ook gevaarlijk als deze interface niet goed beveiligd wordt.

Hoe worden deze kwaardaardige injections het meest uitgevoerd?
De meeste kwaadwillenden kunnen SQL-injections uitvoeren door bepaalde GET- of POST-variabelen te veranderen zodat een database-query helemaal aangepast wordt. Dit is natuurlijk niet de bedoeling en dit kan erge gevolgen hebben voor de website.
Pagina 2

Hoe gaat SQL-Injection te werk?

Een voorbeeld van SQL-injection:
Het veranderen van deze sql-queries kan eigenlijk heel gemakkelijk gebeuren, aangezien iedereen openlijk de bron van elke website kan bekijken en dus op die manier al een brood in de schoot word geworpen over de mogenlijke database-layout. Hoe? Zoals dit:


Deze pagina demonstreert een simpel html-formulier
--------------------------------------------------
Naam: [naam_user input="text"]
Password: [password_user input="password"]
[Register input="submit"]


Waarbij de kwade gebruiker (ik noem hem even Pietje, makkelijker dan dat ik hele tijd 'kwaadaarige gebruiker' moet typen Knipoog/Wink ) even in de bron gaat kijken en waarempel dit vindt:


Code:
<form action="register.php" method="POST">
Naam: <input type="text" name="naam_user" /><br />
Password: <input type="password" name="password_user" /><br />
<input type="submit" value="Register" />
</form>


Als Pietje zijnde is het niet zo moeilijk om te achterhalen dat deze gegevens dus naar de pagina "register.php" gestuurd worden met de POST-variabelen 'naam_user' en 'password_user'. Waarschijnlijk een grote kans dat de kolomnamen van de database dan ook dezelfde naam hebben, of een naam die hierop lijkt. Nu gokt Pietje erop dat de PHP code met de SQL-query als volgt uit ziet:

Code:
<?php
$SQL = "INSERT INTO table (naam_user, password_user) VALUES ('" . $_POST['naam_user'] . "', '" . $_POST['password_user'] . "')";
mysql_query($SQL);
?>


En nu komt dat de echte injection: wat als Pietje nu het volgende in het naam-veld gaat invullen bij het formulier (en de rest van de formuliervelden, in dit geval alleen het password-veld, normaal invult):

Ingevulde waarde van Naam-veld door Pietje:
Pietje Puk', 'passwoord1'), ('Sinterklaas


Dan komt de query er als volgt uit te zien (!!!)

Code:
<?php
$SQL = "INSERT INTO table (naam_user, password_user) VALUES ('Pietje Puk', 'passwoord1'), ('Sinterklaas', 'passwoord2')";
mysql_query($SQL);
?>


En ja, nu is er dus een groot probleem, aangezien Pietje nu dus vanalles kan invullen in de database, nu is dat bij een registratie van een gebruiker niet zo'n ramp, hij had net zogoed twee keer een formulier in kunnen vullen, maar je kunt je waarschijnlijk genoeg scenario's bedenken waar dit wel degelijk uitmaakt.
Pagina 3

SQL-Injection in de Where-clause

SQL-injection in de WHERE-clause:
We hebben het nu gehad over de injection in de Insert-clause, dat vaak op die manier misbruikt wordt. Nu ook even een injection op een totaal andere manier.

Stel je voor, er wordt bij een website een passwoord opgevraagd van een gebruiker door middel van een link, dit komt voor als vragen om problemen, maar schrik niet, dit komt toch nog vaak voor (op een dergelijke manier).

De php-code voor de opvraag-pagina:
Code:

<?php
$SQL = mysql_query("SELECT password_user FROM table WHERE naam_user = '{$_GET['naam_user']}'");
$data = mysql_fetch_array($SQL);
echo $data['password_user'] . " hoort bij user: " . $_GET['naam_user'];
?>


Je ziet het waarschijnlijk al gebeuren, wat als we die $_GET-waarde gaan veranderen?
We maken eens een link waarbij we meerdere gebruikers op kunnen vragen.

Voorbeeld van normale link:

Code:
<a href="lookup.php?naam_user=pietje">
Bekijk password
</a>


Stel pietje wil erachter komen wat het password van gebruiker "Sinterklaas" is, dan kan hij dat als volgt teweten komen, middels de URL te veranderen in iets als:

Nieuwe, kwaadaardige URL:
lookup.php?naam_user=pietje%27+OR+naam_user+%3D+%27sinterklaas


Wat uitkomt is een query als deze:

Kwaadaardige query:
SELECT password_user FROM table
WHERE naam_user = 'pietje' OR naam_user = 'sinterklaas'


Nu kan pietje dus het password van gebruiker "Sinterklaas" achterhalen, iets waar die gebruiker niet blij mee zal zijn. Dit is ook een van de redenen waarom passwoorden het liefst gecodeerd opgeslagen moeten worden, maar ook dit als voorbeeld.
Pagina 4

Hoe kun je dit tegengaan?

Hoe kan je dit nu tegengaan?:
Er zijn verschillende mogenlijkheden om het SQL-injection zo veel mogenlijk tegen te gaan.
Ik zal er even 2 toelichten, één ervan zijn de functies mysql_escape_string, mysql_real_escape_string en strip_slashes, en de ander is het filteren van gegevens.

Het nakijken van gegevens door middel van de bovenstaande functies werkt goed onder de volgende functie:

Code:
<?php
function quote_smart($value) {
if (get_magic_quotes_gpc()) {
$value = stripslashes($value);
}
if(version_compare(phpversion(),"4.3.0") == "-1") {
return mysql_escape_string($value);
} else {
return mysql_real_escape_string($value);
}
}
?>


Hierdoor wordt je verstuurde waarde goed gecontroleerd op tekens die er niet thuishoren.
Een andere manier van tegengaan is het filteren van gegevens, alhoewel dat niet werkt bij bijvoorbeeld het nakijken van gebruikersnamen, maar wel bij keuzenlijsten.
Stel je een formulier voor met een keuzelijst van prijzen. Je kunt bijvoorbeeld kiezen tussen een tegoedbon van 10€, 25€, 50€ en 100€. Nu kun je dit controleren in php:

Code:

<?php
$valid_prices = array(10, 25, 50, 100);
if(!in_array($_GET['price'], $valid_prices)){
die("Hack attempted!");
}else{
// ga door met de code
} ?>

Reacties

0
Nog geen reacties.