最近在看《白帽子講Web安全》這本書,對于XSS有了一定的了解?,F在對于書中關于防御XSS的4種方法做一些總結與解說。
XSS的本質
XSS事件發生在網站前端,在相關的數據替換到前端頁面中時,新舊數據結合,混淆了頁面原本的語義,產生了新的語義。以下面這種情況為例:
<a href="$var">test</a>
將$var的值注入到頁面中,本來是為了提供一個跳轉用的url地址。但若將$var的值設為" onclick=alert(1)\,則以上HTML變為了:
<a href="" onclick=alert(1) \">test</a>
點擊test文字后,會進行alert輸出,即改變了原有的HTML語義。
HtmlEncode
當$var變量出現在HTML標簽或屬性中時,XSS可分別通過以下兩種方法來進行注入。
- 在HTML標簽中,如下所示:
<p>$var</p>
若不對$var進行任何處理,當$var的值為<script>alert(1)</script>時,在一些老式的瀏覽器中,HTML代碼如下:
<p><script>alert(1)</script></p>
則這些瀏覽器會執行alert的js操作,實現了XSS注入。
- 在HTML屬性中,如下所示:
<p name="$var">test</p>
若不對$var進行任何處理,當$var的值為"> <script>alert(1)</script>時,HTML代碼如下:
<p name=""> <script>alert(1)</script>">test</p>
則瀏覽器會執行alert的js操作,實現了XSS注入。
為了防御這兩種XSS,可以采用對$var變量進行HtmlEncode的方法。HtmlEncode的作用是將$var的一些字符進行轉化,使得瀏覽器在最終輸出結果上是一樣的,但能夠防止注入的JavaScript執行。
HtmlEncode支持的轉換舉例如下:
& --> &
< --> <
> --> >
以
<script>alert(1)</script>
為例,對$var進行HtmlEncode后的結果為:
<script>alert(1)</script>
以上HTML在瀏覽器中的顯示結果就是<script>alert(1)</script>,實現了將$var作為純文本進行了輸出,且不引起JavaScript的執行。
JavaScriptEncode
當$var變量出現在<script>標簽內或其它JavaScript的執行環境中時,XSS可通過以下方法來進行注入,示例如下:
<script>
var x = "$var";
</script>
若不對$var進行任何處理,當$var的值為";alert(1);"時,JavaScript代碼如下:
<script>
var x = "";alert(1);""
</script>
則瀏覽器會執行alert的js操作,實現了XSS注入。
為了防御這種XSS,可以采用對$var變量進行JavaScriptEncode的方法。JavaScriptEncode的作用可以是將$var中除了數字、字母外的所有字符進行十六進制化處理,使得瀏覽器最終輸出結果上是一樣的,但能夠防止注入的JavaScript執行。
以
";alert(1);"
為例,對$var進行JavaScriptEncode后的結果為:
\x22\x3balert\x281\x29\x3b\x22
其中\x28代表(,\x29代表),以上字符串在JavaScript環境中即為"alert(1)",內容不變,但XSS并不執行。
CSSEncode
當$var變量出現在<style>標簽內或其它css的執行環境中時,XSS的注入和防御原理同JavaScript。在此不累述了。
css中xss的注入,在現在的瀏覽器中基本已經被禁止了,因此也比較少見。
URLEncode
當$var變量出現在url跳轉地址中時,XSS可通過以下方法來進行注入,示例如下:
<a >test</a>
若不對$var進行任何處理,當$var的值為" onclick="alert(1);return false;"時,代碼如下:
<a onclick="alert(1);return false;">test</a>
此時就會阻止了url頁面跳轉,實現了XSS注入。
為了防御這種XSS,可以采用對$var變量進行URLEncode的方法。URLEncode的作用是將字符轉化為%HH的形式,支持的轉換舉例如下:
空格 --> %20
< --> %3c
> --> %3e
以上述的
" onclick="alert(1);return false;"
為例,URLEncode后的結果如下:
%22%20onclick%3d%22alert%281%29%3breturn%20false%3b%22
原有代碼變為:
<a >test</a>
此時便阻止了XSS的注入。
如果上述例子改為:
<a href="$var">test</a>
即$var指代了完整的url地址,則可能出現以下兩種情況:
<a href="javascript:alert(1)">test</a>
<a href="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTs8L3NjcmlwdD4=">test2</a>
這兩種代碼都能夠注入XSS,為了防御這些情況,可以先檢測$var中是否包含url的protocol字段,如果沒有,就加上,再對整個url進行URLEncode處理。
結語
以上是我的一些經驗與心得,若有不足之處,請予指正。希望這篇文章對你有所幫助_。