Forum und email

safe-mode - מצב בטוח

הsafe-mode של PHP הוא נסיון לפתור את בעיית האבטחה של שרתים-משותפים. זה לא נכון מבחינה ארכיטקטורית לפתור את הבעייה הזאת ברמת ה-PHP, אבל מכיוון שהאלטרנטיבות בשרתים ומערכות-הפעלה הן לא מאוד ריאליסטיות, אנשים רבים, במיוחד ספקי-שירות אינטרנט, משתמשים בsafe-mode כרגע.

הוראות קונפיגורציה לשליטה בsafe-mode הן:
הוראה ערך ברירת-מחדל
safe_mode Off
safe_mode_gid 0
safe_mode_include_dir ""
safe_mode_exec_dir 1
open_basedir ""
safe_mode_allowed_env_vars PHP_
safe_mode_protected_env_vars LD_LIBRARY_PATH
disable_functions ""

כאשר safe_mode מופעל, PHP בודקת אם בעל הקובץ של הסקריפט הנוכחי הוא גם הבעלים של הקובץ שפונקציית קבצים תשתמש בו. לדוגמא:

-rw-rw-r--    1 rasmus   rasmus       33 Jul  1 19:20 script.php 
-rw-r--r--    1 root     root       1116 May 26 18:01 /etc/passwd 
הפעלת הקובץ הבא
<?php
 readfile
('/etc/passwd'); 
?>
גורמת לשגיאה הזאת כשsafe-mode פועל:
Warning: SAFE MODE Restriction in effect. The script whose uid is 500 is not 
allowed to access /etc/passwd owned by uid 0 in /docroot/script.php on line 2

למרות זאת, ישנן סביבות שבהן בדיקת UID מחמירה לא מתאימה ובדיקת GID מקלה מספיקה. האפשרות הזאת נתמכת באמצעות מתג ה-safe_mode_gid. קביעתו ל- On מבצעת את בדיקת ה-GID המקלה, קביעתו ל-Off (ברירת-המחדל) מבצעת בדיקת UID.

אם במקום safe_mode, נקבעת ספריית open_basedir אז כל פעולות הקבצים יהיו מוגבלות לקבצים תחת הספרייה הקבועה, לדוגמא (Apache httpd.conf):

<Directory /docroot>
  php_admin_value open_basedir /docroot 
</Directory>
אם אותו קובץ מורץ עם קביעת ה- open_basedir אז זאת התוצאה:
Warning: open_basedir restriction in effect. File is in wrong directory in 
/docroot/script.php on line 2 

אפשר גם לבטל פונקציות פונקציות יחידות, אך לא ניתן להשתמש בהוראה disable_functions מחוץ לקובץ php.ini, מה שאומר שאי-אפשר לבטל פונקציות רק לvirtual-hosts או ספריות בודדות בקובץ httpd.conf. אם מוסיפים את זה לקובץ php.ini:

disable_functions readfile,system  
מקבלים את הפלט:
Warning: readfile() has been disabled for security reasons in 
/docroot/script.php on line 2 

פונקציות המוגבלות/מבוטלות בsafe-mode

זה כנראה רישום לא שלם ואולי לא נכון של הפונקציות המוגבלות ב- safe mode.

