首頁 >後端開發 >php教程 >php檔案系統安全防範措施

php檔案系統安全防範措施

伊谢尔伦
伊谢尔伦原創
2016-11-22 10:48:251324瀏覽

PHP 遵循大多數伺服器系統中關於檔案和目錄權限的安全機制。這就讓管理員可以控制哪些檔案在檔案系統內是可讀的。必須特別注意的是全域的可讀文件,並確保每個有權限的使用者對這些文件的讀取動作都是安全的。

PHP 被設計為以使用者層級來存取檔案系統,所以完全有可能透過編寫一段 PHP 程式碼來讀取系統檔案如 /etc/passwd,更改網路連線以及發送大量列印任務等等。因此必須確保 PHP 程式碼讀取和寫入的是合適的檔案。

請看下面的程式碼,使用者想要刪除自己主目錄中的一個檔案。假設此情形是透過 web 介面來管理檔案系統,因此 Apache 使用者有權刪除使用者目錄下的檔案。

Example #1 不對變數進行安全檢查會導致…

<?php
    // 从用户目录中删除指定的文件
    $username = $_POST[&#39;user_submitted_name&#39;];
    $userfile = $_POST[&#39;user_submitted_filename&#39;];
    $homedir = "/home/$username";
    unlink ("$homedir/$userfile");
    echo "The file has been deleted!";
?>

既然username 和filename 變數可以透過使用者表單來提交,那就可以提交別人的使用者名稱和檔案名,甚至可以刪除本來就不應該讓他們刪除的文件。這種情況下,就要考慮其它方式的認證。想想如果提交的變數是“../etc/”和“passwd”會發生什麼。上面的程式碼就等同於:

Example #2 …檔案系統攻擊

<?php
    // 删除硬盘中任何 PHP 有访问权限的文件。如果 PHP 有 root 权限:
    $username = $_POST[&#39;user_submitted_name&#39;]; // "../etc"
    $userfile = $_POST[&#39;user_submitted_filename&#39;]; // "passwd"
    $homedir = "/home/$username"; // "/home/../etc"
    unlink("$homedir/$userfile"); // "/home/../etc/passwd"
    echo "The file has been deleted!";
?>

有兩個重要措施來防止此類問題。

只給 PHP 的 web 使用者很有限的權限。

檢查所有提交上來的變數。

下面是改進的腳本:

Example #3 更安全的檔案名稱檢查

<?php
    // 删除硬盘中 PHP 有权访问的文件
    $username = $_SERVER[&#39;REMOTE_USER&#39;]; // 使用认证机制
    $userfile = basename($_POST[&#39;user_submitted_filename&#39;]);
    $homedir = "/home/$username";
    $filepath = "$homedir/$userfile";
    if (file_exists($filepath) && unlink($filepath)) {
        $logstring = "Deleted $filepath\n";
    } else {
        $logstring = "Failed to delete $filepath\n";
    }
    $fp = fopen("/home/logging/filedelete.log", "a");
    fwrite ($fp, $logstring);
    fclose($fp);
    echo htmlentities($logstring, ENT_QUOTES);
?>

然而,這樣做仍然是有缺陷的。如果認證系統允許使用者建立自己的登入使用者名,而使用者選擇用「../etc/」作為使用者名,系統又淪陷了。所以,需要加強檢查:

Example #4 更安全的文件名檢查

<?php
    $username = $_SERVER[&#39;REMOTE_USER&#39;]; // 使用认证机制
    $userfile = $_POST[&#39;user_submitted_filename&#39;];
    $homedir = "/home/$username";
    $filepath = "$homedir/$userfile";
    if (!ctype_alnum($username) || !preg_match(&#39;/^(?:[a-z0-9_-]|\.(?!\.))+$/iD&#39;, $userfile)) {
        die("Bad username/filename");
    }
    //后略……
?>

根據操作系統的不同,存在著各種各樣需要注意的文件,包括聯繫到系統的設備(/dev/ 或COM1) 、設定檔(/ect/ 檔案和.ini檔案)、常用的儲存區域(/home/ 或My Documents)等等。由於此原因,建立一個策略禁止所有權限而只開放明確允許的通常會更容易。


陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn