Logo

新人日誌

首頁關於我部落格

新人日誌

Logo

網站會不定期發佈技術筆記、職場心得相關的內容,歡迎關注本站!

網站
首頁關於我部落格
部落格
分類系列文

© 新人日誌. All rights reserved. 2020-present.

本文為「從零開始的 Web 資安」系列第 7 篇

什麼是 XSS 攻擊?一次搞懂跨站腳本攻擊與防護方式

最後更新:2026年1月29日JavaScript

XSS,三個讓資安人員頭痛的字母。

它的全名是 Cross-Site Scripting,中文叫做「跨站腳本攻擊」。

你可能會問:「Cross-Site Scripting 的縮寫不是應該是 CSS 嗎?」

沒錯,但因為 CSS 已經被「層疊樣式表」(Cascading Style Sheets)用掉了,所以改用 XSS 來代表。

這種攻擊從 1999 年就存在了,到現在已經超過 25 年。

聽起來是老掉牙的攻擊手法,但它依然是現今最具威脅性的攻擊之一。

根據 IBM X-Force 的雲端安全報告,XSS 是影響最大的攻擊類型第一名。

而知名的資安組織 OWASP(開放網路應用程式安全專案)也把它列為十大網頁應用程式漏洞的第三名。

為什麼一個存在這麼久的攻擊,到今天還是這麼猖獗?

這篇文章會帶你拆解 XSS 攻擊的原理,看一個實際的程式碼範例,最後介紹如何防範這種攻擊。

XSS 攻擊的運作原理

讓我們先看看 XSS 攻擊是怎麼運作的。

這個攻擊涉及三個角色:

角色說明
攻擊者(駭客)注入惡意程式碼的人
受害者(使用者)不知情地執行惡意程式碼的人
網站(伺服器)被利用來傳播惡意程式碼的平台
說明注入惡意程式碼的人
說明不知情地執行惡意程式碼的人
說明被利用來傳播惡意程式碼的平台

攻擊情境:駭客如何發動 XSS 攻擊

第一步:駭客找到可以注入程式碼的地方

駭客會找到一個正常的、受信任的網站。

駭客會尋找網站上「可以輸入內容」的地方。

例如:留言板、評論區、搜尋框、個人簡介欄位等。

第二步:駭客注入惡意程式碼

假設這個網站有一個留言功能,使用者可以自由輸入文字。

正常使用者會輸入:「這個產品很棒!」

但駭客會輸入一段惡意的程式碼。

如果網站沒有做好防護,這段程式碼就會被存進資料庫,並顯示在網頁上。

這時候,惡意程式碼就像一顆地雷,埋在網頁裡面,等待下一個訪客觸發。

第三步:受害者瀏覽網頁,惡意程式碼被執行

當其他使用者瀏覽這個頁面時,瀏覽器會載入頁面上的所有內容。

包括駭客注入的那段惡意程式碼。

你可能會問:「我只是瀏覽網頁而已,為什麼會執行程式碼?」

這是因為瀏覽器的運作方式。

當你打開一個網頁時,瀏覽器會自動讀取並執行網頁裡的所有程式碼。

這就像你打開一本有聲書,音樂會自動播放一樣。

你不需要按任何按鈕,瀏覽器就會幫你執行網頁裡的 JavaScript。

所以只要網頁裡藏有惡意程式碼,你一打開頁面就中招了。

這時候,網站就在不知不覺中成為駭客的幫兇。

網站本身是無辜的,但它變成了「惡意程式碼的傳播管道」。

關鍵在於:這段惡意程式碼是在「受信任的網站」的環境下執行的。

瀏覽器不知道這段程式碼是駭客注入的,它只知道「這是這個網站的程式碼,我應該執行它」。

這就是 XSS 攻擊的可怕之處。

為什麼叫做 XSS(Cross-Site Scripting)?

了解了攻擊原理後,我們來看看這個名字的意思。

Scripting(腳本)

「腳本」指的是一段可以被執行的程式碼。

在網頁的世界裡,最常見的腳本就是 JavaScript。

當瀏覽器看到網頁裡有 JavaScript 程式碼時,就會自動執行它。

駭客注入的惡意程式碼,就是一段「惡意的腳本」。

Cross-Site(跨站)

「跨站」是什麼意思呢?

先來看看「同站」的情況。

正常情況下,網頁裡的程式碼都是網站自己寫的。

例如,example.com 網站裡的程式碼,是 example.com 的開發者寫的。

這種情況叫做「同站」——程式碼來自同一個網站。

但 XSS 攻擊不一樣。

駭客把自己的程式碼「偷渡」到別人的網站裡。

