• 6個”檔案上傳”功能的資訊安全風險與防護

    有些網站會提供檔案上傳的功能,例如 DropBox、社交網站提供照片上傳或是部落格網站提供檔案上傳分享等功能。

    駭客可以透過檔案上傳的方式執行惡性程式或是產生非預期的結果。因此,檔案上傳的安全防護不亞於帳號密碼的保護措施。

    這篇文章主要討論這些”檔案上傳”的網站,需要注意哪些資訊安全風險與防護的建議。

    我們會舉 6 個檔案上傳相關安全風險的原因、程式範例討論與安全防護必須要注意的建議。

     

    風險1: 檔案路徑

    file path injection 又稱為 path traversal。這樣的攻擊主要是透過檔案路徑的搜尋,間接存取其他網站的資源。

    當URL 網址的路徑內包含  ../ 就表示該網站有潛在的風險

    舉例來說,下列檔名的參數中,帶有路徑位置,因此駭客就可以藉由修改路徑位置,間接存取網站伺服器其他檔案資源。

    http://www.awesomefileupload.com/downloadFile?filename=/../downloadSrc/my_vacation_photos.zip

    例如,駭客可能會嘗試下列網址

    http://www.awesomefileupload.com/downloadFile?filename=/../../../../etc/passwd

    因此,針對這樣的攻擊,並須對於檔案名稱的輸入加以過濾。相關檔案的權限管理必須加以限制。

    風險2: Null Byte Injection

    Null 在系統內部,主要告訴電腦說,這是這個字串的結尾。

    在一些舊版的IIS 或是Java 對於這樣的 Null 並沒有妥善的處理,會導致一些非預期的行為。讓我們看幾個個案如果使用null byte (%00)在檔名中,會發生什麼情況?

    例如

    http://www.site.com/files?filename=../../../../etc/passwd%00profile.jpg

    雖然剛輸入的檔名為 JPG 結尾,但是舊版的 Java 程式讀取,

    還是會直接讀取到 /etc/passwd。

    雖然這樣的漏洞已經在 Java 7之後修正,

    但是正確的處理 Null byte 的輸入,還是處理輸入值重要的一環。

     

    風險3: 沒有適當的關閉資源

    當每一個檔案被開啟時,都有會一個相對應的 handle 紀錄該檔案開啟的狀態。

    檔案沒有被使用的時候,應該要適時的將該 Handle  關閉。讓系統資源釋放。

    如果長時間都沒有關閉 Handle,會慢慢地導致系統資源不足,

    甚至系統當機,需要重新開機才能解決。

    以下列這個例子,finally這段 code就很重要,因為不管是正常執行還是發生 I/O exception 都還是要 close file handles。

    try {
       fileIn = getUploadInputStream();
       fileOut = new FileOutputStream(validatedFilePath);
       byte[] buffer = new byte[bufferSize];
       int byteCount = 0;
       
       while ((byteCount = input.read(buffer)) >= 0) {
       //what happens if an exception happens here?
              output.write(buffer, 0, byteCount);
       }
    
    } catch (IOException ioe) {
          //handle the exception somehow
    
    
    } finally {
          //close output streams to release memory resources!
          fileIn.close();
          fileOut.close();
    }
    Close File Handle

    但是這樣的寫法,如果遇到 close file handles 又出現 exception 那麼怎辦? 還要額外在處理這樣的 exception 比較複雜。Java 7之後提供 “try-with-resources statement”的寫法,可以自動處理相關 resource 的釋放與關閉。

     

    static String readFirstLineFromFile(String path) throws IOException {
    
    
        try (BufferedReader br = new BufferedReader(new FileReader(path))) {
    
    
            return br.readLine();
    
    
    
        }
    }
    try-with-resources statement

     

    風險4:上傳惡性程式

    駭客可能利用一些檔案的特性,上傳惡性程式以達到特定行為。下列是比較常見被駭客使用的檔案格式。

    • 病毒、惡性程式
    • 還有 JavaScript 可以造成 CSRF 或是XSS攻擊的 HTML
    • 可執行的程式。例如 JSP, JSPX, WAR, JAR, PHP, ASP, SH等

    以下提供相關副檔名的處理方式,如果真的需要儲存該類的副檔名,建議將該儲存的伺服器與網站伺服器分開。

    避免該儲存的檔案直接存放在與網站伺服器同一台機器。

    副檔名 防護建議
    HTMLHTM 拒絕這樣的檔案上傳。因為 HTML可以內含有害的 JavaScript
    .JS 拒絕JavaScript 可以帶來許多程式執行的風險,例如 JavaScript Injection, XSS, CSRF等。
    .jsp, .jspx 拒絕這類的檔案主要是 Java 網頁的執行。也會間接讓許多有害的程式執行。
    war 拒絕這是 JAR 檔案的集合。包含了 XML, HTML, JSP等。這樣的檔案可以控制取代整個網站的服務。更不能夠上傳。
    jpg pnggif 這些圖形檔的上傳必須要確認檔案格式的正確性。如何確認檔案格式的正確性,這邊另外介紹一個小技巧。”ImageMagick”ImageMagick是command-line的工具程式,可以用來轉換讀取各式各樣的圖形檔。使用這樣的工具,由於是 command-line 執行,要另外注意 command injection 的風險。
    .zip 在解壓縮之前要做一定的驗證。
    .doc, .ppt, .txt, 上傳之後,建議用防毒軟體做一定的掃描。

    風險5:壓縮檔炸彈

    這是一個特別製作的ZIP壓縮檔,該檔案壓縮的層數較多,壓縮之後再壓縮再壓縮…另外,解壓縮之後檔案高達好幾 G

    因此,如果網站沒有經過驗證就直接解壓縮,很容易造成該網站資源耗盡無法運作。

    http://www.unforgettable.dk/

    目前有許多程式都提供相關的 API 可以檢查壓縮檔。

    例如下列 Java 程式碼,在實際解壓縮之前,檢查該壓縮檔案解開後的大小 。

     

    import java.io.IOException;
    import java.util.Date;
    import java.util.Enumeration;
    import java.util.zip.ZipEntry;
    import java.util.zip.ZipFile;
    
    public class MainClass {
    
      public static void main(String[] args) {
    
        try {
          ZipFile zf = new ZipFile("your.zip");
          Enumeration e = zf.entries();
          while (e.hasMoreElements()) {
            ZipEntry ze = (ZipEntry) e.nextElement();
            String name = ze.getName();
    
    
            long uncompressedSize = ze.getSize();
    
    
            long compressedSize = ze.getCompressedSize();
            
            System.out.println(name);
            System.out.println(uncompressedSize);
            System.out.println(compressedSize);
            
          }
        } catch (IOException ex) {
          System.err.println(ex);
        }
      }
    }
    Get uncompressed ZIP filesize

    參考:http://www.java2s.com/Tutorial/Java/0180__File/GetuncompressedandcompressedSize.htm

     

    風險6:真實檔名

    檔案上傳 之後使用一個對照的 ID來儲存,不要用使用者所提供的檔名儲存。

    可進一步參考,這裡有些關於”檔案上傳”的安全設計建議,

    https://wiki.mozilla.org/WebAppSec/Secure_Coding_Guidelines#Uploads

    http://software-security.sans.org/blog/2009/12/28/8-basic-rules-toimplement-secure-file-uploads/

     

    摘要

    針對網站有提供檔案上傳功能,需要注意下列事項:

    • 確認檔案相關的權限,特別是寫入的權限應該要透過控管。
    • 確認檔名。例如 null byte 或是特殊符號的禁止。像是 / or \  ‘ 或是 ..。
    • 確認檔案內的型態內容。例如JPG, PNG 為副檔名時,確認該檔案是否為圖形檔。
    • 檢查檔案的 File headers以確認該檔案內容型態。
    • 用防毒軟體掃描該檔案是否為已知惡性程式。
    • 禁制特定類型可執行的檔案。例如 JS, EXE, SH, HTML 等

     

    Posted by Tony @ 12:06 pm

    Tags: , , , , ,

  • Leave a Reply

    Your email address will not be published.