PHP安全之文件系統(tǒng)安全及防范措施
PHP 遵從大多數(shù)服務(wù)器系統(tǒng)中關(guān)于文件和目錄權(quán)限的安全機(jī)制。這就使管理員可以控制哪些文件在文件系統(tǒng)內(nèi)是可讀的。必須特別注意的是全局的可讀文件,并確保每一個(gè)有權(quán)限的用戶(hù)對(duì)這些文件的讀取動(dòng)作都是安全的。
PHP 被設(shè)計(jì)為以用戶(hù)級(jí)別來(lái)訪(fǎng)問(wèn)文件系統(tǒng),所以完全有可能通過(guò)編寫(xiě)一段 PHP 代碼來(lái)讀取系統(tǒng)文件如 /etc/passwd,更改網(wǎng)絡(luò)連接以及發(fā)送大量打印任務(wù)等等。因此必須確保 PHP 代碼讀取和寫(xiě)入的是合適的文件。
請(qǐng)看下面的代碼,用戶(hù)想要?jiǎng)h除自己主目錄中的一個(gè)文件。假設(shè)此情形是通過(guò) web 界面來(lái)管理文件系統(tǒng),因此 Apache 用戶(hù)有權(quán)刪除用戶(hù)目錄下的文件。
Example #1 不對(duì)變量進(jìn)行安全檢查會(huì)導(dǎo)致……
<?php // 從用戶(hù)目錄中刪除指定的文件 $username = $_POST[’user_submitted_name’]; $userfile = $_POST[’user_submitted_filename’]; $homedir = '/home/$username'; unlink ('$homedir/$userfile'); echo 'The file has been deleted!';?>
既然 username 和 filename 變量可以通過(guò)用戶(hù)表單來(lái)提交,那就可以提交別人的用戶(hù)名和文件名,甚至可以刪掉本來(lái)不應(yīng)該讓他們刪除的文件。這種情況下,就要考慮其它方式的認(rèn)證。想想看如果提交的變量是“../etc/”和“passwd”會(huì)發(fā)生什么。上面的代碼就等同于:
Example #2 ……文件系統(tǒng)攻擊
<?php // 刪除硬盤(pán)中任何 PHP 有訪(fǎng)問(wèn)權(quán)限的文件。如果 PHP 有 root 權(quán)限: $username = $_POST[’user_submitted_name’]; // '../etc' $userfile = $_POST[’user_submitted_filename’]; // 'passwd' $homedir = '/home/$username'; // '/home/../etc' unlink('$homedir/$userfile'); // '/home/../etc/passwd' echo 'The file has been deleted!';?>
有兩個(gè)重要措施來(lái)防止此類(lèi)問(wèn)題。
只給 PHP 的 web 用戶(hù)很有限的權(quán)限。檢查所有提交上來(lái)的變量。下面是改進(jìn)的腳本:
Example #3 更安全的文件名檢查
<?php // 刪除硬盤(pán)中 PHP 有權(quán)訪(fǎng)問(wèn)的文件 $username = $_SERVER[’REMOTE_USER’]; // 使用認(rèn)證機(jī)制 $userfile = basename($_POST[’user_submitted_filename’]); $homedir = '/home/$username'; $filepath = '$homedir/$userfile'; if (file_exists($filepath) && unlink($filepath)) {$logstring = 'Deleted $filepathn'; } else {$logstring = 'Failed to delete $filepathn'; } $fp = fopen('/home/logging/filedelete.log', 'a'); fwrite ($fp, $logstring); fclose($fp); echo htmlentities($logstring, ENT_QUOTES);?>
然而,這樣做仍然是有缺陷的。如果認(rèn)證系統(tǒng)允許用戶(hù)建立自己的登錄用戶(hù)名,而用戶(hù)選擇用“../etc/”作為用戶(hù)名,系統(tǒng)又一次淪陷了。所以,需要加強(qiáng)檢查:
Example #4 更安全的文件名檢查
<?php $username = $_SERVER[’REMOTE_USER’]; // 使用認(rèn)證機(jī)制 $userfile = $_POST[’user_submitted_filename’]; $homedir = '/home/$username'; $filepath = '$homedir/$userfile'; if (!ctype_alnum($username) || !preg_match(’/^(?:[a-z0-9_-]|.(?!.))+$/iD’, $userfile)) {die('Bad username/filename'); } //后略……?>
根據(jù)操作系統(tǒng)的不同,存在著各種各樣需要注意的文件,包括聯(lián)系到系統(tǒng)的設(shè)備(/dev/ 或者 COM1)、配置文件(/ect/ 文件和 .ini文件)、常用的存儲(chǔ)區(qū)域(/home/ 或者 My Documents)等等。由于此原因,建立一個(gè)策略禁止所有權(quán)限而只開(kāi)放明確允許的通常更容易些。
相關(guān)文章:
1. Laravel操作session和cookie的教程詳解2. html小技巧之td,div標(biāo)簽里內(nèi)容不換行3. XML入門(mén)的常見(jiàn)問(wèn)題(一)4. css進(jìn)階學(xué)習(xí) 選擇符5. 將properties文件的配置設(shè)置為整個(gè)Web應(yīng)用的全局變量實(shí)現(xiàn)方法6. PHP字符串前后字符或空格刪除方法介紹7. jsp實(shí)現(xiàn)登錄界面8. 解析原生JS getComputedStyle9. 淺談SpringMVC jsp前臺(tái)獲取參數(shù)的方式 EL表達(dá)式10. Echarts通過(guò)dataset數(shù)據(jù)集實(shí)現(xiàn)創(chuàng)建單軸散點(diǎn)圖