例如,駭客把惡意程式碼塞進 example.com 的留言板。

這段程式碼不是 example.com 寫的,而是駭客從「外部」注入的。

這種「外部程式碼混入網站」的情況,就是「跨站」。

組合起來:Cross-Site Scripting

  • Cross-Site(跨站):惡意程式碼是從外部注入的,不是網站自己的
  • Scripting(腳本):注入的是可執行的程式碼

合在一起就是:駭客把惡意腳本注入到別人的網站,讓訪客的瀏覽器執行。

這就是 XSS(Cross-Site Scripting)的意思。

XSS 攻擊可以造成什麼危害?

一旦惡意程式碼在受害者的瀏覽器中執行,駭客可以做很多事情。

篡改網頁內容,欺騙使用者

駭客可以用 JavaScript 修改網頁上顯示的內容。

想像一下這個情境:

你登入了網路銀行,想要轉帳 10,000 元給朋友「王小明」。

你填好表單,確認畫面顯示「轉帳金額:10,000 元,收款人:王小明」。

看起來沒問題,你按下確認。

但實際上,駭客的程式碼早就在背後偷偷修改了表單的資料。

你「看到」的是轉給王小明,但「實際送出」的是轉給駭客的帳戶。

等你發現帳戶少了錢,錢早就被轉走了。

這就是篡改網頁的可怕之處:你眼睛看到的,不一定是真的。

竊取 Cookie,劫持使用者的登入狀態

還記得 Cookie 嗎?

當你登入一個網站時,伺服器會產生一個「Session ID」(會話識別碼),代表你的登入身份。

這個 Session ID 會被存放在瀏覽器的 Cookie 裡面。

之後每次你發送請求,瀏覽器都會自動帶上這個 Cookie,伺服器就知道「這是剛才登入的那個人」。

換句話說,誰拿到你的 Cookie,誰就能假冒你的身份。

那駭客要怎麼拿到你的 Cookie 呢?

這就要說到 JavaScript 和瀏覽器的關係了。

當 JavaScript 在網頁上執行時,它可以存取瀏覽器提供的各種功能。

其中一個功能就是「讀取 Cookie」。

JavaScript 只要執行 document.cookie,就能讀取到當前網站的所有 Cookie。

這是瀏覽器設計的正常功能,讓網站可以管理使用者的登入狀態。

但問題是:駭客注入的惡意程式碼也是 JavaScript。

它在「受信任的網站」環境下執行,自然也有權限讀取該網站的 Cookie。

於是駭客可以透過 JavaScript 讀取你的 Cookie,然後傳送到駭客自己的伺服器。

駭客拿到你的 Cookie 後,就可以「劫持」(Hijack)你的登入狀態。

如果這是你的銀行網站,駭客就可以用你的身份登入,把你的錢轉走。

如果這是電商網站,駭客就可以用你的身份購物,讓你付錢。

植入惡意軟體

駭客可以透過 JavaScript 觸發檔案下載。

想像一下這個情境:

你只是瀏覽一個購物網站的商品頁面。

突然間,瀏覽器跳出一個下載視窗,顯示「系統更新程式.exe」。

如果你不小心點了「執行」,惡意軟體就會安裝到你的電腦裡。

更狡猾的做法是,駭客會讓下載視窗看起來像是正常的系統通知:

「您的 Flash Player 已過期,請點擊更新」

很多人看到這種訊息就會直接點下去,結果電腦就被植入了木馬程式。

一旦惡意軟體進入你的電腦,駭客就可以:

  • 監控你的鍵盤輸入,竊取所有密碼
  • 存取你電腦裡的檔案
  • 把你的電腦變成殭屍網路的一部分,用來攻擊其他人

導向釣魚網站

駭客可以透過 JavaScript 把你重新導向到另一個網站。

想像一下這個情境:

你在瀏覽某個論壇,點了一篇看起來很正常的文章。

頁面閃了一下,你發現自己還是在同一個論壇,但網頁顯示「您的登入已逾時,請重新登入」。

你沒多想,就輸入了帳號密碼。

但其實,你已經被導向到駭客做的假網站了。

這個假網站長得跟真的一模一樣,網址也很相似(例如把 forum.com 改成 forurn.com,把 m 換成 rn)。

你輸入的帳號密碼,全部都被駭客收走了。

這就是「釣魚攻擊」(Phishing)。

而 XSS 讓駭客可以在「你信任的網站」上發動釣魚攻擊,讓你更難察覺異常。

另一種攻擊方式:透過惡意連結

上面介紹的是「把程式碼存進網站,等人來看」的攻擊方式。

但駭客還有另一種手法:直接發送一個「帶有惡意程式碼的連結」給你。

