LV. 15
GP 63

【網頁安全】給網頁開發新人的 XSS 攻擊 介紹與防範

樓主 摘喵喵 kanade86514
GP68 BP-
現今網路世界的資源非常豐富,網頁開發的入門門檻越來越低。雖充斥著大量的教學文章,但這些文章為了能以最簡單的方式說明,大多都忽略最基礎的資訊安全。

因此我特地撰寫此篇文章,期望能宣達給網頁開發的新血,告訴大家如何保障自己開發的網站的安全,降低遭到黑帽駭客攻擊的風險。




何謂 Web Security (網頁安全)

泛指針對網頁、網站上的資訊安全,涵蓋程式漏洞、邏輯漏洞、資訊洩漏等。



何謂 XSS (Cross-Site Scripting) 攻擊

XSS 全稱為 Cross-Site Scripting,可中譯為跨網站指令碼攻擊。相信想接觸網站開發的朋友們一定聽過,有一種可以寫在網頁裡,讓瀏覽器執行的程式碼稱為 JavaScript,只要使用 HTML 的 <script> 標籤,就可以在裡面撰寫一些 JavaScript 的程式,讓網頁具有動態、互動效果,甚至能製作遊戲。

雖然 JavaScript 如此方便,但各位是否想過,如果讓任何人可以在你網站上寫入任何 JavaScript 代碼會發生什麼事呢?

那將會非常的危險!因為使用者相信你的網頁是安全的!以為安全進入網站後反而被導向到釣魚網站、甚至被竊取帳號密碼、個人資料,但使用者仍然會傻傻地不知道發生什麼事。

像這樣由惡意人士代入可執行的惡意代碼的手法就被稱為 XSS 攻擊。

至於如何竊取資料?只要插入代碼讓它以 AJAX 方式傳送到攻擊者的伺服器即可。

簡易代碼示範,此網頁具有一個 input 和 button:


當使用者以為輸入密碼是安全的,殊不知當使用者滑鼠點下 Submit 按鈕,會觸發 onfocusout 事件,使密碼被默默寄送到惡意者的伺服器 (此處以不存在的 localhost 進行示範)。


此示範是我本身已經寫好在網頁之中,假如是惡意人士發現可以插入代碼的漏洞,那麼他就可以以「 document.getElementById('id').onfocusout = function() {...} 」之類的方法動態插入事件,或是竊取 cookie 中藏有的重要資料。不僅僅是如此,使用者非常信任你的網站,所以你執行任意指令時使用者幾乎不會注意到,因此還可以拿來進行更惡劣的用途。

目前 XSS 攻擊的種類大致可以分成以下幾種類型:
  • Stored XSS (儲存型)
  • Reflected XSS (反射型)
  • DOM-Based XSS (基於 DOM 的類型)

1. Stored XSS (儲存型)

會被保存在伺服器資料庫中的 JavaScript 代碼引起的攻擊即為 Stored XSS,最常見的就是論壇文章、留言板等等,因為使用者可以輸入任意內容,若沒有確實檢查,那使用者輸入如 <script> 等關鍵字就會被當成正常的 HTML 執行,標籤的內容也會被正常的作為 JavaScript 代碼執行。

像現在各位所使用的巴哈姆特論壇也曾發生過 Stored XSS 的漏洞,詳情可參考此篇文章:

2. Reflected XSS (反射型)

Reflected 是指不會被儲存在資料庫中,而是由網頁後端直接嵌入由前端使用者所傳送過來的內容造成的,最常見的就是以 GET 方法傳送資料給伺服器時,伺服器未檢查就將內容回應到網頁上所產生的漏洞。

此處也用簡單代碼作示範:


功能非常簡單,提供一個 input 讓使用者輸入名字,確定之後,網頁會出現 Hi, XXX 的訊息。



仔細注意網址會發現 GET 參數就是網址上的「 ? 」後面那串,假如我修改成「 ?name=<script>alert(123)</script>」:



這就是因為網頁後端沒有過濾掉惡意字元,直接回傳的內容理所當然會變成正常的代碼執行。

