PHP houdt vast aan de meeste rechten die het server systeem gebruikt
voor permissies op bestanden en directories. Dit maakt het mogelijk dat
je kunt controleren welke bestanden op het systeem mogen worden gelezen.
Voorzichtigheid moet genomen worden met elke bestand dat world readable
is om ervoor te zorgen dat deze geen informatie bevat die niet
bedoeld zijn voor eventuele andere gebruikers die toegang hebben tot
dit bestand.
Omdat PHP is ontworpen met gebruikers level toegang tot het
bestandssysteem, is het helemaal mogelijk om een PHP script te
schrijven dat systeembestanden zoals /etc/password bewerkt,
ethernet connecties door de war gooit of heel veel uitprint op
een printer. Dit geeft een aantal implicaties; je moet namelijk
goed controleren dat de bestanden die je leest en schrijft
ook diegene zijn die je denkt dat je leest en schrijft.
Neem het volgende in gedachten: als een gebruikt te kennen geeft een
bestand in hun homedirectory te verwijderen. Neem aan dat dit een
situatie betreft waar een PHP web interface wordt gebruikt voor bestands
beheer. Hierom heeft de Apache gebruiker rechten om bestanden in de
home directory van de gebruiker aan te passen en te verwijderen.
Voorbeeld 4-1. Slechte variabele controle leidt tot...
<?php
// Verwijder een bestand uit de gebruikers home directory
$gebruiker = $aangegeven_naam;
$homedir = "/home/$gebruiker";
$te_verwijderen_bestand = "$bestandje";
unlink ($homedir/$bestandje);
echo "$te_verwijderen_bestand is verwijderd!";
?>
|
|
Omdat de gebruikersnaam is te posten vanuit een form, kunnen gebruikers
bestanden benaderen van iemand anders, en deze verwijderen.
In dit voorbeeld heb je enige vorm van authenticatie nodig. Neem in
gedachten wat er kan gebeuren als de geposte variabelen waren
"../etc/" en "passwd". De code zou dan effectief zijn:
Voorbeeld 4-2. ... Een aanval op het bestandssysteem
<?php
// verwijderen een bestanden ergens op de harde schijf waar
// de PHP gebruiker toegang tot heeft. Als PHP root rechten heeft:
$gebruiker = "../etc/";
$homedir = "/home/../etc/";
$te_verwijderen_bestand = "passwd";
unlink ("/home/../etc/passwd");
echo "/home/../etc/passwd" is verwijderd!";
?>
|
|
Er zijn twee belangrijke manieren om dit soort dingen tegen te gaan:
Hier is een verbeterd script:
Voorbeeld 4-3. Veiliger bestandsnaam controle
<?php
// verwijderd een bestand van de schijf waartoe de PHP gebruiker
// toegang heeft.
$gebruiker = $HTTP_REMOTE_USER; // use an authentication mechanisim
$homedir = "/home/$gebruiker";
$te_verwijderen_bestand = basename("$bestand"); // stript directories
unlink ($homedir/$te_verwijderen_bestand);
$fp = fopen("/home/logging/filedelete.log","+a"); //log de verwijdering
$logstring = "$HTTP_REMOTE_USER $homedir $te_verwijderen_bestand";
fputs ($fp, $logstring);
fclose($fp);
echo "$te_verwijderen_bestand is verwijderd!";
?>
|
|
Een alternatief is om een eigen controle uit te voeren:
Voorbeeld 4-4. Veiliger bestandsnaam controle
<?php
$username = $HTTP_REMOTE_USER;
$homedir = "/home/$username";
if (!ereg('^[^./][^/]*$', $userfile))
die('niet geldige bestansnaam'); //die, ga niet verder
//etc...
?>
|
|
Afhankelijke van je operating system zijn er een groot aantal files
die extra andacht vereisen, inbegrepen zijn device entries (/dev/
or COM1), configuratie files (/etc/ bestanden en de .ini files),
bekende bestandslocaties (/home/, Mijn Documenten), etc. Om deze
reden is het vaak makkelijker om een policy aan te houden die alles
verbied, behalve de dingen die je expliciet toelaat.