Cross-Site Scripting
Cross-Site Scripting (XSS) 對網站而言,是一個大麻煩,不只是其弱點容易被發現與使用,被利用後所造成的後果更是無法預期! 現今幾乎所有的網站都會使用到 Javascript,很少純粹使用 HTML 語言,這導致使用者必須強迫接受 script 指令,在這個前提下,XSS 就是利用用戶端執行 script 時,埋入惡意程式,進而掌握機密資訊或後門,來達成竊取身份或遠端監控等目標。
Cross-Site Scripting 可以分為反射式(Reflected)、儲存式(Stored):
-
Reflected XSS 利用網站從存取可從外部修改的參數時,未經驗證而被埋入惡意語法,通常是利用可供輸入的欄位表單或可經proxy 修改的參數等功能,埋入惡意 script 語法,再將惡意連結偽裝讓受害人點擊,藉此騙過伺服器驗證而被盜取用戶端的身分資訊,並傳至第三方站台做為收集或掌控。
-
Stored XSS 則為利用類似留言板等網站功能,將外部輸入的惡意語法直接儲存在資料庫,當每個用戶存取到該頁面時,都會讀取到該惡意行為而被攻擊,受害者的層面更為廣大。

由此可知,XSS 的攻擊面向很多樣化,就算針對特殊符號阻擋,還是可能利用編碼或其他格式來構成script 語法,只要想辦法避開檢驗規則即可,而不像 SQL injection 只能符合 SQL 的語法,相對於HTML 格式嚴謹許多。就如從外部輸入 onmouseover=alert(document.cookie) ,其中沒使用到< >等跳脫字元,但瀏覽器認定為合法的HTML事件而被執行,再加上可編成其他格式來逃避驗證規則,難怪此弱點仍然是眾多駭客攻打網站的首選。
防禦方法可參考如 HTTP Header 安全性所述,對 Header 加入安全設定防止被竊取機密資訊,或 Injection Attack 的通用原則,對可竄改的外部來源做過濾驗證,有幾項原則可參考:
-
不要將不信任資料放入 HTML 中,但通常難以達成。
-
不信任資料放入 HTML 前須先進行編碼特殊字元,例如 & < > ” ‘ 及 / 等字元。
-
不信任資料不建議放入 Javascript ,極度危險,因為難以確認編碼目標。
-
不信任資料放入CSS 中需要經過編碼處理,HTML Style格式同樣會造成跳脫。
當然最安全方法是使用白名單政策,可使用正則表示式(Regular Expression) 來限定外部參數的資料格式,但通常很難符合網站功能的需求,因此會採用黑名單方式,可藉由第三方套件或開發語言原生的安全套件來過濾跳脫字元,如 OWASP 的 ESAPI 專案或微軟原生提供的 AntiXSS 套件等,都是經測試防禦效果較為全面的選擇,並有經過第三方單位比較針對各字元編碼的成效。
ESAPI
輸入端驗證
String validatedFirstName = ESAPI.validator().getValidInput(“FirstName”,
myForm.getFirstName(), “FirstNameRegex”, 255, false, errorList);
boolean isValidFirstName = ESAPI.validator().isValidInput(“FirstName”,
myForm.getFirstName(), “FirstNameRegex”, 255, false);
輸出端編碼
String safeOutput = ESAPI.encoder().encodeForHTML( clean encoded output Comment );
AntiXSS
HtmlEncode Method: 將內容經過編碼
GetSafeHtml Method: 輸出完整的HTML架構
GetSafeHtmlFragment Method: 將輸入的HTML片段輸出