而此手法需透過特定網址點入,因此攻擊者通常會以釣魚手法、社交工程等方式誘騙受害者點入連結,但因為代碼都在網址上,只要細心一點就不容易受害。

3. DOM-Based XSS

了解此種 XSS 類型時,務必事先了解 DOM 是什麼,DOM 全稱為 Document Object Model,用以描述 HTML 文件的表示法,它讓我們可以使用 JavaScript 動態產生完整的網頁,而不必透過伺服器。

因此 DOM-Based XSS 就是指網頁上的 JavaScript 在執行過程中,沒有詳細檢查資料使得操作 DOM 的過程代入了惡意指令。

此處也提供一個簡單的示範:


正常輸入執行後,input 的內容會被代入到 <span id="show_name"> 之中,而網頁本身並不會跳轉。



假如未妥善檢查內容就代入的話,輸入任意的內容都會被建立成有效的 DOM 物件,包含嵌入的代碼也會被執行,此處試著輸入「 <img src=# onerror="alert(123)"> 」。



但這樣除非攻擊者親自到受害者電腦前輸入,否則不可能讓受害者輸入這種惡意代碼。因此通常需要搭配前兩個手法。讓內容保存在伺服器資料庫中、或是以反射型的方式製造出內容,再藉由JavaScript 動態產生有效的 DOM 物件來運行惡意代碼。



如何防範 XSS 攻擊?

1. Stored、Reflected 防範

前兩種 Stored、Reflected 的類型都必須由後端進行防範,除了必要的 HTML 代碼,任何允許使用者輸入的內容都需要檢查,刪除所有「<script>」、「 onerror=」及其他任何可能執行代碼的字串。

若內容只是純字串呈現,基本上只要將以下左欄所有的字元替換成右欄文字就可以杜絕了。
原始字元 HTML 跳脫字元
(請去除 & 後方的空白)
< & lt;
> & gt;
" & quot;
' & #x27;
/ & #x2F;
& & amp;
(巴哈把我的「& amp;」變成「&」了 )

當瀏覽器解析時遇到右欄的文字內容,會認為是左欄的字元,但絕對不會當成代碼的部份,而是純粹的文字,所以顯示上還是會像左邊的字元。

2. DOM-Based 防範

其他兩種類型必須由後端來防範,而 DOM-Based 則必須由前端來防範,但基本上還是跟前面的原則相同。

另外不同的一點就是應該選擇正確的方法、屬性來操作 DOM,譬如前面的示範中會產生漏洞的主要原因是「 document.getElementById('show_name').innerHTML = name; 」中的「 innerHTML 」屬性,此屬性代表插入的內容是合法的 HTML 字串,所以字串會解析成 DOM 物件。

此處的話應該使用「 innerText 」,使用此屬性插入字串時,會被保證作為純粹的文字,也就不可能被插入惡意代碼執行了。




以上就是我的心得和建議提供給網頁開發的新人們,希望能藉此提升各位對網頁安全的意識。
若有其他大大覺得有錯誤的地方也歡迎告知,讓我能及時修正。

另外附上我於板上發表的另一篇文章:
68
-
未登入的勇者,要加入討論嗎?
板務人員:歡迎申請板主

精華區有 10 筆文章
目前無人維護,申請組長


face基於日前微軟官方表示 Internet Explorer 不再支援新的網路標準,可能無法使用新的應用程式來呈現網站內容,在瀏覽器支援度及網站安全性的雙重考量下,為了讓巴友們有更好的使用體驗,巴哈姆特即將於 2019年9月2日 停止支援 Internet Explorer 瀏覽器的頁面呈現和功能。
屆時建議您使用下述瀏覽器來瀏覽巴哈姆特:
。Google Chrome(推薦)
。Mozilla Firefox
。Microsoft Edge(Windows10以上的作業系統版本才可使用)

face我們了解您不想看到廣告的心情⋯ 若您願意支持巴哈姆特永續經營,請將 gamer.com.tw 加入廣告阻擋工具的白名單中,謝謝 !【教學】