2008-11-01 154 views
24

我工作的公司最近在我們託管的網站上發現了很多頭文件注入和文件上傳漏洞,雖然我們已經解決了頭注入攻擊方面的問題,但是我們尚未得到上傳漏洞的控制。上傳文件最安全的方法是什麼?

我試圖設置一個即插即用類型的上傳腳本系列,以便內部使用,設計人員可以將其複製到其網站結構中,修改一些變量,去他們的網站上傳表格。我們正在儘可能限制我們的曝光(我們已經關閉了fopen和shell命令)。

我搜索了網站最後一個小時,發現許多不同的答案處理依賴外部來源的特定方法。你們都認爲什麼是最好的腳本專用解決方案,足以作爲一種可靠的保護方法?另外,如果可能的話,我想保留限於PHP或僞代碼的語言。

編輯:我已經找到了我的答案(發佈如下),雖然它確實使用shell命令exec(),但如果阻止腳本文件上傳(此解決方案非常好),你不會遇到任何問題。

回答

36

最好的解決方案,恕我直言,是把包含上傳文件的目錄放在「web」環境之外,使用腳本使它們可下載。這樣,即使有人上傳腳本,也不能通過從瀏覽器調用腳本來執行腳本,也不必檢查上載文件的類型。

+2

是的,並將該目錄放在一個特殊的noexec掛載分區更好 – 2008-11-02 09:24:15

+2

也使分區nosuid。 – 2008-11-02 11:03:54

53
  1. 只允許授權用戶上傳文件。您也可以添加一個驗證碼以阻止原始機器人。

  2. 首先,設置MAX_FILE_SIZE在你上傳表單,並設置服務器上最大文件sizecount爲好。

    ini_set('post_max_size', '40M'); //or bigger by multiple files 
    ini_set('upload_max_filesize', '40M'); 
    ini_set('max_file_uploads', 10); 
    

    待辦事項大小檢查被上傳文件:

    if ($fileInput['size'] > $sizeLimit) 
        ; //handle size error here 
    
  3. 你應該使用$_FILESmove_uploaded_file()把你上傳的文件到正確的目錄,或者如果你要處理它,然後請使用is_uploaded_file()進行檢查。 (這些功能存在,以防止文件名注射引起register_globals。)

    $uploadStoragePath = '/file_storage'; 
    $fileInput = $_FILES['image']; 
    
    if (fileInput['error'] != UPLOAD_ERR_OK) 
        ; //handle upload error here 
    
    //size check here 
    
    $temporaryName = $fileInput['tmp_name']; 
    $extension = pathinfo($fileInput['name'], PATHINFO_EXTENSION); 
    
    //mime check, chmod, etc. here 
    
    $name = bin2hex(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM)); //true random id 
    
    move_uploaded_file($temporaryName, $uploadStoragePath.'/'.$name.'.'.$extension); 
    

    始終產生一個隨機ID,而不是使用原始文件名

  4. 例如http://static.example.com或至少一個新的目錄中創建一個新的子域public_html外,對上傳的文件。此子域或目錄不應執行任何文件。將其設置在服務器配置中,或通過目錄設置in a .htaccess file

    SetHandler none 
        SetHandler default-handler 
        Options -ExecCGI 
        php_flag engine off 
    

    也設定它爲with chmod()

    $noExecMode = 0644; 
        chmod($uploadedFile, $noExecMode); 
    

    對新上傳的文件也使用chmod(),並將其設置在目錄中。

  5. 你應該檢查MIME類型通過黑客發送的。你應該創建一個白名單允許的mime類型只允許圖像如果沒有其他格式是必要的。任何其他格式都是安全威脅。圖片太多,但至少我們有工具來處理他們...
    損壞內容例如:HTML在圖像文件可以通過content sniffing vulnerability瀏覽器導致XSS。當損壞的內容是代碼時,則可以結合eval注入漏洞。

    $userContent = '../uploads/malicious.jpg'; 
    include('includes/'.$userContent); 
    

    儘量避免這種情況,例如使用class autoloader,而不是手動包括PHP文件...
    通過處理,你必須關閉XSS內容嗅第一JavaScript注入在瀏覽器內容嗅探問題是典型的老年人msie,我認爲其他瀏覽器過濾他們很好。無論如何,你可以用一堆頭文件來防止這些問題。 (不通過每一個瀏覽器完全支持,但是這是你可以在客戶端做的最好的。)

    Strict-Transport-Security: max-age={your-max-age} 
    X-Content-Type-Options: nosniff 
    X-Frame-Options: deny 
    X-XSS-Protection: 1; mode=block 
    Content-Security-Policy: {your-security-policy} 
    

    您可以檢查文件是否與Imagick identify損壞,但是,這並不意味着一個完整的保護。

    try { 
        $uploadedImage = new Imagick($uploadedFile); 
        $attributes = $uploadedImage->identifyImage(); 
        $format = $image->getImageFormat(); 
        var_dump($attributes, $format); 
    } catch (ImagickException $exception) { 
        //handle damaged or corrupted images 
    } 
    

    如果你想爲其他MIME類型,你應該總是力下載他們,從來沒有包括他們進入的網頁,除非你真的知道你在做什麼?

    X-Download-Options: noopen 
    Content-Disposition: attachment; filename=untrustedfile.html 
    
  6. 有可能在EXIF數據裏面他們的代碼,例如有效的圖像文件。所以你必須清除exif從圖片,如果它的內容對你不重要。你可以用ImagickGD這樣做,但它們都需要重新打包文件。作爲替代,您可以找到一個exiftool。 我覺得最簡單的方法來清除exif,正在加載圖像GDsave them as PNG with highest quality。所以圖像不會丟失質量,並且標籤將被清除,因爲GD無法處理它。如果你想提取EXIF數據與上傳的PNG太...
    圖像使此,從來沒有使用preg_replace()如果patternreplacement是從用戶,因爲這將導致eval射入。如有必要,請使用preg_replace_callback()而不是eval regex flag。 (複製粘貼代碼中的常見錯誤。) Exif如果您的站點有eval注入漏洞(例如,如果在某處使用include($userInput)),數據可能會出現問題。

  7. 永遠不要include()require()上傳的文件,爲他們服務,爲靜態或使用file_get_contents()readfile(),或任何其他文件閱讀功能,如果你想控制訪問。
    這是很少可用的,但我認爲最好的方法使用X-Sendfile: {filename}標頭與sendfile apache module。通過標題,絕對不要使用用戶輸入而不進行驗證或清理,因爲這將導致HTTP標頭注入
    如果您不需要訪問控制(表示:只有授權用戶才能看到上傳的文件),然後通過您的網絡服務器提供文件。它要快得多...

  8. 使用antivir檢查上傳的文件,如果有的話。

  9. 總是使用組合保護,而不只是一個單一的方法。這將是更難以違反你的防禦...

相關問題