ࡱ > q O bjbjt+t+ > A A J ] $ 2 2 2 2 P $ 2 * x ~ Z ( $ " ^ 4 ^ T ~ J 8 2 2 V R 6 J 4 l)2 2 Entwurf
Dieses Script ist noch nicht vollstndig
Stand SPEICHERDAT \@ "tt.MMMM.jjjj HH:mm" \* FORMATVERBINDEN 11.Mai.2005 18:48
Rahmenbedingungen
Getestet wurde auf:
Debian Linux
Apache 1.3.27
PHP 4.3.1
PHP-Untersttzung testen
Bevor wir mit den bungen zum Safe Mode starten, mssen wir testen, ob unser Provider uns wirklich die verkaufte /vermietete "PHP-Untersttzung" gewhrt.
Unter PHP-Untersttzung versteht man, dass das dafr zustndige Programm alle dem Stand der Technik entsprechenden Operationen im dem User zugewiesenen "Webspace" vornehmen darf. Dazu gehren insbesondere das Anlegen, Verndern und Lschen von Dateien und Verzeichnissen bis zur gemieteten Gesamtnutzungsgre...
(Anmerkung vom Autor: Einschrnkungen durch den Safe Mode sind dabei hinzunehmen)
Ein ganz einfaches Script, das wir in die Document Root unseres Webspaces laden mssen, gibt uns schon eine ganz wensentliche Aussage darber.
nicht beschreibbar
"; }
else
{
echo "Zielverzeichnis ist beschreibbar
";
}
?>
Wenn uns dieses Script bei seiner Ausfhrung meldet, dass das Zielverzeichnis nicht beschreibbar ist, mssen wir die weiteren bungen bereits hier abbrechen und unseren Provider ermahnen, die PHP-Untersttzung nach dem Stand der Technik herzustellen.
Der Webserver sollte (mindestens) einer Gruppe angehren. Diese Gruppe sollte auf die Document Root des Users alle Rechte (rwx) haben. Alle weiteren Zugriffsrechte fr diese Gruppe und den User des Webservers werden durch open_basedir geregelt. Mehr darber im Kapitel "Tipps fr den Provider".
Einschalten des safe_mode
Der Safe Mode kann auf zwei Wegen aktiviert werden:
php.ini
Einstellungen in der php.ini wirken sich i.d.R. auf alle vom Webserver bedienten Domains (Main Host und Virtual Hosts) aus.
hierzu muss in die php.ini die Zeile
safe_mode = On
eingefgt werden.
httpd.conf
In der httpd.conf kann der Safe Mode fr jeden Virtual Host und sogar bis auf Verzeichnisebene getrennt eingestellt werden.
ServerAdmin thomas@testserver.bitworks
DocumentRoot /www/docs/docserver
ServerName docuserver.lan.fli4l
ErrorLog /logs/docserver/error_log
CustomLog /logs/docserver/access_log common
php_admin_value safe_mode 1
php_admin_value open_basedir /www/docs/docserver/
Hinweis: Zum Einschalten des Safe Mode war nur die Angabe
php_admin_value safe_mode 1
bei diesem Server erfolgreich
Funktionsweise des safe_mode
Die Safe Mode Rechteprfung arbeitet in der Applikationsschicht. Der PHP-Parser prft whrend der Ausfhrung des Scriptes bei diversen Funktionen, ob der Eigentmer des ausgefhrten Scriptes mit dem Eigentmer des Verzeichnisses, in dem das mit der im Script benutzten Funktion bearbeitete Objekt (Verzeichnis, Datei) liegt, bereinstimmt. Stimmt der Eigentmer des Scriptes mit dem Owner des Objektes berein, darf auch zugegriffen werden.
Safe Mode ist ein Versuch, Sicherheitsprobleme bei gemeinsam genutzten Servern zu lsen. Da es auf Ebene des Webservers bzw. des Betriebssystems keine praktischen Alternativen gibt, wird Safe Mode nunmehr von vielen Leuten, vor allem von Providern, eingesetzt.
Beintrchtigte Funktionen
FunktionOKBeonderheiten, die bei der Beschreibung der Einschrnkung im Manual zu bachten sinddbmopen()dbase_open()fopen()(keine Abweichungpopen()rename()unlink()touch()copy()mkdir()(keine Abweichungrmdir()(keine Abweichungopendir()(keine Abweichungfile()(keine Abweichungfile_get_contents()(keine Abweichungfile_put_contents()(ab PHP 5)readfile()(keine Abweichungfilepro()filepro_rowcount()filepro_retrieve()ifx_*ingres_*mysql_*pg_lo_import()posix_mkfifo()putenv()move_uploaded_file()chdir()dl()Backtick-Operator
$out = `command`;shell_exec()exec()(keine Abweichungsystem()(keine Abweichungpassthru()chown()chgrp()chmod()symlink()link()apache_request_headers()header()PHP_AUTH variableshighlight_file()show_source()parse_ini_file()set_time_limit()max_execution_time()mail()include()include_path wird berprft,
safe_mode_include_path ist freirequire()
"OK" bedeutet, dass die Funktionen und ihre Einschrnkungen intensiv getestet wurden und in diesem Script beschrieben werden. Abweichungen zum Manual werden beschrieben bzw klargestellt.
Settings berprfen
Im Zusammenhang mit dem Safe_Mode knnen diverse Einstellungen vorgenommen werden:
safe_mode On|Off
Safe Mode aktivieren oder deaktivieren.
safe_mode_gid On|Off
Standardmig vergleicht PHP im Safe Mode den Owner (UID) des Scriptes mit dem Owner des zu verwendenen Objektes (Verzeichnis, Datei). Wenn man diesen Vergleich etwas lockern will, kann man durch Aktivierung von safe_mode_gid die Gruppenzugehrigkeit (GID) vergleichen lassen.
safe_mode_include_dir '/www/php/includes/,/www/user/mod_,scripts'
Vergleiche auf Owner (UID) oder Gruppe (GID) werden bei Dateien, die aus den durch diese Angabe zugelassenen Verzeichnissen und ihren Unterverzeichnissen hinzugeladen (include()) werden, nicht vorgenommen. Die Verzeichnisse mssen entweder mit qualifizierter Pfadangabe benannt werden oder im include_path enthalten sein. Seit PHP 4.2.0, kann diese Direktive mehrere Musterangaben getrennt durch einen Doppelpunkt (Linux) oder ein Semikolon (Windows) enthalten. Die Syntax ist die gleiche wie beim include_path.
Die Angabe ist als Muster von links zu verstehen, nicht als Verzeichnisangabe. Das bedeutet, dass "safe_mode_include_dir = /dir/incl" auch Zugriff auf "/dir/include" und "/dir/incls" erlaubt, wenn diese Pfade existieren. Wenn der Zugriff ausschlielich auf ein spezielles Verzeichnis erlaubt sein soll, muss die Angabe mit einem Schrgstrich (/) enden. Beispiel: "safe_mode_include_dir = /dir/incl/"
safe_mode_exec_dir '/www/php/exec/'
Wenn PHP im Safe Mode betrieben wird, werden Systemfunktionen wie z.B. system() nicht ausgefhrt, wenn sie nicht (als Kopie) in diesem Verzeichnis vorhanden sind. Beim Aufruf nicht vorhandener Systemprogramme wird keine Fehlermeldung ausgelst. Das safe_mode_exec_dir muss in der php.ini oder in der httpd.conf angebeben werden.
safe_mode_allowed_env_vars 'PHP_,data_,_free'
Mit Hilfe der hier als kommaseparierte Liste eingetrageneen Prefixe fr Variablen kann der Schreibzugriff auf Umgebungsvariablen im Safe Mode eingeschrnkt werden. Wenn nichts angegeben wird, findet keinerlei Einschrnkung statt. Die Voreinstellung in der php.ini ist
safe_mode_allowed_env_vars = PHP_. Eine Einstellung kann sowohl in der php.ini als auch in der httpd.conf vorgenommen werden.
safe_mode_protected_env_vars HYPERLINK "language.types.string.php"language.types.string.php 'LD_LIBRARY_PATH'
Diese Angabe enthlt eine durch Kommata getrennte Liste von Environment Variablen, die der End-User nicht mehr verndern darf durch putenv(). Diese Variablen sind selbst dann geschtzt, auch wenn sie in safe_mode_allowed_env_vars aufgefhrt sind.
open_basedir '/www/docs/script_root/'
durch open_basedir wird ein Muster fr Pfade im Dateibaum festgelegt, von denen aus abwrts PHP Zugriff auf das Dateisystem hat und Scripte ausfhrt. Diese Direktive wird nicht von den Einstellungen fr safe_mode oder safe_mode_gid beeinflusst. Eingeschrnkt sind Operationen mit fopen(), gzopen(), file() file_get_contents(), readfile() u.. Wenn sich die Datei auerhalb des angegebenen Pfades liegt, wird PHP sie nicht ffnen. Symbolische Links werden aufgelst und dann geprft, sodass aes auch auf diesem Wege nicht mglich ist, die Restriktionen zu umgehen. Es kann eine Liste von Pfaden angegeben werden, die mit Doppelpunkt (Linux) oder Semikolon (Windows) getrennt werden. Das Auflisten von Verzeichnissen wird durch diese Funktion nicht beschrnkt. Es ist zum Beispiel mglich, die public_html Verzeichnisse der User zu listen, aber nicht mglich, eine Datei darin zu ffen oder auszufhren, wenn das jeweilige Verzeichnis nicht durch Angabe eines Pfadmusters freigegeben ist.
As an Apache module, open_basedir paths from parent directories are now automatically inherited.
The restriction specified with open_basedir is actually a prefix, not a directory name. This means that "open_basedir = /dir/incl" also allows access to "/dir/include" and "/dir/incls" if they exist. When you want to restrict access to only the specified directory, end with a slash. For example: "open_basedir = /dir/incl/"
Note: Support for multiple directories was added in 3.0.7.
The default is to allow all files to be opened.
disable_functions HYPERLINK "language.types.string.php"string
This directive allows you to disable certain functions for HYPERLINK "security.index.php"security reasons. It takes on a comma-delimited list of function names. disable_functions is not affected by HYPERLINK "features.safe-mode.php" \l "ini.safe-mode"Safe Mode.
This directive must be set in php.ini For example, you cannot set this in httpd.conf.
disable_classes HYPERLINK "language.types.string.php"string
This directive allows you to disable certain classes for HYPERLINK "security.index.php"security reasons. It takes on a comma-delimited list of class names. disable_classes is not affected by HYPERLINK "features.safe-mode.php" \l "ini.safe-mode"Safe Mode.
This directive must be set in php.ini For example, you cannot set this in httpd.conf.
Availability note: This directive became available in PHP 4.3.2
Safe Mode ist ".((ini_get('safe_mode'))?'ON':'OFF')."
\n";
echo "
BaseDir ist ".
((ini_get('open_basedir'))?ini_get('open_basedir'):'n/a')."
\n";
?>
Funktionsweise von open_basedir
Die Wirkung von open_basedir wird nicht vom Safe Mode beeinflusst, ergnzt diesen also auf ihre Art.
Ausgangssituation
Verzeichnisstruktur
Eigentumsverhltnisse zu Beginn
drwxr-xr-x 2 thomas root 4096 May 21 15:11 .
drwxr-xr-x 4 root root 4096 May 21 04:25 ..
-rw-r--r-- 1 root root 96 May 21 04:22 index.html
-rw-r--r-- 1 thomas websites 712 May 21 11:58 safe_mode_test.php
Script
1 \$_SERVER['PHP_SELF']: ".$_SERVER['PHP_SELF']."
\n";
.6
.7 echo "
Safe Mode ist ".((ini_get('safe_mode'))?'ON':'OFF')."
\n";
.8 echo "
BaseDir ist".
.9 ((ini_get('open_basedir'))?ini_get('open_basedir'):'n/a')."
\n";
10
11 if (!file_exists('daten')) mkdir('daten',0777);
12
13 if (file_exists('daten') and !file_exists('daten/thomas'))
14 {
15 mkdir('daten/thomas',0777);
16 }
17
18 if (file_exists('daten/thomas/'))
19 {
20 echo "
\nDatei wird angelegt: ";
21 $fh = fopen('daten/thomas/file01.txt','w+');
22 $write_ok = fwrite($fh,"dieser Text soll auch rein\n");
23 fclose($fh);
24 echo (($write_ok !== false)?'Erfolg':'fehlgeschlagen')."
\n";
25 }
26
27 ?>
Der Aufruf des Scriptes verursacht folgende Meldung:
$_SERVER['PHP_SELF']: /safe_mode_test.phpSafe Mode ist ONBaseDir ist /www/docs/docserver/Warning: mkdir(daten) [HYPERLINK "http://www.php.net/function.mkdir"function.mkdir]: Permission denied in /www/docs/docserver/safe_mode_test.php on line 11
Woran liegt es nun, dass unser Script keinen Erfolg gehabt hat? Der Safe_Mode ist hier nicht schuld. Dieser Fehler wird aus der Betriebssystem-Schicht zurckgemeldet. Linux bemngelt hier, dass der ausfhrende User (das ist der wwwrun) keine ausreichenden Rechte fr mkdir() besitzt. Um in der Dokcument Root (.), also unserem Domainverzeichnis, eine Datei oder ein Verzeichnis anlegen zu knnen, bentigt der ausfhrende User Schreibrechte in diesem Verzeichnis. Da der Safe_Mode eingeschalet ist, muss auerdem der Owner des Scriptes, dass der wwwrun fr uns ausfhren soll, mit dem Owner des Verzeichnisses, in dem die Aktion stattfinden soll, bereinstimmen. Deshalb stellen wir die Rechte und Besitzverhltnisse entsprechend ein.
Als Owner des Verzeichnisses drfen wir die Gruppe des Verzeichnisses und auch deren Rechte ndern. Einzige Voraussetzung ist, dass wir als Owner selber Mitglied dieser Gruppe sind. Wenn wir einen ssh-Zugang haben, knnen wir uns mit dem befehl groups bersicht verschaffen:
thomas@testserver:/www/docs/docserver$ groups thomas
thomas : szene websites praktikum
thomas@testserver:/www/docs/docserver$ groups wwwrun
wwwrun : websites szene praktikum wwwrun
Sowohl thomas als auch wwwrun sind Mitglied in der Gruppe websites.
Stellen wir also mit dem Befehl chgrp websites ./ fr das aktuelle Verzeichnis die Gruppe websites ein. Das ist uns als Eigentmer des Verzeichnisses gestsattet.
drwxrwxr-x 2 thomas websites 4096 May 21 15:11 .
drwxr-xr-x 4 root root 4096 May 21 04:25 ..
-rw-r--r-- 1 root root 96 May 21 04:22 index.html
-rw-r--r-- 1 thomas websites 712 May 21 11:58 safe_mode_test.php
Nach nochmaligem Aufruf des Scriptes ergibt sich nun folgende Verzeichnisstruktur:
Das mkdir() in der Zeile 11 des Scriptes war also schon erfolgreich. Trotzdem gibt es noch Fehlermeldungen, die diesmal auf den safe_mode zurckzufhren sind.
$_SERVER['PHP_SELF']: /safe_mode_test.phpSafe Mode ist ONBaseDir ist /www/docs/docserver/Warning: file_exists() [HYPERLINK "http://www.php.net/function.file-exists"function.file-exists]: SAFE MODE Restriction in effect. The script whose uid is 1000 is not allowed to access /www/docs/docserver/daten owned by uid 1002 in /www/docs/docserver/safe_mode_test.php on line 13Warning: mkdir() [HYPERLINK "http://www.php.net/function.mkdir"function.mkdir]: SAFE MODE Restriction in effect. The script whose uid is 1000 is not allowed to access /www/docs/docserver/daten owned by uid 1002 in /www/docs/docserver/safe_mode_test.php on line 15Warning: file_exists() [HYPERLINK "http://www.php.net/function.file-exists"function.file-exists]: SAFE MODE Restriction in effect. The script whose uid is 1000 is not allowed to access /www/docs/docserver/daten owned by uid 1002 in /www/docs/docserver/safe_mode_test.php on line 18
Der wwwrun versucht in Zeile 13 des Scriptes, dass dem User thomas gehrt, mit der Funktion file_exists() das Verzeichnis ./daten, das dem User wwwrun gehrt, zu lesen. Das ist aber nach den regeln des safe_mode verboten. Ebenfalls verboten ist es, mit diesem Script ein Unterverzeichnis in ./daten anzulegen. Der wwwrun hat hier zwar Schreibrechte auf Betriebssystemebene, aber die Owner von Script und Verzeichnis stimmen nicht berein.
Wie knnten wir Abhilfe schaffen? Wir mssen dafr sorgen, dass der Owner des Scriptes und der Owner des Verzeichnisses identisch sind. Dazu knnten wir nun entweder den Owner des Verzeichnisses ndern, oder den des Scriptes. Versuchen wir unser Glck:
thomas@testserver:/www/docs/docserver$ chown thomas daten
chown: changing ownership of `daten': Operation not permitted
Es ist egal, ob wir den Befehl chown ber die ssh-Konsole oder ber einen ftp-Client versuchen. Wir drfen ihn als "normaler User" nicht ausfhren, da es ein Root-Kommando ist. Ownerwechsel darf also nur vom User root oder seinen Sicherheitsquvalenten ausgefhrt werden. Diese begehrten Rechte wird uns der Provider aber nicht freiwillig einrumen.
Wir knnen uns denken, das die gleichen Einschrnkungen fr die nderung des Owners unseres Scriptes gelten. Nun ist guter Rat teuer. berlegen wir nochmals, was wir erreichen wollen, und was bisher passiert ist.
Zielsetzung: Wir mchten erreichen, dass unsere Scripte und unsere Verzeichnisse und Dateien denselben Owner haben, damit uns der safe_mode nicht den Zugriff verwehrt.
Beobachtung: Wenn wir mittels eines Scriptes, das uns gehrt, ein Unterverzeichnis oder eine Datei anlegen, funktioniert das nur, wenn wir auch Eigentmer des Mutterverzeichnisses sind und der wwwrun als Beauftragter User Schreibrechte in diesem Verzeichnis besitzt. Diesen Zustand knnen wir herstellen (wenn unser Provider nicht total verbldet ist). Wenn wir dann den wwwrun mit unserem Script ein Unterverzeichnis anlegen lassen, gehrt dieses dem wwwrun.
Dateien und Verzeichnisse gehren immer demjenigen User, der sie anlegt. Eine nderung dieser Besitzverhltnisse darf nur der User root vornehmen.
Wenn wir also unser Script durch den User wwwrun einfach kopieren lassen, dann gehrt die Kopie dem User wwwrun. Den Auftrag dazu erteilen wir dem php-parser mit dem folgenden kleinen Script:
Wir schauen uns das Verzeichnis vor Ausfhrung des Scriptes an:
drwxrwxr-x 3 thomas websites 4096 May 21 17:00 .
drwxr-xr-x 4 root root 4096 May 21 04:25 ..
drwxr-xr-x 2 wwwrun wwwrun 4096 May 21 15:29 daten
-rw-r--r-- 1 root root 96 May 21 04:22 index.html
-rw-r--r-- 1 thomas websites 264 May 21 14:10 safe_mode_copy.php
-rw-r--r-- 1 thomas websites 712 May 21 11:58 safe_mode_test.php
und nach der Anwendung des Scriptes:
drwxrwxr-x 3 thomas websites 4096 May 21 17:03 .
drwxr-xr-x 4 root root 4096 May 21 04:25 ..
drwxr-xr-x 2 wwwrun wwwrun 4096 May 21 15:29 daten
-rw-r--r-- 1 root root 96 May 21 04:22 index.html
-rw-r--r-- 1 thomas websites 263 May 21 14:12 safe_mode_copy.php
-rw-r--r-- 1 thomas websites 712 May 21 11:58 safe_mode_test.php
-rw-r--r-- 1 wwwrun wwwrun 712 May 21 17:03 safe_mode_test02.php
Eigentmer des neu entstandenen Scriptes ist nun wwwrun, dem auch das Verzeichnis ./daten/ gehrt. Wenn wir nun das kopierte Script ausfhren lassen, erhalten wir folgende Meldungen:
$_SERVER['PHP_SELF']: /safe_mode_test02.phpSafe Mode ist ONBaseDir ist /www/docs/docserver/Datei wird angelegt: Erfolg
Es sind also keine Verletzungen des safe_mode mehr aufgetreten.
Die Verzeichnisstruktur hat sich gendert:
Schauen wir uns die Rechte in der Kosolenausgabe an:
testserver:/www/docs/docserver# ls -lR
.:
total 24
drwxr-xr-x 3 wwwrun wwwrun 4096 May 21 17:08 daten
-rw-r--r-- 1 root root 96 May 21 04:22 index.html
-rw-r--r-- 1 thomas websites 263 May 21 14:12 safe_mode_copy.php
-rw-r--r-- 1 thomas websites 712 May 21 11:58 safe_mode_test.php
-rw-r--r-- 1 wwwrun wwwrun 712 May 21 17:03 safe_mode_test02.php
./daten:
total 4
drwxr-xr-x 2 wwwrun wwwrun 4096 May 21 17:08 thomas
./daten/thomas:
total 4
-rw-r--r-- 1 wwwrun wwwrun 27 May 21 17:08 file01.txt
Wie wir sehen, war das kopierte Script mit dem Eigentmer wwwrun nun in der Lage, alle Aufgaben zu unserer Zufriedenheit zu erledigen.
Seite SEITE \* FORMATVERBINDEN 9 von ANZSEITEN \* FORMATVERBINDEN 1
http://bitworks.de eMail@bitworks.de Tel 05582/999 881 Fax 05582/999 882
safe_mode & Co.
2 9 : r s ? L A
M
t / 0 N O v w x h q 4 @
" 2 & G a b h
$ % / ; [ g ! 0J j U0J 565CJ
j 5CJ 5eh 0J >*mH j UCJ( Q 2 3 # $
&