一、如何預防XSS
XSS 攻擊有兩?要素:
-
攻擊者提交惡意代碼,
-
瀏覽器執?惡意代碼,
針對第?個要素:我們是否能夠在?戶輸?的程序,過濾掉?戶輸?的惡意代碼呢?
輸入過濾
在?戶提交時,由前端過濾輸?,然后提交到后端,這樣做是否可?呢? 答案是不可?,?旦攻擊者繞過前端過濾,直接構造請求,就可以提交惡意代碼了, 那么,換?個過濾時機:后端在寫?資料庫前,對輸?進?過濾,然后把“安全的”內容,回傳給前端,這樣是否可行呢?我們舉?個例子,?個正常的?戶輸?了 5 < 7 這個內容,在寫入資料庫前,被轉義,變成了 5 < 7 ,問 題是:在提交階段,我們并不確定內容要輸出到哪?,
這?的“并不確定內容要輸出到哪?”有兩層含義:
-
用戶的輸入內容可能同時提供給前端和客戶端,而?旦經過了 escapeHTML() ,客戶端顯示的內容就變成了亂碼(5 < 7),
-
在前端中,不同的位置所需的編碼也不同,
- 當 作為 5 < 7 HTML 拼接頁面時,可以正常顯示:
<div title="comment">5 < 7</div>
- 當 5 < 7 通過 Ajax 回傳,然后賦值給 JavaScript 的變數時,前端得到的字串就是轉義后的字符,這個內容不能直接?于 Vue 等模板的展示,也不能直接用于內容長度計算,不能?于標題、alert 等,
所以,輸?側過濾能夠在某些情況下解決特定的 XSS 問題,但會引?很?的不確定性和亂碼問題,在防范 XSS 攻擊時 應避免此類?法,
當然,對于明確的輸?型別,例如數字、URL、電話號碼、郵件地址等等內容,進?輸?過濾還是必要的,
既然輸入過濾并非完全可靠,我們就要通過“防止瀏覽器執行惡意代碼”來防范 XSS,這部分分為兩類:
-
防止HTML 中出現注入,
-
防止JavaScript 執行時,執行惡意代碼,
預防存盤型和反射型 XSS 攻擊
存盤型和反射型 XSS 都是在服務端取出惡意代碼后,插?到回應 HTML 里的,攻擊者刻意撰寫的“資料”被內嵌到“代碼”中,被瀏覽器所執行,
預防這兩種漏洞,有兩種常見做法:
-
改成純前端渲染,把代碼和資料分隔開,
-
對 HTML 做充分轉義,
純前端渲染
純前端渲染的程序:
-
瀏覽器先加載?個靜態 HTML,此 HTML 中不包含任何跟業務相關的資料,
-
然后瀏覽器執行 HTML 中的 JavaScript,
-
JavaScript 通過 Ajax 加載業務資料,呼叫DOM API 更新到頁面上,
在純前端渲染中,我們會明確的告訴瀏覽器:下面要設定的內容是文本( .innerText ),還是屬性 ( .setAttribute ),還是樣式( .style )等等,瀏覽器不會被輕易的被欺騙,執行預期外的代碼了, 但純前端渲染還需注意避免 DOM 型 XSS 漏洞(例如 onl oad 事件和 href 中的 javascript:xxx 等,請參考下?”預防 DOM 型 XSS 攻擊“部分), 在很多內部、管理系統中,采用純前端渲染是?常合適的,但對于性能要求?,或有 SEO 需求的頁面,我們仍然要面對拼接 HTML 的問題,
轉義 HTML
如果拼接 HTML 是必要的,就需要采?合適的轉義庫,對 HTML 模板各處插?點進?充分的轉義, 常?的模板引擎,如 doT.js、ejs、FreeMarker 等,對于 HTML 轉義通常只有?個規則,就是把 & < > " ’ / 這?個字 符轉義掉,確實能起到?定的 XSS 防護作?,但并不完善,所以要完善 XSS 防護措施,我們要使?更完善更細致的轉義策略, 例如 Java 工程里,常?的轉義庫為 org.owasp.encoder ,以下代碼引?? org.owasp.encoder 的官方說明,
<!-- HTML 標簽內?字內容 -->
<div><%= Encode.forHtml(UNTRUSTED) %></div>
<!-- HTML 標簽屬性值 -->
<input value="<%= Encode.forHtml(UNTRUSTED) %>" />
<!-- CSS 屬性值 -->
<div style="width:<= Encode.forCssString(UNTRUSTED) %>">
<!-- CSS URL -->
<div style="background:<= Encode.forCssUrl(UNTRUSTED) %>">
<!-- JavaScript 行內代碼塊 -->
<script> var msg = "<%= Encode.forJavaScript(UNTRUSTED) %>"; alert(msg); </script>
<!-- JavaScript 行內代碼塊內嵌 JSON -->
<script> var INITIAL_STATE = JSON.parse('<%= Encoder.forJavaScript(data.to_json) %>'); </script>
<!-- HTML 標簽行內監聽器 -->
<button onclick="alert('<%= Encode.forJavaScript(UNTRUSTED) %>');"> click me </button>
<!-- URL 參 數 -->
<a href="/search?value=<%= Encode.forUriComponent(UNTRUSTED) %>&order=1#top">
<!-- URL 路 徑 -->
<a href="/page/<%= Encode.forUriComponent(UNTRUSTED) %>">
<!--URL. 注意:要根據項?情況進?過濾,禁?掉 "javascript:" 鏈接、?法 scheme 等 -->
<a href='<%= urlValidator.isValid(UNTRUSTED) ? Encode.forHtml(UNTRUSTED) : "/404" %>'>link </a>
可?,HTML 的編碼是?分復雜的,在不同的上下??要使?相應的轉義規則,
預防 DOM 型 XSS 攻擊
DOM 型 XSS 攻擊,實際上就是?站前端 JavaScript 代碼本身不夠嚴謹,把不可信的資料當作代碼執行了, 在使用 .innerHTML 、 .outerHTML 、 document.write() 時要特別小心,不要把不可信的資料作為 HTML 插到??上, 而應盡量使? .textContent 、 .setAttribute() 等,
如果? Vue/React 技術堆疊,并且不使用 v-html 、 dangerouslySetInnerHTML 功能,就在前端render階段避免 innerHTML 、 outerHTML 的XSS隱患,
DOM 中的行內事件監聽器,如 location 、 onclick 、 one rror 、 onl oad 、 onm ouseover 等, 標簽的 href 屬 性,JavaScript 的 eval() 、 setTimeout() 、 setInterval() 等,都能把字串作為代碼運?,如果不可信的資料拼接到字串中傳遞給這些 API,很容易產?安全隱患,請務必避免,
<!-- 行內事件監聽器中包含惡意代碼 -->

