php檔案上傳漏洞簡單分析

來源:互聯網
上載者:User


下面是一個簡單的檔案上傳表單

 代碼如下 複製代碼

<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']變數用來儲存上傳檔案時的錯誤資訊,它的值如下:

錯誤資訊 數值 說    明
UPLOAD_ERR_OK 0 沒有錯誤
UPLOAD_ERR_INI_SIZE 1 上傳檔案的大小超過php.ini的設定
UPLOAD_ERR_FROM_SIZE 2 上傳檔案的大小超過HTML表單中MAX_FILE_SIZE的值
UPLOAD_ERR_PARTIAL 3 只上傳部分的檔案
UPLOAD_ERR_NO_FILE 4 沒有檔案上傳

檔案上傳漏洞

如果提供給網站訪問者上傳圖片的功能,那必須小心訪問者上傳的實際可能不是圖片,而是可以指定的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">
  <input type="file" name="file1" /><br />
  <input type="submit" value="上傳檔案" />
  <input type="hidden" name="MAX_FILE_SIZE" value="1024" />
</form>

這個例子沒有檢驗檔案尾碼,可以上傳任意檔案,很明顯的上傳漏洞,要解決上面的問題很簡單,我們從一段代碼來看。

 代碼如下 複製代碼
 switch( $extension )
   {
    case 'application/msword':
    $extension ='doc';
    break;
    case 'application/vnd.ms-excel':
    $extension ='xls';
    break;
    case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document':
    $extension ='docx';
    break;
    case 'application/vnd.ms-powerpoint':
    $extension ='ppt';
    break;
    case 'application/pdf':
    $extension ='pdf';
    break;
    case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':
    $extension ='xlsx';
    break;
    default:
    die('只允許上傳doc,docx,xls,pdf,ppt檔案 <a href="wend.php">重新上傳</a>');
   
   }

這個是用來限制使用者上傳的類型號或尾碼名了,這樣可以過濾簡單不能直接上傳php了,但是我們再看一個執行個體,你繪發現太可怕了。

用畫圖工具建立一個jpg或gif或png之類圖片格式,開頭一定是GIF或JPG或PNG之類。

將php網馬的頭部寫入GIF 如圖:

 代碼如下 複製代碼


然後寫一個簡單的php上傳檔案處理(我趕時間隨便寫的,沒什麼美感):

 

<?php

if($_FILES){
 echo '以下是錯誤的$_FILES:<br/>';
 echo "<pre>";
 print_r($_FILES);
 echo "</pre>";

 echo "以下是錯誤的getimagesize()<br/>";
 echo "<pre>";
 print_r(getimagesize($_FILES['bug']['tmp_name']));
 echo "</pre>";
 exit;
 $fp = fopen($_FILES['bug']['tmp_name'],"r");
 $content = fread($fp,filesize ($_FILES['bug']['tmp_name']));
 //echo $content 可以看到上傳的原始碼
}
?>

<form action="" method="post" enctype="multipart/form-data">

<input type="file" name="bug" />

<input type="submit" >
</form>

就可以看到如圖這樣坑爹的效果了。


首先是print_r($_FILES) 直接顯示的是擴充的jpg結果。
然後是php函數getimagesize()的結果是gif(它以檔案開頭那段為判斷依據)。

在這種問題上php是無法解決的,但我們可以從伺服器目錄許可權來操作,下面提供一些解決辦。

其實,我們抓住幾個地方即可,我們先來分析下,既然使用者要上存檔案,而且檔案將是多種多樣格式;可能有的檔案內容與使用者傳入格式不一致,有的檔案內容還夾雜木馬代碼。 那麼,我們讓使用者上存檔案,跟網站檔案做一個分別授權,做隔離。

讓儲存上存目錄獨立開來,目錄許可權唯讀不能執行
這一步從系統設計加以授權,無論你上次什麼檔案,都不可能執行到。就算我不做任何檢測,你的檔案都上存到這裡了,也不會對我系統構成安全。(如果有使用者上存一些反動言語的圖片,那另外需要處理的)

 

不直接使用伺服器傳入值,所有都要進行檢測

這類跟我們做一切輸入都是有害原則一樣,對於用戶端傳入的:type, name ,都要進行判斷,不直接使用。對於要產生到某個目錄,某個檔案名稱。

檔案名稱最好方法是:自己寫死目錄(不要讀取傳入目錄),檔案名稱,最好自己隨機產生,不讀取使用者檔案名稱。副檔名,可以取最右邊"."後面字元。

以上2個方法,剛好從2個方面對上存做了整體約束。

方法2 : 儲存上存檔案名稱,按照自己指定目錄寫入,並且檔案名稱自己產生的。

方法1:只要保證檔案寫對了位置,然後從配置上,對寫入目錄進行許可權控制,這個是治本。可以做到,你無論上存什麼檔案,都讓你沒有許可權跳出去可以運行。

 

以上2個方法,一起使用,可以保證檔案正確存到地方,然後,許可權可以控制。 這裡順便說明下, 判斷使用者上存檔案是否滿足要求類型,就直接檢查副檔名,只要滿足副檔名就讓上存。 反正,做了執行許可權限制,你不按要求上存內容,也無妨。 反正,不能執行,也不會有多大危害性的。

正確步驟:
1.讀取檔案名稱,驗證副檔名是不是在範圍內

2.自己定義產生的檔案名稱,目錄,副檔名可以來自檔案名稱副檔名。 其它值,都自己配置,不讀取上存中內容

3.將檔案 移到新目錄(這個目錄使用權限設定唯讀)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.