目錄
前言
在網頁安全當中,資料消毒,是其中一種最重要的功能,其目的在於處理使用者輸入的內容,將有問題的字元或字串等移除掉或做變換處理,如果一個網站的輸入欄位不做任何的檢查,勢必會讓攻擊者進行注入的動作,最終可以在讀者的網頁服務上執行惡意的行為
其中在網路安全歷史中最常見也最久遠的就屬於Cross-Site Scripting或簡稱XSS攻擊,這個漏洞在動態注入惡意內容到使用者信任的網站上,之後的使用者連到該網站都會被惡意的code干擾到自己的瀏覽器
儘管早期大家覺得這是低風險的漏洞,時至今日隨著網頁技術的發展以及堆疊的架構越來越多,XSS的風險等級就漸漸提升了,並且也是現在做網頁安全很前期的階段就要測試的項目,只要一個網頁應用服務的伺服器沒有做好規範,就有可能讓攻擊者注入用戶端的惡意腳本,例如影響JavaScript感染其他連上線的讀者
儲存式與反應式XSS理論
通常XSS漏洞會被分類成兩種主要的形式
- 儲存式(Stored)
- 反射式(Reflected)
第一種儲存式的XSS攻擊也稱作持久性XSS,攻擊者會讓惡意的payload(惡意code)儲存進網頁伺服器的資料庫內或者快取儲存區內,而只要後端伺服器執行了惡意內容,就會讓應用服務接收到該payload,並且讓所有到該網站的使用者也執行到相關的惡意code
只需要單一組的儲存式XSS漏洞就可以攻擊到所有網站的使用者,通常這類的XSS漏洞喜好攻擊論壇的應用服務或平台式的部落格網站,特別是在留言區塊當中,因為這些區塊的設計就是為了讓使用者輸入後,如果有其他人以後拜訪到該網站就會中標
第二種反射式的XSS攻擊將惡意的payload放進HTTP請求或者連結當中,目標網頁應用服務就會將攻擊者置入的數值植入進頁面的內容當中,這類XSS只會針對送出請求或點到連結的使用者進行攻擊,且經常會發生在搜尋欄位或者搜尋結果當中,以及將使用者輸入的內容當作錯誤內容的標準
除了這兩種主流的之外,同時也有一種變形叫做DOM-based,這種XSS攻擊單獨針對文件物件模型(Document Object Model, DOM)元件進行感染,常見的瀏覽器都會分析HTML原始檔案,並且產出內部的DOM表示結構,這個結構裡可以被使用者修改的區塊都能被利用在XSS上
所以DOM-based的XSS漏洞可以是儲存式的也可以是反射式的,不過這種漏洞最主要的區別就是瀏覽器分析的網頁內容跟插入的JavaScript必須要能夠執行,所以需要設計一些不容易被察覺出來的函式
不論XSS payload是要傳送出去還是讓受害者執行,都必須先讓使用者連上感染過後的頁面,才能用他們的瀏覽器權限注入惡意code,意思是基本上XSS惡意內容並非由網頁服務伺服器來運作,而是由使用者的瀏覽器來進行觸發的
並且成功植入後的果實非常豐碩,從造成session劫持、強制跳轉惡意網頁、執行受害者的應用程式,到利用使用者的身份反向植入木馬進網頁服務等功能分分鐘直接讓攻擊者取得
JavaScript更新器
既然XSS這麼依賴JavaScript,我們也來介紹一下這個高階程式語言,是現代網頁應用服務不可或缺的主要元件,所有現代瀏覽器皆內建JavaScript引擎來執行JavaScript程式碼
當瀏覽器處理來自伺服器的HTTP回應時,裡面會包含HTML檔案,而瀏覽器就會根據該檔案建置DOM樹狀資料結構,並且渲染裡面的結構至讀者目前讀到的整個頁面,DOM裡的元件包括所有的表單、輸入欄位、圖片等跟網頁要呈現的樣子有關
而JavaScript的角色就是存取與修改頁面裡的DOM結構,讓整個網頁跟使用者的互動更靈活,同理從攻擊者的視角來看,只要有辦法注入JavaScript程式碼進去應用服務裡,就代表我們也可以存取跟修改DOM資料結構,便能夠製作重新跳轉的登入表單、把使用者的密碼提取出來以及竊取使用者的session cookie
而跟其他高階語言一樣,JavaScript可以組合許多邏輯成一個function裡
function multiplyValues(x,y) {
return x * y;
}
let a = multiplyValues(3, 5)
console.log(a)
multiplyValues這個function可以吃兩個參數,並且把兩者相乘回傳給呼叫的地方,而範例中我們讓a呼叫了這個函式,最終會把結果賦值給a這個變數,目前這個a變數也沒有任何型態,畢竟JavaScript是個相對寬鬆的程式語言,所以只有當變數接收到任何參數時當下才決定該變數型態
如果想要驗證這件事的話可以在瀏覽器內開啟開發者工具,並且到Console頁面底下就可以輸入JavaScript程式了,這也是所有現代瀏覽器都內建的功能,但這個區塊幾乎都測試不需要引入函式庫的寫法


可以看到15的型態是未定義的,而輸出不同的值對於未來我們要針對網頁安全進行debug時會非常有幫助,在分析複雜的JavaScript程式內容時觀察不同狀態下的資料是很重要的
辨識XSS漏洞
我們來初步的認識一下如何辨認出潛在的XSS漏洞入口,針對網頁應用服務的可輸入欄位(例如搜尋欄位)接受到何種程度的未消毒輸入,並且會呈現出何種的頁面給我們來看,一旦我們找到了可以開始的初始點,就先輸入一些特別的字元,然後觀察網頁針對這些特殊字元回傳哪些訊息回來
比較常見的特殊字元包含
< > ' " { } ;
我們稍微來說明一下這些特殊字元的用途,在HTML當中經常使用”<“跟”>”來標記元件的位置,決定了開始的位置以及結束的位置讓HTML檔案可以進行區分,而JavaScript則使用”{“跟”}”來表示function的範圍,單一的(‘)以及雙層(“)則用來表示字串,最後”;”分號決定了一段的結束
如果應用服務的輸入沒有移除或編碼這些字元,伺服器可能會將這些字元視作code的一部份而執行起來,代表可以讓有心人士新增一些code進網頁應用服務當中,所以在網頁設計歷史當中,制定了幾種編碼的方式,現今最常見的就屬HTML編碼或者URL編碼最多了
URL編碼或有時稱作百分符號編碼,把在網址裡那些非ASCII碼還有保留字元通通轉成”%20″,而HTML編碼或字元參考則特別用來顯示特殊意義給原先的字元,例如tag元素很長需要用到,像是<就是把\<這個tag元件的一部份轉換過去的,但遇到這類的編碼形式,瀏覽器通常不會轉回來,而是直接顯示轉換過的型態
如果我們可以注入這些特殊的字元進去頁面當中,瀏覽器就會將這些內容看作是code的一部份,就可以用這些工具建構出新的payload,並且只要受害者的瀏覽器執行到我們注入的惡意JavaScript code,就能夠在他們的環境中成功植入並且執行
但要達成這種條件可能需要使用多組不同的字元,這取決於我們的輸入欄位中包含了哪些東西,例如目前注入的地方是在div這個元素之中,我們就需要能夠注入”<“跟”>”來決定範圍,以及將我們自己的script tag也放進去來成為一組payload,而如果注入的位置已經有JavaScript tag了,那我們就只需要用(‘)、(“)跟”;”就可以新增我們想要的code內容了