2014年3月24日 星期一

Html跳脫字元處理(Escape Html)&XSS攻擊

特殊字元在Html的顯示處理會衍生出的相關問題常有:
1.Html頁面能不能正常的運作:此種情況通常是因為要在html中呈現的屬性值中含有特殊字元像是單引號(')、雙引號(")等,以Jsp的程式範例來說,我們可能會寫一段javascript如下:

var memo='${memo}'
假設${memo}的內容為'test,則整串javascript會變成var memo =''test' ,變成一句無效的javascript敘述,因前面兩個單引號已經表示字串的內容結尾,後面的test'即成為無效的敘述 ; 因此一定要養成良好的寫作習慣,要將Server端資料輸出到前端時,無論資料內容為何,還是盡量使用JSTL(<c:out value='${memo}' /> 或<bean:write ..>等有針對特殊字元的輸出做處理的 Tag函式庫,避免直接使用<%= %>或是${}等方式直接輸出。


2.Cross-Site Scripting(XSS) 跨網站指令稿攻擊:此種攻擊方式是利用網站未對
使用者輸入的內容加以過濾驗證處理,便將可能有攻擊性的Scripting在其他使用者的瀏覽器上
顯示執行,造成危害。例如將此串Scripting <script>alert('attack')</script>輸入在某個可供查詢輸入的文字方塊,一般來說,網站都會將使用者的查詢條件紀錄下來並隨同查詢結果一併再次顯示在回應的網頁上,若顯示查詢結果時,同時也執行了上面那段script,那麼即表示該頁面的輸出沒有針對特殊字元做輸出的處理。
如左圖即為在我自行製作的網頁的文字方塊內輸入上面那段script,再傳到server端後並沒有做任何特殊字元的過濾處理,而在顯示時也不使用任何有跳脫特殊字元的tag(如<c:out value='xxx' />),直接將那段script又原封不動的輸出在原html的文字方塊內,即產生被scripting 攻擊的效果。




我的前端頁面很單純,只是將該查詢的輸入內容再次從server端取得後並呈現在頁面上如下:
$(document).ready(function() {
         $(".searchWrapper").find("#keyword").val('${keyword}');
}
比較正確的做法應該是將'${keyword}'此段輸出改為<c:out value="${keyword}">,即可避免此種XSS的潛在危險。

當然以這個例子來說,實際上是危害不到任何人,只是提供一個會產生潛在XSS風險的寫法來做示範,若真的要有可能危害到其他瀏覽同一頁面的使用者,一般還是得將有風險的scripting輸入存入DB後,當其他使用者又瀏覽相同頁面時,再將該scripting輸出並執行,此種風險通常就存在可讓人輸入意見的論壇,若沒有針對特殊字元做過濾,則很容易在瀏覽其他人所留下的意見資訊時,被做XSS攻擊。


PS:
1.順帶一提,若要使用org.apache.commons.lang3的StringEscapeUtils來自行在後端escape特殊字元
,個人遇到的情況是當使用StringEscapeUtils.escapeHtml4及StringEscapeUtils.escapeHtml3都沒有針對單引號做escape,因此就自行寫了一個EscapeUtil並繼承StringEscapeUtils,並針對escapeHtml4未對單引號做escape的部分做補強,程式碼如下:
public class EscapeUtil extends StringEscapeUtils {
  /***
   * this method is to enhance  StringEscapeUtils.escapeHtml4' method,
   * StringEscapeUtils.escapeHtml4 doesn't escape "'" .
   * @param input
   * @return
   */
  public static String escapeHtml(String input){
   String escapeText= StringEscapeUtils.escapeHtml4(input);
   escapeText=escapeText.replaceAll("\'", "&#039;");
   return escapeText;
   
  }
}
附上StringEscapeUtils API參考網頁
2.XSS參考網站