任意檔案上傳漏洞
檔案上傳漏洞(File Upload Attack)是由于檔案上傳功能實作代碼沒有嚴格限制使用者上傳的檔案字尾以及檔案類型,導緻允許攻擊者向某個可通過 Web 通路的目錄上傳任意PHP檔案,并能夠将這些檔案傳遞給 PHP 解釋器,就可以在遠端伺服器上執行任意PHP腳本。
一套web應用程式,一般都會提供檔案上傳的功能,友善來訪者上傳一些檔案。
下面是一個簡單的檔案上傳表單
<form action="upload.php" method="post" enctype="multipart/form-data" name="form1">
<input type="file" name="file1" /><br />
<input type="submit" value="上傳檔案" />
<input type="hidden" name="MAX_FILE_SIZE" value="1024" />
</form>
php的配置檔案php.ini,其中選項upload_max_filesize指定允許上傳的檔案大小,預設是2M
$_FILES數組變量
PHP使用變量$_FILES來上傳檔案,$_FILES是一個數組。
如果上傳test.txt,那麼$_FILES數組的内容為:
$FILES
Array
{
[file] => Array
{
[name] => test.txt //檔案名稱
[type] => text/plain //MIME類型
[tmp_name] => /tmp/php5D.tmp //臨時檔案
[error] => 0 //錯誤資訊
[size] => 536 //檔案大小,機關位元組
}
}
如果上傳檔案按鈕的name屬性值為file
<input type="file" name="file" />
那麼使用$_FILES['file']['name']來獲得用戶端上傳檔案名稱,不包含路徑。使用$_FILES['file']['tmp_name']來獲得服務端儲存上傳檔案的臨時檔案路徑
存放上傳檔案的檔案夾
PHP不會直接将上傳檔案放到網站根目錄中,而是儲存為一個臨時檔案,名稱就是$_FILES['file']['tmp_name']的值,開發者必須把這個臨時檔案複制到存放的網站檔案夾中。
$_FILES['file']['tmp_name']的值是由PHP設定的,與檔案原始名稱不一樣,開發者必須使用$_FILES['file']['name']來取得上傳檔案的原始名稱。
上傳檔案時的錯誤資訊 $_FILES['file']['error']變量用來儲存上傳檔案時的錯誤資訊,它的值如下:
<a href="http://blog.51cto.com/attachment/201309/235554372.png" target="_blank"></a>
檔案上傳漏洞
如果提供給網站通路者上傳圖檔的功能,那必須小心通路者上傳的實際可能不是圖檔,而是可以指定的PHP程式。如果存放圖檔的目錄是一個開放的檔案夾,則入侵者就可以遠端執行上傳的PHP檔案來進行攻擊。
下面是一個簡單的檔案上傳例子:
<?php
// 設定上傳檔案的目錄
$uploaddir = "D:/www/images/";
// 檢查file是否存在
if (isset($_FILES['file1']))
// 要放在網站目錄中的完整路徑,包含檔案名
$uploadfile = $uploaddir . $_FILES['file1']['name'];
// 将伺服器存放的路徑,移動到真實檔案名 move_uploaded_file($_FILES['file1']['tmp_name'], $uploadfile);
}
?>
……
<form method="post" enctype="multipart/form-data" name="form1">
這個例子沒有檢驗檔案字尾,可以上傳任意檔案,很明顯的上傳漏洞。
利用此漏洞黑客克制自由上床任意的木馬檔案而導緻網站失陷。
漏洞防護措施
解決上面所述問題的一種方法是通過檢查上傳檔案的類型來限制使用者的檔案上傳,如以下代碼所示。
if(isset($_POST["form"]))
{
if($_FILES['upfile']['type'] == 'image/pjpeg') //檢查檔案類型是否為JPEG
$uploadfile = "upfiles/".$_FILES['upfile']['name'];
//上傳後檔案所在的檔案名和路徑
move_uploaded_file($_FILES['upfile']['tmp_name'], $uploadfile);
//上傳檔案
print_r($_FILES);
die();
else
die("上傳檔案的格式不正确!");
?>
上面的代碼要求使用者上傳的檔案必須是JPEG類型的圖檔檔案,徹底地避免了終端使用者通過上傳PHP腳本危害伺服器的行為。
檔案上傳路徑變量過濾不嚴
在許多論壇的使用者發帖頁面中存在這樣的上傳Form,如圖7-27所示,其網頁程式設計代碼為:
“<form action="user_upfile.asp" ...>
<input type="hidden" name="filepath" value="UploadFile">
<input type="file" name="file">
<input type="submit" name="Submit" value="上傳" class="login_btn">
</form>”
在其中“filepath”是檔案上傳路徑,由于網頁編寫者未對該變量進行任何過濾,是以使用者可以任意修改該變量值。在網頁程式設計語言中有一個特殊的截止符"\0",該符号的作用是通知網頁伺服器中止後面
的資料接收。利用該截止符可們可以重新構造filepath,例如正常的上傳路徑是:
“http://www.***.com/bbs/uploadface/200409240824.jpg”,
但是當我們使用“\0”構造filepath為
“http://www.***.com/newmm.asp\0/200409240824.jpg ”
這樣當伺服器接收filepath資料時,檢測到newmm.asp後面的\0後了解為filepath的資料就止結束了,這樣我們上傳的檔案就被儲存成了:“http://www.***.com/newmm.asp”。
利用這個上傳漏洞就可以任意上傳如.ASP的網頁木馬,然後連接配接上傳的網頁即可控制該網站系統。
提示:可能有讀者會想,如果網頁伺服器在檢測驗證上傳檔案的格式時,碰到“/0”就截止,那麼不就出現檔案上傳類型不符的錯誤了嗎?其實在檢測驗證上傳檔案的格式時,系統是從filepath的右邊向左邊讀取資料的,是以它首先檢測到的是“.jpg”,當然就不會報錯了。
最安全的防範辦法就是删除上傳頁面。
本文轉自Tar0 51CTO部落格,原文連結:http://blog.51cto.com/tar0cissp/1286799
,如需轉載請自行聯系原作者