<!-- 鏈接內包含惡意代碼 -->
<a href="UNTRUSTED">1</a>
<script>
// setTimeout()/setInterval() 中調?惡意代碼
setTimeout("UNTRUSTED")
setInterval("UNTRUSTED")
// location 調?惡意代碼
location.href = 'UNTRUSTED'
// eval() 中調?惡意代碼
eval("UNTRUSTED") </script>
如果項?中有?到這些的話,?定要避免在字串中拼接不可信資料,
其他 XSS 防范措施
雖然在渲染??和執? JavaScript 時,通過謹慎的轉義可以防? XSS 的發?,但完全依靠開發的謹慎仍然是不夠的, 以下介紹?些通?的?案,可以降低 XSS 帶來的?險和后果,
1.Content Security Policy
嚴格的 CSP 在 XSS 的防范中可以起到以下的作?:
-
禁止加載外域代碼,防?復雜的攻擊邏輯 ,
-
禁止外域提交,網站被攻擊后,用戶的資料不會泄露到外域,
-
禁止行內腳本執行(規則較嚴格,目前發現 GitHub 使用) ,
-
禁止未授權的腳本執行(新特性,Google Map 移動版在使用) ,
-
合理使?上報可以及時發現 XSS,利于盡快修復問題,
2.輸入內容長度控制
對于不受信任的輸?,都應該限定?個合理的?度,雖然?法完全防? XSS 發?,但可以增加 XSS 攻擊的難度,
3.其他安全措施
-
HTTP-only Cookie: 禁? JavaScript 讀取某些敏感 Cookie,攻擊者完成 XSS 注?后也?法竊取此 Cookie,
-
驗證碼:防?腳本冒充?戶提交危險操作,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/233598.html
標籤:其他
