在WEB前端開發的過程當中,因爲大量的URL和多處使用的傳遞參數,使得不少開發者常常會留下XSS的漏洞。在安全測試中一旦發現漏洞,必須給開發者開defect。Defect的優先級很是高,必須馬上解決。開發者每每爲了快速封堵當前漏洞,使用很tricky的方法。這樣子常常致使這邊漏洞堵上了,那邊漏洞又出現了。php
我在開發過程當中,總結了本身的一套方法。此方法能夠有系統的,一致性的解決XSS問題。本文所使用的開發環境爲簡單java和jsp平臺。對於其餘平臺,如php,c#,.net,此方法也可用。html
首先舉兩個前端常見的XSS的漏洞。前端
1, https://test.com.cn?name="><script>prompt('XSS Vulnerability')</script>java
若是JSP裏面有這麼一段代碼(本處使用了EL):node
<input value="${name}"/>
name參數中的值將會對input進行截斷,並聲稱script片斷,從而運行script。c#
2, https://test.com.cn?name=";alert("Hello");"安全
若是JSP中的JS有這麼一段代碼:jsp
<script>var name="${name}";</script>post
name參數中的值也會對其截斷。並運行alert。測試
下面講一下HTML的NCR標準
html使用了不合規範的unicode,也就是ncr標準,&#後面跟代碼點,就能夠被展示成相應代碼點對應的字符。若是使用unicode表達,使用document.createTextNode('\uxxxx').
或者在HTML頁面中直接使用&#xxxx.
例如,字的unicode是23383, 在html中,若是這樣寫:<label>字</label><input name="字" value="字"/>
又例如,>的unicode是62, 在html中,若是這樣寫:<label>></label><input name=">" value=">"/>
最終user agent在展現html以後,頁面將完全解析成爲 <label>></label><input name=">" value=">"/> 展現爲<label>></label><input name=">" value=">"/>
注意:這裏須要解釋。user agent在解釋html的時候,會有3個過程:
1, 把NCR替換成真正的字符, 2, 將某些替換好的字符再轉成HTML Entities.例如>將變爲>。3,將解析好的HTML進行展現。
這時候若是調用innerText(IE) 或者textContent(FF),將會獲得展現後的字符串。若是調用innerHTML或者outerHTML,將會獲得第2步解析後的字符串。
使用getAttribute().nodeValue永遠都是獲得的展現後的字符串。
將想要獲取的字符串轉爲NCR格式,保存於attribute之中,在展現後使用getAttribute().nodeValue從新獲取原字符串。
展現字符——》NCR——》(innerHTML) HTML entities——》(textContent/innerText/getAttribute)展現字符
使用NCR來解決XSS問題
1,建立一個tag,專門用來將全部的字符轉爲NCR。tag使用方法如: <ncr:transfer></ncr:transfer>
2,對於第一種XSS使用如下方法
<input value="<ncr:transfer>${name}</ncr:transfer>"/>
3,對於第二種XSS使用如下方法
<div id="test" style="display:none" value-name="<ncr:transfer>${name}</ncr:transfer>"/>
<script>var name=dojo.attr('test','value-name');</script>
這裏使用了dojo。dojo.attr(id, attribute)是取id對應的node中的attribute的值。
使用此方法,不用擔憂${name}裏面到底含有什麼值,\ ' " , ; < > & #全都不怕。此方法還解決了奇怪字符,和高位字符的亂碼問題。高位字符指codepoint大於2^16的字符。在UTF16中,須要用4個字節2個unit來表示。高位字符若是處理很差,在html端會顯示亂碼。使用NCR格式,可讓HTML正確顯示高位字符。