這個連結可能透過 Email、簡訊、或社群媒體傳送。

連結看起來像是正常的網站網址,但裡面藏著惡意程式碼。

怎麼藏的呢?

你可能看過這種網址:https://example.com/search?q=手機

問號後面的 q=手機 是搜尋的關鍵字。

當你點擊這個連結,網站會顯示「您搜尋的關鍵字是:手機」。

駭客的手法是:把「手機」換成一段惡意程式碼。

當你點擊這個連結時,會發生什麼事?

首先,瀏覽器會向網站的伺服器發送請求,請求裡包含完整的網址。

伺服器收到請求後,會從網址裡取出 q= 後面的內容(也就是搜尋關鍵字)。

接著,伺服器會產生一個網頁,把這個關鍵字放進 HTML 裡面,變成「您搜尋的關鍵字是:OOO」。

最後,伺服器把這個網頁傳回給瀏覽器。

問題就出在這裡。

如果伺服器沒有檢查 q= 後面的內容是什麼,就直接放進 HTML 裡,那麼惡意程式碼也會被放進去。

所以惡意程式碼就從「網址」跑到「網頁」上了。

瀏覽器收到這個網頁後,看到裡面有程式碼,就會自動執行。

瀏覽器不知道這段程式碼是從網址帶進來的,它只知道「網頁裡有程式碼,我要執行它」。

因為程式碼是從「網址」帶進來,再被「反射」到網頁上的,所以叫做「反射型」XSS。

這兩種方式的差別在於:

攻擊方式程式碼存在哪裡如何觸發
存進網站(儲存型)網站的資料庫任何人瀏覽該頁面就會中招
惡意連結(反射型)網址本身只有點擊該連結的人會中招
程式碼存在哪裡網站的資料庫
如何觸發任何人瀏覽該頁面就會中招
程式碼存在哪裡網址本身
如何觸發只有點擊該連結的人會中招

不管是哪種方式,結果都一樣:駭客的程式碼在你的瀏覽器裡執行了。

XSS 攻擊程式碼範例

讓我們看一個簡單的範例。

這個範例不會造成實際傷害,但你可以理解攻擊的原理。

假設有一個網站的搜尋功能,網址長這樣:

https://example.com/search?q=手機

當你搜尋「手機」時,網頁會顯示:「您搜尋的關鍵字是:手機」。

如果網站沒有做好防護,駭客可以構造這樣的網址:

https://example.com/search?q=<script>alert('XSS')</script>

讓我們拆解這個網址:

部分說明
https://example.com網站的網域,看起來完全正常
/search搜尋功能的路徑
?q=搜尋的參數
<script>alert('XSS')</script>這就是惡意程式碼(Payload)
說明網站的網域,看起來完全正常
說明搜尋功能的路徑
說明搜尋的參數
說明這就是惡意程式碼(Payload)

當使用者點擊這個連結時,網頁會顯示:

您搜尋的關鍵字是:<script>alert('XSS')</script>

瀏覽器看到 <script> 標籤,就會執行裡面的程式碼。

結果是畫面會跳出一個警告視窗,顯示「XSS」。

這個範例只是跳出一個無害的視窗。

但駭客可以把 alert('XSS') 換成任何惡意程式碼,例如竊取 Cookie 的程式碼。

開發者如何防範 XSS 攻擊?

在講防護方式之前,我們先來理解 XSS 攻擊的核心問題。

瀏覽器在載入網頁時,會區分兩種東西:

  • 資料:純粹的文字內容,只是要「顯示」給使用者看的
  • 程式碼:需要「執行」的指令,例如 JavaScript

正常情況下,使用者在留言板輸入的內容應該是「資料」。

例如,使用者輸入「這個產品很棒!」,網頁應該只是把這段文字顯示出來。

但 XSS 攻擊的問題在於:

駭客輸入的內容「看起來像程式碼」,瀏覽器就會把它當成程式碼來執行。

例如,駭客輸入 <script>...</script>,瀏覽器看到 <script> 標籤,就會認為「這是程式碼,我要執行它」。

所以 XSS 攻擊的核心是:駭客把程式碼偽裝成資料,讓瀏覽器誤以為是要執行的指令。

理解了這個核心問題,防護的思路就很清楚了:

確保使用者輸入的內容只會被當成「資料」,而不是「程式碼」。

具體來說,有兩種做法。

防護方式一:不信任使用者輸入,驗證並過濾

第一個原則:永遠不要信任使用者輸入的任何內容。

不管是留言、評論、搜尋關鍵字,還是任何使用者可以輸入的地方,都要進行驗證。

做法是:檢查並拒絕可疑的內容。