פונקציות המוגבלות בsafe-mode
פונקציה הגבלות
dbmopen() בודק האם הקבצים\ספריות שאתה מתכוון לבצע עליהם פעולות, הם בעלי הרשאת משתמש (UID) הזהה לזו של התוכנית המורצת.
dbase_open() בודק האם הקבצים\ספריות שאתה מתכוון לבצע עליהם פעולות, הם בעלי הרשאת משתמש (UID) הזהה לזו של התוכנית המורצת.
filepro() בודק האם הקבצים\ספריות שאתה מתכוון לבצע עליהם פעולות, הם בעלי הרשאת משתמש (UID) הזהה לזו של התוכנית המורצת.
filepro_rowcount() בודק האם הקבצים\ספריות שאתה מתכוון לבצע עליהם פעולות, הם בעלי הרשאת משתמש (UID) הזהה לזו של התוכנית המורצת.
filepro_retrieve() בודק האם הקבצים\ספריות שאתה מתכוון לבצע עליהם פעולות, הם בעלי הרשאת משתמש (UID) הזהה לזו של התוכנית המורצת.
ifx_*() הגבלות sql_safe_mode, (!= safe-mode)
ingres_*() הגבלות sql_safe_mode, (!= safe-mode)
mysql_*() הגבלות sql_safe_mode, (!= safe-mode)
pg_loimport() בודק האם הקבצים\ספריות שאתה מתכוון לבצע עליהם פעולות, הם בעלי הרשאת משתמש (UID) הזהה לזו של התוכנית המורצת.
posix_mkfifo() בודק האם הספרייה שבה אתה רוצה לבצע פעולה, היא בעלת הרשאת משתמש (UID) הזהה לזו של התוכנית המורצת.
putenv() ממלא את הוראות ה-ini safe_mode_protected_env_vars ו- safe_mode_allowed_env_vars. תיעוד מלא ב- putenv()
move_uploaded_file() בודק האם הקבצים\ספריות שאתה מתכוון לבצע עליהם פעולות, הם בעלי הרשאת משתמש (UID) הזהה לזו של התוכנית המורצת.
chdir() בודק האם הספרייה שבה אתה רוצה לבצע פעולה, היא בעלת הרשאת משתמש (UID) הזהה לזו של התוכנית המורצת.
dl() פונקציה זו אינה פעילה במצב safe-mode
backtick operator פונקציה זו אינה פעילה במצב safe-mode
shell_exec() (פונקציה זהה לbacktick operator) פונקציה זו אינה פעילה במצב safe-mode
exec() ניתן להפעיל קבצים רק בתוך safe_mode_exec_dir. מסיבות מעשיות לא ניתן כרגע להכיל .. בנתיב (Path) ההפעלה.
system() ניתן להריץ קבצים רק בתוך safe_mode_exec_dir. מסיבות מעשיות לא ניתן כרגע להכיל .. בנתיב (Path) ההפעלה.
passthru() ניתן להריץ קבצים רק בתוך safe_mode_exec_dir. מסיבות מעשיות לא ניתן כרגע להכיל .. בנתיב (Path) ההפעלה.
popen() ניתן להריץ קבצים רק בתוך safe_mode_exec_dir. מסיבות מעשיות לא ניתן כרגע להכיל .. בנתיב (Path) ההפעלה.
mkdir() בודק האם הספרייה שבה אתה רוצה לבצע פעולה, היא בעלת הרשאת משתמש (UID) הזהה לזו של התוכנית המורצת.
rmdir() בודק האם הקבצים\ספריות שאתה מתכוון לבצע עליהם פעולות, הם בעלי הרשאת משתמש (UID) הזהה לזו של התוכנית המורצת.
rename() בודק האם הקבצים\ספריות שאתה מתכוון לבצע עליהם פעולות, הם בעלי הרשאת משתמש (UID) הזהה לזו של התוכנית המורצת. בודק האם הספרייה שבה אתה רוצה לבצע פעולה, היא בעלת הרשאת משתמש (UID) הזהה לזו של התוכנית המורצת.
unlink() בודק האם הקבצים\ספריות שאתה מתכוון לבצע עליהם פעולות, הם בעלי הרשאת משתמש (UID) הזהה לזו של התוכנית המורצת. בודק האם הספרייה שבה אתה רוצה לבצע פעולה, היא בעלת הרשאת משתמש (UID) הזהה לזו של התוכנית המורצת.
copy() בודק האם הקבצים\ספריות שאתה מתכוון לבצע עליהם פעולות, הם בעלי הרשאת משתמש (UID) הזהה לזו של התוכנית המורצת. בודק האם הספרייה שבה אתה רוצה לבצע פעולה, היא בעלת הרשאת משתמש (UID) הזהה לזו של התוכנית המורצת. (ב- source ו- target )
chgrp() בודק האם הקבצים\ספריות שאתה מתכוון לבצע עליהם פעולות, הם בעלי הרשאת משתמש (UID) הזהה לזו של התוכנית המורצת.
chown() בודק האם הקבצים\ספריות שאתה מתכוון לבצע עליהם פעולות, הם בעלי הרשאת משתמש (UID) הזהה לזו של התוכנית המורצת.
chmod() בודק האם הקבצים\ספריות שאתה מתכוון לבצע עליהם פעולות, הם בעלי הרשאת משתמש (UID) הזהה לזו של התוכנית המורצת. בנוסף, לא ניתן לקבוע את SUID, SGID וביטים דביקים (Sticky bits)
touch() בודק האם הקבצים\ספריות שאתה מתכוון לבצע עליהם פעולות, הם בעלי הרשאת משתמש (UID) הזהה לזו של התוכנית המורצת. בודק האם הספרייה שבה אתה רוצה לבצע פעולה, היא בעלת הרשאת משתמש (UID) הזהה לזו של התוכנית המורצת.
symlink() בודק האם הקבצים\ספריות שאתה מתכוון לבצע עליהם פעולות, הם בעלי הרשאת משתמש (UID) הזהה לזו של התוכנית המורצת. בודק האם הספרייה שבה אתה רוצה לבצע פעולה, היא בעלת הרשאת משתמש (UID) הזהה לזו של התוכנית המורצת. (רק המטרה נבדקת)
link() בודק האם הקבצים\ספריות שאתה מתכוון לבצע עליהם פעולות, הם בעלי הרשאת משתמש (UID) הזהה לזו של התוכנית המורצת. בודק האם הספרייה שבה אתה רוצה לבצע פעולה, היא בעלת הרשאת משתמש (UID) הזהה לזו של התוכנית המורצת. (רק המטרה נבדקת)
getallheaders() בsafe-mode, כותרות-עליונות (Headers) שמתחילות ב-'authorization' (לא מושפע יחסה, case insensitive) לא יוחזרו. אזהרה: זה לא תקין בגירסת שרת-aol של getallheaders()!
header() בsafe-mode, המספר הסידורי של הסקריפט מתווסף לחלק ה- realm בכותרת העליונה WWW-Authenticate אם הכותרת הזאת נקבעת (משמש לאימות HTTP).
highlight_file(), show_source() בודק האם הקבצים\ספריות שאתה מתכוון לבצע עליהם פעולות, הם בעלי הרשאת משתמש (UID) הזהה לזו של התוכנית המורצת. בודק האם הספרייה שבה אתה רוצה לבצע פעולה, היא בעלת הרשאת משתמש (UID) הזהה לזו של התוכנית המורצת. (מושפע רק מאז PHP 4.2.1)
parse_ini_file() בודק האם הקבצים\ספריות שאתה מתכוון לבצע עליהם פעולות, הם בעלי הרשאת משתמש (UID) הזהה לזו של התוכנית המורצת. בודק האם הספרייה שבה אתה רוצה לבצע פעולה, היא בעלת הרשאת משתמש (UID) הזהה לזו של התוכנית המורצת. (מושפע רק מאז PHP 4.2.1)
כל פונקציה שמשתמשת ב- php4/main/fopen_wrappers.c ??