• 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 等

     

    Tags: , , , , ,

  • 資訊安全測試的測試個案資料庫 – FuzzDB

    這篇文章主要介紹 FuzzDB,FuzzDB主要提供網站資訊安全測試時,

    或是自動化安全測試工具所需要的測試個案資料,舉例來說, Injection的攻擊,

    但是實際測試的時候,到底要輸入什麼值來當作是 Injection Attack 的測試資料呢?

    FuzzDB 提供各種攻擊行為會用到的測試個案資料

    https://code.google.com/p/fuzzdb/source/browse/#svn%2Ftrunk

    fuzzDB

     

    舉例來說 “All-attacks-win.txt” 這個檔案提供許多安全測試個案所需的資料

    https://code.google.com/p/fuzzdb/source/browse/trunk/attack-payloads/all-attacks/all-attacks-win.txt

    Command injection

    | ping -i 30 127.0.0.1 |
    | ping -n 30 127.0.0.1 |
    & ping -i 30 127.0.0.1 &
    & ping -n 30 127.0.0.1 &
    ; ping 127.0.0.1 ;
    %0a ping -i 30 127.0.0.1 %0a
    `ping 127.0.0.1`
    ;echo 111111
    echo 111111
    response.write 111111

     

    SQL Injection

    ‘) or (‘x’=’x
    0 or 1=1
    ‘ or 0=0 —
    ” or 0=0 —
    or 0=0 —
    ‘ or 0=0 #
    ” or 0=0 #
    or 0=0 #
    ‘ or 1=1–
    ” or 1=1–

    Directory Traversal

    /./././././././././././boot.ini
    /../../../../../../../../../../../boot.ini%00
    /../../../../../../../../../../../boot.ini
    /..\../..\../..\../..\../..\../..\../boot.ini

     JavaScript / XSS injection 

    “><script>”
    <script>alert(“XSS”)</script>
    <<script>alert(“XSS”);//<</script>
    <script>alert(document.cookie)</script>
    ‘><script>alert(document.cookie)</script>
    ‘><script>alert(document.cookie);</script>
    \”;alert(‘XSS’);//
    %3cscript%3ealert(“XSS”);%3c/script%3e
    %3cscript%3ealert(document.cookie);%3c%2fscript%3e
    %3Cscript%3Ealert(%22X%20SS%22);%3C/script%3E
    &ltscript&gtalert(document.cookie);</script>

    Buffer Overflow

    %d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d
    %i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i
    %o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o
    %u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u

     

    進行資訊安全測試時,就可以使用自動化測試工具,或是半自動化測試工具

    挑選合適的測試個案資訊輸入進行測試

    測試流程 + 測試工具 + 測試個案資料 FuzzDB

    這三者的結合會讓整個資訊安全測試更加完善

    另一方面,如果再 Web Log中看到這些輸入值,也代表有潛在的資訊安全威脅,

    可以進一步設定防火牆,或是將網站的安全設計再強化。

     

    Tags: , , , ,

  • SQL Injection 基本原理與保護

    由於每個網站背後都會有 Database 存放資料,

    這篇文章主要介紹SQL Injection 的形成原因、如何避免、

    SQL injection 所帶來的資訊安全風險與建議。

     

    通常來說,網站或是雲端服務會利用資料庫來存放下列資料

    • 使用者資料、帳號
    • 商品資訊、訂單
    • 其他相關商業邏輯與權限

    由於 SQL是直譯式的語言,

    因此如果網站的使用者輸入與後端資料庫沒有適當的安全防護,

    駭客就可以利入輸入SQL 語法與參數讓後端資料庫執行駭客所預期的行為甚至控制整個資料庫與電腦。

    由於SQL Injection的問題存在多年,

    目前新的程式語言的寫法與資料庫本身都會提供一些保護機制,避免SQL injection 的發生

    當然,這也讓SQL injection 的攻擊方法有所演進,

    接著我們將從幾個 SQL injection 基本概念到進階的攻擊方法做討論。

     

    SQL 線上練習

    這邊介紹一個可以線上練習各種 SQL database 的雲端服務,

    讓你不需要安裝任何Database 就可以學習 SQL 語法,

    還可以選擇 MySQL, MS SQL, Oracle..等資料庫

    http://sqlzoo.net/wiki/Main_Page

     

    SQL online

     

    語法錯誤 ‘

    為了測試是否有 SQL injection 的風險,一開始都會利用語法錯誤來做測試,

    因此,常見的輸入值就是

    因為這個很多 database 的保留字,舉例來說:

    通常網站會有選單,當使用者選到法國,網站就會傳回該法國人口的數量,資料庫後端就會執行這樣的語法,

    SELECT population

    FROM world

    WHERE name = ‘France’

    回傳為:65350000

    但是如果輸入值加入 ‘ 讓SQL 語法就會變成:

    SELECT population

    FROM world

    WHERE name = ‘France’

    多了一個’ 就會造成 SQL Syntax error ,

    SQL Server 錯誤

    [Microsoft][ODBC SQL Server Driver][SQL Server]Unclosed quotation mark after the character string ‘France”. (SQL-42000) [err was 1 now 1] [state was 42000 now 42000] [Microsoft][ODBC SQL Server Driver][SQL Server]Incorrect syntax near ‘France”. (SQL-42000) [err was 1 now 1] [state was 42000 now 42000] [Microsoft][ODBC SQL Server Driver][SQL Server]Statement(s) could not be prepared. (SQL-42000)

    MySQL 的錯誤

    You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ”France”’ at line 2

    為什麼這樣的錯誤會造成 SQL injection 呢?

    因為我們知道原來輸入的值,在這個例子中:

    • France
    • France’

    最後這些值會變成整個SQL Query 語法的一部分讓 SQL 執行

    因此,接下來就可以把 ‘ 變成更複雜的查詢語句,達到其他特定目的。

     

    跳過過濾條件 or 1 = 1 —

    剛剛的例子中,我們查詢法國的人口數,

    那要如何得知所有國家的人口數呢?

    如果網站的控管沒有做好,透過 SQL injection 的語法就會變成

    SELECT population

    FROM world

    WHERE name = ‘France’ or 1 = 1 —

    透過 or 1 = 1 — 的輸入會造成 SQL 語句中的 Where 條件整個失效

    因此,將所有國家的人口數列出。

    (註: —  主要在 MS SQL Server 中為註解,將 — 後面的所有語句都變成註解)

     

    跳過登入驗證

    如果這樣的例子應用在登入驗證,原本的SQL 語句為

    使用者名稱輸入 Lily

    密碼輸入 secret

    SELECT *

    FROM users

    WHERE username = ‘Lily’ and password = ‘secret’

     

    變成

    使用者名稱輸入Lily’ or 1 = 1 —

    密碼輸入 secret

    該輸入傳到後端資料庫執行,就會變成如下

    SELECT *

    FROM users

    WHERE username = ‘Lily’ or 1 = 1 — ‘ and password = ‘secret’

    因為 — 之後所有的語句都是註解,加上 1= 1的緣故,

    造成整個 SQL 語法Where 的條件永遠為真,不管 password 是否輸入正確。

     

    SQL Injection 簡單測試

    因此,對於該網站是否有 SQL injection 可以用幾個簡單的測試,

    看看是否有相關的 SQL syntax 回傳

    • Oracle: ‘||’test
    • MS-SQL: ‘+’test
    • MySQL: ‘    ‘test

     

    網站保護

    如何避免 SQL injection 呢? 通常要由程式的寫法著手

    主要有三種方式

     

    1.Prepared statement

    每種程式語言都會提供類似的方式,將使用者輸入當作參數處理,而非直接組成一整個 SQL query 語句

    • Java EE – PreparedStatement() with bind variables
    • .NET – SqlCommand() or OleDbCommand() with bind variables
    • PHP – bindParam()

     

    2.Stored Procedure

    利用事先定義好的 Stored procedure來執行,

    Stored Procedure 與 Prepared statement

    主要的差異在於Stored procedure 是事先定義好的 SQL 程式存放在資料庫中。

    這兩個方式都可以避免 SQL injection 的發生。

     

    3.Validate User input

    使用者資料輸入的驗證與編碼。這種方法無法完全避免 SQL injection。

    主要是針對上線很久的程式,

    短時間又無法改為 Stored procedure 或是 prepared statement的寫法的時候

    就必須針對輸入的參數做一定的檢查與編碼,避免變成 SQL 語句執行。

     

     

    網站安全

    這篇文章主要介紹 SQL injection 的基本原理

    線上 SQL database 測試的雲端服務

    SQL injection 形成原因與如何測試

    最後說明三種由程式保護SQL Injection 的方法

     

     

    Tags: , , ,