XSS (Cross-Site Scripting):攻擊者在網頁注入惡意腳本,受害者瀏覽時腳本在其瀏覽器執行,竊取 Cookie、劫持 Session、盜取鍵盤輸入、重導向釣魚頁、甚至透過 ActiveX 控制本機程式 (舊版 IE)。
為避免與 CSS (樣式表) 混淆,故取名 XSS。
| 類型 | 特徵 | 儲存位置 | 範例 |
|---|---|---|---|
| 反射型 | URL 參數直接輸出回應 | 無 (即時) | 搜尋關鍵字、錯誤頁面 |
| 儲存型 | 惡意碼存入資料庫 | 資料庫 | 留言板、評論、用戶資料 |
| DOM 型 | 前端 JS 處理 URL 片段 | 前端邏輯 | 單頁應用路由、錨點解析 |
<%-- index.jsp --%>
<% String op = request.getParameter("opr"); %>
<div><%= op %></div>
攻擊載荷:
?opr=<script>alert('XSS')</script>
?opr=<img src=x onerror=alert(1)>
?opr=<script>location.href='https://evil.com'</script>
?opr=<script>new ActiveXObject('WScript.Shell').Run('calc.exe')</script> (舊 IE)
?opr=<script>var fso=new ActiveXObject('Scripting.FileSystemObject');...</script> (寫檔)
流程:
Comments 表comment.jsp,JSP 直接 `<%= comment.getContext() %>` 輸出關鍵程式碼:
<%-- comment.jsp 易受攻擊版 --%>
<c:forEach var="c" items="${all}">
<td><%= c.getCName() %></td>
<td><%= c.getCContext() %></td> <!-- 直接輸出未轉義 --%>
</c:forEach>
JSTL `
<%@ taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core" %>
<c:out value="${param.opr}" /> <!-- 自動轉義 --%>
<%@ taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core" %>
<c:forEach var="x" items="${requestScope.all}">
<tr>
<td><c:out value="${x.cName}" /></td>
<td><c:out value="${x.cContext}" /></td> <!-- 安全輸出 --%>
</tr>
</c:forEach>
| 方案 | 原理 | 適用場景 | 注意 |
|---|---|---|---|
<c:out> | HTML 實體編碼 | JSP 頁面輸出 | 預設 `escapeXml=true`,勿關閉 |
| EL `${...}` | 不轉義! | 僅用於屬性值或 JS 字串 (需配合轉義) | 直接輸出 HTML 內容**不安全** |
| 過濾器統一轉義 | ResponseWrapper 包裹 getWriter() | 全站舊專案快速修補 | 可能誤傷合法 HTML |
| 內容安全策略 (CSP) | HTTP Header 限制腳本來源 | 深度防禦、現代瀏覽器 | 需精心調整策略 |
| HttpOnly Cookie | JS 無法讀取 Cookie | 緩解 Session 劫持 | 不防禦 XSS 本身 |
若業務需允許部分 HTML (如粗體、連結),禁止黑名單過濾,必須使用白名單 HTML 淨化庫:
// 只允許 b, i, u, a, br
String safe = Jsoup.clean(userInput, Whitelist.basicWithImages());