|
Dit deel gaat over de beveiliging van PHP websites. De meeste beginners slaan dit gedeelte gewoon over, terwijl het noodzakelijk is om een veilige website te bouwen. Want wie wil er nu z'n persoonlijke gegevens aan een website geven die evenveel veiligheidslekken heeft als een bank waar de kluis op een kier blijft?
Voordat ik begin met de meest voorkomende veiligheidslekken te bespreken, wil ik benadrukken dat ik enkel deze gevaren aantoon om veiligere websites te verkrijgen, NIET om onveilige websites plat te leggen. Als je dit toch doet, is het op eigen risico, en hoop ik dat je binnenkort blauwe mannetjes op bezoek krijgt.
XSS
XSS staat voor Cross Site Scripting, dat een techniek is om een pagina te genereren doordat de server de inhoud niet controleert. Er zijn 3 types XSS:
- Client-side XSS
- Server-side XSS voor 1 persoon
- Server-side XSS voor meerdere personen
Client-side XSS
Dit is niet van toepassing op PHP, omdat PHP een server-side taal is.
Server-side XSS voor 1 persoon
Via XSS kan men ongecontroleerde input weergeven, zoals javascript code. Een klein voorbeeld:
URL: fotogallerij.php?foto=<script>alert("xss-tutorial");</script>
fotogallerij.php:
Foto: <?= $_GET['foto']; ?>
<!-- weergeven van de foto, enz... !-->
Bij dit voorbeeld wordt er verkeerde informatie meegegeven via de URL, waardoor er een stuk javascript-code uitgevoerd wordt (nl. het weergeven van een popup). Een slechter geval kan zijn dat men cookie-inhoud weergeeft (waardoor de hacker weet welke gegevens op je pc opgeslagen worden).
Server-side XSS voor meerdere personen
Hierbij wordt de input niet gewoon weergeven op de pagina, maar wordt dit opgeslagen in een database, waardoor meerder personen de inhoud kunnen zien. Stel dat we zelf een forum uitschrijven, maar dat we de inhoud van de topics en replies niet controleren. Dan kan je ook javascript (e.d.) in de database steken, waardoor meerdere gebruikers popups op hun scherm krijgen, of doorgestuurd worden naar allerlei websites vol virussen en spyware.
Hoe lossen we dit op?
Een goede manier om XSS tegen te gaan is html-tekens om te zetten naar html entities
Voorbeeld
$_POST['input'] = "<script>alert("xss-tutorial");</script>"
<?php
echo $_POST['input']; // input: <script>alert("xss-tutorial");</script>
echo htmlentities($_POST['input']); // input: <script>alert("xss-tutorial");</script> -> geeft de html-code weer, maar voert die niet uit
?>
MySQL-injection
Een goed voorbeeld van server-side XSS voor meerdere personen is het niet controleren van input voor databases (MySQL-injection). Laten we eens een voorbeeld bekijken van een kwetsbare website:
<?php
mysql_connect("localhost","gebruikersnaam","paswoord"); // mysql_connect("plaatsvandatabase","loginaanm","paswoord");
mysql_select_db("testdatabase"); // mysql_select_db("naamvandatabase");
mysql_query("SELECT paswoord FROM gebruikers WHERE loginnaam = '".$_POST['loginnaam']."'");
?>
Goede input:
$_POST['loginnaam'] = Firmin
Query: "SELECT paswoord FROM gebruikers WHERE loginnaam = 'Firmin'"
Slechte input: (MySQL-injection)
$_POST['loginnaam'] = Firmin' OR loginnaam = 'Kamiel
Query: "SELECT paswoord FROM gebruikers WHERE loginnaam = 'Firmin' OR loginnaam = 'Kamiel'"
Zoals je kan zien, als je je inhoud niet controleert, kunnen gebruikers verkeerde informatie ontvangen (zoals bv paswoorden van andere gebruikers).
Hoe lossen we dit op?
We gebruiken een php-functie, mysql_real_escape_string(). Die functie 'escaped' (een backslash voor plaatsen) de input-string, waardoor de gevaren gemeden zijn.
<?php
mysql_connect("localhost","gebruikersnaam","paswoord"); // mysql_connect("plaatsvandatabase","loginaanm","paswoord");
mysql_select_db("testdatabase"); // mysql_select_db("naamvandatabase");
mysql_query("SELECT paswoord FROM gebruikers WHERE loginnaam = '".mysql_real_escape_string($_POST['loginnaam'])."'");
?>
Goede input:
$_POST['loginnaam'] = Firmin
Query: "SELECT paswoord FROM gebruikers WHERE loginnaam = 'Firmin'"
Slechte input: (MySQL-injection)
$_POST['loginnaam'] = Firmin' OR loginnaam = 'Kamiel -> escaped: Firmin\' OR loginnaam = \'Kamiel
Query: "SELECT paswoord FROM gebruikers WHERE loginnaam = 'Firmin\' OR loginnaam = \'Kamiel'"
De functie escaped de enkele aanhalingstekens, waardoor de server de input ziet als een gewone string, waardoor er een error zal verschijnen, ipv verkeerde inhoud.
Session Hijacking
Iets wat minder voor de hand ligt is session hijacking. Sessies worden opgeslagen op de server, en om te weten welke sessie bij welke client hoort, slaat de server een session cookie op. Bij iedere keer dat men sessie-informatie nodig heeft, controleert men de session cookie. Een hacker kan dataverkeer tussen client en server 'opsnuifen' waardoor hij de informatie van een session cookie kan verkrijgen, en zo de sessie kan 'hijacken'. De hacker maakt vervolgens de cookie na, en die kan dan gewoon 'ingelogd' zijn als een andere gebruiker.
Hoe lossen we dit op?
- Iedere keer dat een gebruiker inlogt, gebruik de functie session_regenerate_id() om een nieuwe sessie-ID aan te maken
- Vertrouw je gebruiker niet, als je bv een paswoord moet resetten, vraag opnieuw het oude paswoord
- Sla geen paswoorden en andere gevoelige data op in een sessie (of gebruik encryptie-functies zoals sha1() (beter) en md5())
- Sla bij een login een IP op, en controleer die tijdens de sessie (als je men een ander IP gebruikt tijdens dezelfde sessie is het een session hijacker)
Enkele extra tips om hackers tegen te gaan
- Gebruik de ingebouwde PHP Ctype functies om input te controleren
- Plaats een index.php in elke map (zonder een index-pagina kan men bij een Apache-server de inhoud van de map bekijken)
- Plaats bovenaan je script ini_set(error_reporting,0); om zo syntax-errors niet weer te geven (die geven meestal kostbare informatie weg aan hackers)
- Zoek op Google naar PHP beveiliging, je komt zeker veel meer soorten veiligheidslekken tegen (aanrader)
Wat hebben we vandaag geleerd?
- Vertrouw je input NOOIT
- Wees slim en controleer je input zo specifiek mogelijk (string, integer, decimal, ...), gebruik eventueel reguliere expressies
- Probeer zelf je eigen website te hacken (of te laten hacken) voordat je hem online plaatst, om zo eventuele veiligheidslekken snel te dichten
Auteur : Skwizz
|