如果你的留言功能只應該接受純文字,那就檢查輸入的內容:

  • 純文字 → 允許
  • 包含 <script> 標籤 → 拒絕
  • 包含 onclick、onerror 等事件屬性 → 拒絕
  • 包含 SQL 指令(順便防止 SQL Injection) → 拒絕
// 簡單的驗證範例
function validateInput(input) {
  // 檢查是否包含可疑的標籤或屬性
  const dangerousPatterns = /<script|onclick|onerror|javascript:/i;

  if (dangerousPatterns.test(input)) {
    return false;  // 拒絕這個輸入
  }
  return true;  // 允許這個輸入
}

防護方式二:輸出時進行編碼

第二個重要的防護是:在輸出內容到網頁時,進行編碼(Encoding)。

什麼是編碼?

就是把有特殊意義的字元,轉換成「純文字」的對應版本。

原始字元編碼後說明
<&lt;小於符號
>&gt;大於符號
"&quot;雙引號
'&#x27;單引號
&&amp;And 符號
編碼後&lt;
說明小於符號
編碼後&gt;
說明大於符號
編碼後&quot;
說明雙引號
編碼後&#x27;
說明單引號
編碼後&amp;
說明And 符號

舉個例子。

如果使用者輸入了 <script>alert('XSS')</script>,經過編碼後會變成:

&lt;script&gt;alert('XSS')&lt;/script&gt;

當瀏覽器看到 &lt; 時,它知道這只是要「顯示」一個小於符號,而不是一個 HTML 標籤的開始。

所以畫面上會顯示:<script>alert('XSS')</script>

但這段文字只是被「顯示」出來,不會被「執行」。

這樣就成功阻止了 XSS 攻擊。

防護重點整理

防護方式時機做法
驗證並過濾接收使用者輸入時檢查並拒絕可疑的內容
輸出編碼將內容顯示到網頁時把特殊字元轉換成純文字對應版本
時機接收使用者輸入時
做法檢查並拒絕可疑的內容
時機將內容顯示到網頁時
做法把特殊字元轉換成純文字對應版本

驗證輸入 + 編碼輸出,兩者都要做,才能提供完整的防護。

更多資源:OWASP Cheat Sheet

如果你想了解更多 XSS 防護的細節,推薦參考 OWASP 提供的 Cheat Sheet。

OWASP 是知名的資安組織,他們整理了詳細的程式碼範例和防護建議。

搜尋「OWASP XSS Prevention Cheat Sheet」就可以找到。

小結

讓我們回顧一下這篇文章的重點:

  1. XSS 是什麼:Cross-Site Scripting,跨站腳本攻擊,駭客把惡意程式碼注入到網頁中
  2. 攻擊原理:駭客注入的程式碼會在受害者的瀏覽器中執行,而且是在「受信任網站」的環境下執行
  3. 可能的危害:竊取 Cookie 劫持登入狀態、篡改網頁內容、植入惡意軟體、導向釣魚網站
  4. 防護方式一:驗證並過濾使用者輸入,拒絕可疑的內容
  5. 防護方式二:輸出時進行編碼,把特殊字元轉換成純文字

XSS 攻擊已經存在超過 25 年,但至今仍是最常見的攻擊之一。

身為開發者,做好輸入驗證和輸出編碼,就能大幅降低被攻擊的風險。

上一篇什麼是 CSRF 攻擊?一次搞懂跨站請求偽造與 Cookie 安全防護
下一篇SQL 注入攻擊全解析:從入門到防禦實戰指南
目前還沒有留言,成為第一個留言的人吧!

發表留言

留言將在審核後顯示。

JavaScript

目錄

  • XSS 攻擊的運作原理
  • 攻擊情境:駭客如何發動 XSS 攻擊
  • 第一步:駭客找到可以注入程式碼的地方
  • 第二步:駭客注入惡意程式碼
  • 第三步:受害者瀏覽網頁,惡意程式碼被執行
  • 為什麼叫做 XSS(Cross-Site Scripting)?
  • Scripting(腳本)
  • Cross-Site(跨站)
  • 組合起來:Cross-Site Scripting
  • XSS 攻擊可以造成什麼危害?
  • 篡改網頁內容,欺騙使用者
  • 竊取 Cookie,劫持使用者的登入狀態
  • 植入惡意軟體
  • 導向釣魚網站
  • 另一種攻擊方式:透過惡意連結
  • XSS 攻擊程式碼範例
  • 開發者如何防範 XSS 攻擊?
  • 防護方式一:不信任使用者輸入,驗證並過濾
  • 防護方式二:輸出時進行編碼
  • 防護重點整理
  • 更多資源:OWASP Cheat Sheet
  • 小結