Beveiliging van het bestandssysteem

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.