防范xss攻擊的核心在于對用戶輸入進行過濾和對輸出內容進行html實體轉義。具體做法包括:1. 輸入過濾作為輔助手段,可限制長度、使用白名單校驗、攔截危險字符;2. 輸出時必須進行html轉義,不同語言有相應處理庫如php的htmlspecialchars()、python的escape()、Javascript的dom操作、java的stringescapeutils;3. 對富文本內容使用html凈化庫如sanitize-html、html purifier、bleach,并設置標簽白名單,禁止危險屬性;4. 不信任任何用戶輸入,包括表單、url參數、Cookie等;5. 轉義應在拼接html時進行,而非存儲時;6. 注意框架中可能繞過轉義的操作如vue的v-html、react的dangerouslysetinnerhtml;7. 定期使用owasp zap或burp suite測試網站安全性。
防范XSS攻擊的關鍵在于對用戶輸入的內容進行合理過濾和轉義。XSS(跨站腳本攻擊)之所以常見,是因為很多網站允許用戶提交內容,比如評論、留言、昵稱等,而這些內容如果沒有經過處理就直接顯示在頁面上,就可能被惡意利用。
要有效防范,核心做法就是:所有用戶輸入都要做處理,所有輸出到HTML的內容都要轉義。接下來從幾個實際場景出發,講講怎么操作更安全。
輸入過濾:不是萬能,但不能沒有
很多人覺得只要限制用戶輸入的格式,就能防住XSS。其實這種方法不能完全依賴,但確實可以作為第一道防線。
立即學習“前端免費學習筆記(深入)”;
- 限制輸入長度:比如昵稱不超過20個字符,密碼必須符合一定復雜度。
- 白名單校驗字段:郵箱、網址、電話號碼等可以用正則表達式做基本校驗。
- 拒絕明顯危險字符:比如 <script>、JavaScript: 這類關鍵詞,可以在接收階段直接攔截。</script>
不過要注意,輸入過濾只是輔助手段,真正關鍵的是輸出時的處理。因為有些看似“合法”的內容,也可能被組合成攻擊代碼。
輸出轉義:真正的核心防線
無論輸入內容是否做過濾,只要它會被展示在網頁中,就必須進行HTML實體轉義。簡單來說,就是把特殊字符轉換成瀏覽器不會執行的形式。
比如:
- > 變成 >
- ” 變成 “
- & 變成 &
這樣即使用戶輸入了 <script>alert(1)</script>,也會被瀏覽器當作普通文本顯示,而不是執行這段腳本。
不同語言都有現成的庫來處理這個事情:
- PHP:htmlspecialchars()
- python:escape()(Jinja模板自動轉義)
- JavaScript:手動替換或使用DOM操作避免innerHTML
- Java:apache Commons Text的StringEscapeUtils.escapeHtml4()
如果你用的是現代前端框架,比如React、vue,默認是不執行動態內容的,也屬于一種保護機制。
富文本內容怎么辦?需要特別小心
有時候你確實需要讓用戶發布富文本內容,比如博客文章、帶格式的評論。這時候不能簡單地全部轉義,否則格式就被破壞了。
這種情況下,應該:
- 使用專門的HTML凈化庫,例如:
- Node.JS:sanitize-html
- PHP:HTML Purifier
- Python:bleach
- 設置標簽白名單,只允許安全標簽如
, ,
,并禁止內聯樣式和事件屬性(如 onload, onclick)
- 圖片標簽中的 src 屬性要做額外檢查,防止 javascript: 協議注入
一句話:富文本不是不能處理,而是要精細控制可接受的HTML結構和屬性。
基本原則記清楚,別掉坑里
最后再強調幾個容易忽視的點:
- 不要信任任何來自用戶的輸入,包括表單、URL參數、Cookie、http頭等。
- 轉義時機很重要:是在拼接HTML的時候,而不是存儲的時候。
- 框架默認有轉義機制,但也有可能被繞過(比如在Vue中用了 v-html,React中用了 dangerouslySetInnerHTML),這時候尤其要小心。
- 定期測試自己的網站,模擬XSS攻擊看能否成功,工具推薦 OWASP ZAP 或 Burp Suite。
基本上就這些。防范XSS聽起來復雜,其實只要在每個數據輸出的地方都加上一層轉義,大多數問題都能避免。