Gegevens verkregen uit $_POST, $_GET, $_REQUEST en $_SERVER kunnen onverwachte inhoud bevatten. Daarom horen we deze te controleren voordat we deze data wegschrijven naar een database, gewoon weg opslaan of gaan gebruiken in onze output. Om hier inzicht in te krijgen geef ik enkele voorbeelden van simpele code die we makkelijk kunnen misbruiken en de oplossingen.
12.1 Server-side XSS
Een methode om code uit te voeren op een website en zo zelfs login cookies en dergelijke te kunnen stelen. Om dit te voorkomen laat ik jullie natuurlijk eerst zien hoe het werkt. Door een perfect werkend script te tonen met enkele ernstige beveiligingslekken!
Mogelijke slachtoffersscript 1
PHP-code:
<form action="" method="get">
<label for="name">Naam</label><input type="text" name="name" id="name" value="" /><input type="submit" value="Verzenden" />
</form>
<?php
if(isset($_GET['name']))
echo '<p>Je naam is '.$_GET['name'].'</p>';
?>
Code:
<script type="text/javascript"> alert("XSS Hack!"); </script>
Nu de oplossing is zeer simpel maar zovelen vergeten het toe te passen. Er zijn meerdere oplossingen mogelijk vandaar 2 correcte oplossingen waarvan ik zelf de 2de vaker uitvoer indien mogelijk.
Oplossing 1
PHP-code:
<form action="" method="get">
<label for="name">Naam</label><input type="text" name="name" id="name" value="" /><input type="submit" value="Verzenden" />
</form>
<?php
if(isset($_GET['name']))
echo '<p>Je naam is '.htmlspecialchars($_GET['name']).'</p>';
?>
PHP-code:
<form action="" method="get">
<label for="name">Naam</label><input type="text" name="name" id="name" value="" /><input type="submit" value="Verzenden" />
</form>
<?php
if(isset($_GET['name']) && preg_match('/^([a-zA-Z0-9]{2,40})$/', $_GET['name']))
echo '<p>Je naam is '.htmlspecialchars($_GET['name']).'</p>';
?>
Onthoud dus: Bij html output waarbij we de gegevens verkregen via de gebruiker maken we gebruik van htmlspecialchars. Ookal komt de data uit een database deze kwam onrechtstreeks ook van de gebruiker en door een lek elders in je script zou deze misbruikt kunnen worden. Vandaar dat we deze even door htmlspecialchars halen, een kleine moeite toch?
12.2 SQL Injections
Door het niet controleren van input data kunnen we ook gegevens beinvloeden die uitgelezen worden uit de database om zo te selecteren wat we willen zien.
Mogelijke slachtoffersscript 1
PHP-code:
<?php
$result = mysql_query('SELECT * WHERE password="'.$_POST['pwd'].'" AND username="'.$_POST['username'].'" LIMIT 0,1');
?>
Code:
" OR 1=1
Oplossing
PHP-code:
<?php
if(isset($_POST['pwd']) && isset($_POST['username']) && preg_match('/^[a-z0-9]{6,14}$/i', $_POST['pwd']) && preg_match('/^[a-z0-9]{6,14}$/i', $_POST['username']))
{
$result = mysql_query('SELECT * FROM users WHERE password="'.mysql_real_escape_string($_POST['pwd']).'" AND username="'.mysql_real_escape_string($_POST['username']).'" LIMIT 0,1');
/**
* Rest van de code
*/
}
?>
De headers die met het HTTP protocol worden meegestuurd kunnen beinvloed worden door een gebruiker. Hierdoor kunnen we deze data nooit vertrouwen en moeten we deze ook steeds controleren. De manieren van controleren zijn steeds het zelfde.
12.4 Conclusie
Alle gegevens die de bezoeker kan beinvloeden dienen gecontroleerd te worden en mag je nooit vertrouwen. Gebruik de gegevens dus pas wanneer je zeker bent dat ze niets schadelijks kunnen aanrichten.
Geschreven door: Kurt Aerts.
Systeembericht