PHP is een krachtige taal en de interpreter, zowel als module
in een webserver, of uitgevoerd in een afzonderlijke
CGI binary, kan bestanden lezen, commando's
uitvoeren en netwerk connecties openen op de server. Deze
eigenschappen maken alles wat draait op een webserver onveilig als
default. PHP is ontworpen als een veiliger taal om CGI programma's
te maken dan Perl of C, en met de juiste selectie van compile-time
en runtime configuratie opties, en een goede coding stijl, kan het
je over de exacte combinatie van vrijheid en veiligheid beschikken
die jij nodig hebt.
Omdat er veel verschillende manieren zijn om PHP te gebruiken,
zijn er ook veel opties die het gedrag aanpassen. Een grote
keus aan opties garanderen dat PHP gebruikt kan worden voor
veel doeleinden, maar het betekend ook dat er combinaties zijn
van opties en server configuraties die resulteren in een slecht
beveiligde setup.
De configureerbaarheid van PHP is evenredig met de felixibiliteit
van code schrijven. PHP kan gebruikt worden om complete server
applicaties te schrijven met de kracht van een shell user, maar ook
voor simpele server-side includes met weinig risico en een goed
te controleren omgeving. Hoe zo'n omgeving te creeren en hoe veilig
het is, hangt grotendeels af van de PHP ontwikkelaar.
Dit hoofdstuk start met het uitleggen van de verschillende combinaties
van opties en de situaties waarin deze veilig kunnen worden gebruikt.
Hierna zal het verschillende mates van beveiliging van de geprogrammeerde
scripts doornemen, en het zal eindigen met een algemeen beveiligins
advies.
Ge�nstalleerd als CGI binary
Mogelijke aanvallen
PHP gebruiken als CGI binary is een optie voor
personen die om een of andere reden PHP niet willen integreren
als een module in server software (zoals Apache), of die PHP met
verschillende CGI wrappers willen gebruiken om zo een veilige
omgeving voor scripts te cre�n. Deze opzet vereist vaak het
installeren van de PHP binary in de web server's cgi-bin directory.
CERT advisory beveelt of
om interpreters in de cgi-bin te installeren. Zelfs als een
binary gebruikt wordt als een standalone interpreter is PHP
ontworpen om een aantal aanvallen op deze setup te verijdelen:
Het lezen van systeem bestanden: http://mijn.server/cgi-bin/php?/etc/passwd
De string in een URL na het vraagteken (?) wordt
doorgegeven als argumenten aan de interpreter door de CGI
interface. Gewoonlijk openen interpreters het eerste argument
als het script dat ze proberen uit te voeren.
Als PHP als CGI binary word gebruikt, dan vertikt hij het om
command line argumenten te accepteren.
Het lezen van elk web document op de server: http://mijn.server/cgi-bin/php/geheim/doc.html
De bestandslocatie in de URL achter de PHP binary naam,
/geheim/doc.html wordt
normaal gebruikt om de naam van het uit te voeren bestand
aan te geven dat moet worden uitgevoerd door het
CGI programma.
Normaal gezien wordt een configuratie optie (Apache: Action)
gebruikt om zulke requests als
http://my.host/secret/script.php3/secret
door te sturen naar de PHP interpreter. Op deze manier worden
eerst de toegangsrechten naar de directory
/secret gecontroleerd. Pas
daarna wordt het nieuwe request http://my.host/cgi-bin/php/secret/script.php3
uitgevoerd. Helaas worden requests welke in deze vorm gegeven
worden niet gecontroleerd op toegangspermissies. Er word alleen
gekeken of er toegang is tot
/cgi-bin/php en niet
of er toegang is tot
/secret/script.php3.
Op deze manier kan elke gebruiker met toegang tot
/cgi-bin/php elk beschermd
document in de web tree benaderen.
In PHP, de compile-time configuratie optie --enable-force-cgi-redirect
en de runtime configuration opties doc_root en user_dir kunnen worden gebruikt
om dit type aanval, als de web document tree enige directories
heeft met restricties. Zie hier onder voor een volledige uitleg
van alle verschillende combinaties.
Case 1: alleen normale bestanden
Als jouw server geen enkele beveiligde webpagina heeft, bijvoorbeeld
met een wachtwoord, of gebaseerd op IP, dan is het niet nodig om
deze configuratie opties te gebruiken. Indien jouw webserver het niet
toestaat om redirects te doen, of de server kan op geen enkele manier
communiceren met de PHP binary dat de informatie aanvraag is een veilig
geredirectioneerde aanvraag dan kun je de optie --enable-force-cgi-redirect
veilig toevoegen aan de configure regel. Je zult wel zelf moeten
controleren of jouw PHP scripts niet afhankelijk van elkaar zijn
bij het direct aanroepen http://mijn.server/cgi-bin/php/dir/script.php3
en via redirectie http://mijn.server/dir/script.php3.
Redirectie kan in Apache worden geconfigureerd met behulp van
AddHandler en Action regels (zie hieronder).
Case 2: gebruik maken van --enable-force-cgi-redirect
Deze compile-time optie voorkomt het direct aanroepen van PHP
met een URL als volgende http://my.host/cgi-bin/php/geheimedir/script.php3.
In plaatse hiervan zal PHP het scripts alleen parsen in deze mode als
het via een web server's redirect rule wordt aangeboden.
Normaal gesproken is redirectie in Apache te configureren met de
volgende directives:
Action php3-script /cgi-bin/php
AddHandler php3-script .php3 |
Deze opties is alleen getest met de Apache web server, en gaat ervan
uit dat Apache de niet standaard CGI environment variable
REDIRECT_STATUS gebruikt bij redirectioneerde
aanvragen. Als jouw web server geen manier heeft om door te
geven of een aanvraag is geredirectioneerd of niet, dan kun je
deze optie niet gebruiken en zal je een andere manier moeten vinden
om de CGI versie te runnen.
Case 3: het gebruik van doc_root of user_dir
Soms wordt in twijfel getrokken of het gebruiken van scrips of
programma's in de web server document directories wel veilig is.
Als namelijk, vanwege een configuratie foutje, de scripts niet
worden uitgevoerd, maar worden getoond als normale HTML documenten,
dan kan er copyrighted materiaal, of beveiliginsinformatie als
wachtwoorden beschikbaar komen voor onbevoegden. Hierom zullen
veel beheerders een apparte directory opzetten die altijd wordt
uitgevoerd door de PHP CGI, hierdoor komt de source van de PHP
scripts nooit beschikbaar komen voor onbevoegden.
Als er geen manier is om te controleren of een aanvraag is niet
doorverwezen, zoals bescrijven is in de vorige Case, dan is het ook
nodig om een doc_root op te zetten die verschillend is van de web
documenten root-directory.
Je kunt de document van een PHP script instellen met de configuratie
directive doc_root in de
configuratie file, of
met het setten van de environment variabele
PHP_DOCUMENT_ROOT. Als deze is ge-zet dan zal de CGI
versie van PHP altijd de bestandsnaam gebruiken met de
doc_root en path informatie van de aanvraag.
Op deze manier is het zeker dat geen script wordt uitgevoerd buiten
de directory (met uitzondering voor user_dir
die hieronder wordt beschreven).
Een andere bruikbare optie is de user_dir. Als user_dir niet getset is,
dan is het enige dat de geopende file be�nvloed de
doc_root. Het openen van een URL als http://mijn.server/~gebruiker/doc.php3 resulteerd
niet in het openen van een bestand in de home directory van de gebruiker,
maar van het openen van
~gebruiker/doc.php3 in de doc_root
(een directory die met een tilde begint
[~]).
Als user_dir de waarde public_php is, een aanvraag als http://mijn.server/~gebruiker/doc.php3
zal de file doc.php3 in de directory genaamd
public_php openen in de home
directory van de gebruiker. Als de home directory van de gebruiker
/home/gebruiker is, dan zal het uitgevoerde
bestand /home/gebruiker/public_php/doc.php3 zijn.
user_dir expansie gebeurd onafkanelijk van de
waarde van doc_root. Dit maakt het mogelijk om
de document root en user directory toegang afzonderlijk te configureren.
Case 4: PHP parser buiten de of web tree
Een erg veilige optie is het plaatsen van de PHP binary buiten de
directory met web bestanden. De PHP binary wordt voor deze methode
vaak in /usr/local/bin geplaatst.
Het enige nadeel is hieraan dat je nu een regel moet toevoegen aan
een script. Deze regel moet de eerste zijn in een script en ziet
er als volgt uit:
Het is ook noodzakelijk dat het script uitvoerbaar wordt gemaakt.
Dit impliceerd dat je het script moet zien als elk ander script
dat gebruikt wordt in CGI, zoals in Perl, shellscript of elke andere
taal die het
#! shell-escape mechanisme gebruikt
voor het starten van zichzelf.
Om er voor te zorgen dat PHP PATH_INFO en
PATH_TRANSLATED information correct gebruikt in deze
setup, moet de PHP parser worden gecompileerd met de --enable-discard-path
configure optie.