淘寶漏洞

 

昨天在網上游蕩看到一篇文章:淘寶跨站腳本漏洞。

看完整篇,作者主要的分析點在於javascript的編碼。目的在於如何將攻擊語句在頁面中還原,可執行。

但是最後該作者也沒有說出如何利用。

我覺得可利用的應該就是淘寶的域名了。

做法就是:將淘寶的鏈接http://search1.taobao.com/browse/0/n-g,lr4dgzk4pazwg2lnm4qhg4tdhvvgc5tbonrxe2lqoq5gc3dfoj2cqmjj-------2-------b--40--commend-0-all-0.htm?at_topsearch=1&ssid=s1-e中植入需要跨站的腳本代碼,然後將該url發給他人,他人點擊的時候會跳轉到目標網站,目標網站該幹嘛就幹嘛了!

附上原文:

 

fonix 寫道
(此漏洞廠商已解決)

緣起

我在公司是做應用安全的,平時主要關注於“防”。由於工作繁忙,少有時間來嘗試攻擊別人的系統。但是攻防本一家,做了那麼多防治安全問題的解決方案,也該試試手,把防護經驗用在攻擊中,看看效果如何?

第一個問題,進行什麼類型的攻擊?時間有限,已經是深夜了,爲了節省時間,還是選跨站腳本注入吧。遍地都是XSS,哪個上規模的網站上沒有XSS問題反倒怪了。第二個問題是,選什麼網站?XSS漏洞分佈廣,攻擊門檻低,爲了保證有一定的挑戰性,我選擇了淘寶。第三個問題,攻擊哪個頁面的哪個字段?簡單起見,就選擇首頁的第一個輸入框,商品搜索。

好,動手。我打開IE來到淘寶。

投石問路

首先,我在商品搜索框中輸入swx<>&"'。其中字串swx是爲了方便在頁面輸出中查找注入的內容,後面的幾個亂字符,則是HTML中可能會引起跨站腳本的常見敏感字符。點擊搜索,結果頁面出來了,沒有什麼語法或者顯示上的錯誤。有一個現象,就是頁面的標題,以及頁面最上方的搜索框裏面,搜索關鍵字已經變成了swx<>&"',除小於號之外的四個字符都被HTML編碼了。這說明開發人員有點心虛,或者缺乏統一的編碼解決方案,導致在不同的地方編碼了兩次,多餘了,不影響安全,但是改變了用戶的搜索關鍵字。

第一步注入沒有明顯結果很正常,只是扔幾個怪字符過去,探探路而已。第二步要做的事情是分析HTML的源代碼,看看我們給的那幾個探路的字符,到了敵人那裏下場如何?

蛛絲馬跡

選擇View Source,打開HTML源代碼,然後搜索swx關鍵字,UltraEdit顯示有71處發現,還好不算太多,一個一個看。基本上,注入的那幾個特殊字符在頁面的各處都被施加了HTML編碼,包括head裏面、HTML body裏面、JavaScript字符串值裏面等等。有些地方還確實被HTML編碼了兩次,如前面所推測。

值得注意的是,單引號則始終沒有被編碼,這是唯一保持原樣的字符。但是因爲頁面的開發人員在HTML裏面和JavaScript裏面始終使用雙引號來包住字符,單引號無法逃出雙引號構成的牢籠,也就不能產生語法意義了。

其實直接輸入HTML標籤的跨站腳本攻擊,比如<script>alert(1)</script>,成功的可能性比較小,除非目標網站太爛了。一般只要開發人員稍微考慮一下安全問題,都會把<>這樣最基本的危險字符幹掉。

頁面裏用的都是HTML編碼,包括JavaScript代碼裏面也是。而JavaScript編碼似乎被忽略了,所以我把目光移向JavaScript裏面注入的那段內容:

var word = "swx<>&"'";

單引號無辜的呆在那裏,似乎在等待援軍。看來得嘗試更多的特殊字符,目標,JavaScript。

掩護

第二波,我只輸入了一個反斜槓字符\。反斜槓是JavaScript裏面字符串常量非常重要的一個字符,也就是編碼字符。因爲JavaScript字符串可以用被單引號或者雙引號括起來的,並且只能是單行的。但是如果字符串的內容本身就需要包含引號或者換行符怎麼辦?這時就需要進行編碼,比如雙引號可以被編碼爲\x22或者\"。其中22是雙引號的ASCII編碼值的16進制形式。

在商品搜索欄輸入\。點擊搜索按鈕,出問題了。結果頁面中有JavaScript語法錯誤:Unterminated String Constant,未結束的字符串常量。

Bingo!

其實這麼簡單的case淘寶沒有測試到,實在是不應該。一個簡單有效的測試做法是,往輸入框裏扔上一堆亂字符~`!@#$%^ *()_+-={}|[]\\x22:”;’<>,.?/*,如果在結果頁面中,這些字符都能原樣的顯示在界面上,沒有任何語法報錯或者頁面顯示上的異常,那麼基本上可以說跨站腳本的可能性就比較小了,包括SQL注入漏洞也順帶的被驗證了。

第二次注入嘗試後,HTML代碼裏是這樣的:var word = "\";。顯然,反斜槓兄弟成功打入敵人內部。後面緊跟着的雙引號和反斜槓變成了一個整體的編碼\",雙引號被喫掉了,從而原來用以包住字符串的一對引號只剩下了前一個,所以頁面報“未結束的字符串常量”錯誤。正因爲反斜槓的特殊性,任何字符都可以被它所編碼。任何字符,當然也包括大於號小於號這一對XSS攻擊最基本的字符。

現在,我們試一下,利用JS的這個字符編碼機制,讓反斜槓掩護剛纔被幹掉的大於號、小於號和雙引號字符潛入到word變量的值裏面,一旦這三個字符可以潛入敵後,那麼腳本執行也就有了希望。我們想賦給word變量的值是<>",用反斜槓編碼掩護之後,變成\x3c\x3e\x22,注意,這裏之所以用16進制ASCII碼的編碼方式,是因爲\"這樣的編碼中雙引號還是以明文出現,會被Web服務器上的編碼邏輯發現並幹掉。而\x22看起來就非常像良民,逃過檢查的可能性比較大。

輸入\x3c\x3e\x22,點擊搜索,然後在結果的HTML文本里查找word =得到:

var word = "\x3c\x3e\x22";

三個特殊字符可以注進去,這意味着,現在我們已經可以在word變量的值裏面任意寫HTML標籤代碼,比如類似<script>alert(1);</script>這樣的。另一個有價值的發現,就是把頁面卷屏到一半的位置時,屏幕右方的顯示出現混亂,本來應該是有問題就打聽一下的欄目標題,變成了" target="_blank">有問題就打聽一下,說明HTML語法已經被破壞。JS異常和頁面顯示錯亂都很可能意味着XSS,因爲這兩個現象都說明輸入的特殊字符已經起了某些語法上的作用,而不僅僅是當做字符顯示或者保存在HTML中。

偵查

存在跨站腳本注入漏洞的可能性看來很大,但是爲了構造有效的攻擊字串,我們需要跟蹤分析word變量的使用。通過View Source Code,查找跟蹤word變量的值的傳播和使用路徑,得到以下代碼,註釋是我加的 (網站開發人員可不會主動在註釋裏面寫明漏洞):



// 注入內容原樣出現在JS代碼的字符串常量中,但是在賦值給word時

// JS引擎會進行解碼,所以word變量的值是<>"三個字符

var word = "\x3c\x3e\x22";



//word變量的值直接拼到了moreDating後面,是個URL

var moreDating="http://dating.xxx.com/search_question.htm"+"?q="+word;



var _hebin = function(a, b){

...

if (a != 0) {...}

_html += '...美容達人心得榜</a></div>';

else {

// moreDating URL直接作爲<a>標籤的href屬性值

// 顯然,這裏只要moreDating變量的值包含一個小於號(已經有了!)

// 就可以強行終止<a>標籤,然後後面就可以自由書寫自己的腳本標籤了

_html += '<div class="Title"><a href='+moreDating+' target="_blank">有問題就打聽一下</a></div>';



}



if(a>0||b>0){

layer.innerHTML += _html;

}



閱讀過這段代碼,基本上可以確定跨站腳本攻擊的整個流程是通的。用戶可以輸入經過JS編碼的HTML標籤,然後被解碼並存儲到word變量,word變量又被拼接到moreDating這個URL的後面作爲參數,而moreDating在滿足特定條件(a等於0而b大於0)時,會被拼裝到HTML裏面去,並輸出到頁面。

_hebin這個函數在什麼條件下會被觸發?粗略讀了一下代碼之後,發現邏輯不是很清晰。算了,先不浪費時間來研究這個。讓事實說話吧。

發動

上一節的那段代碼轉了兩道彎,實際上可以等價簡化爲下面這樣:

<a href=http://.../?q= +word+ target="_blank">。其中word變量的前後分別被拼上了一小段HTML代碼,然後被輸出到頁面。如果我們能通過適當設置word的值,讓這一行代碼變成下面這樣:

<a href=http://xxx/?q=><img src=javascript:alert(1) target="_blank"> 那麼JS腳本就會被執行了。大家也許發現後面那個看起來多餘的target=,這其實不要緊,只是給HTML標籤賦予一個無意義的屬性值。上面字串的中間黑體字部分就是word變量應當具有的值,但是我們不能直接輸入它,那樣會被HTML編碼邏輯捕捉到。把這個值用JS編碼過後,就可以躲過HTML編碼,得到我們需要輸入的搜索關鍵字的值爲:

\x3e\x3cimg src=javascript:alert(1) 我把這段文本拷貝出來,貼到商品搜索輸入框,點擊搜索按鈕。等了幾秒鐘後,“當”的一聲響,警告框彈了出來。成功了。對應上面的搜索關鍵字的URL是:http://search1.taobao.com/browse/0/n-g,lr4dgzk4pazwg2lnm4qhg4tdhvvgc5tbonrxe2lqoq5gc3dfoj2cqmjj-------2-------b--40--commend-0-all-0.htm?at_topsearch=1&ssid=s1-e

直接訪問這個URL,也會彈出警告框。用這個漏洞可以幹些什麼?那就看讀者的想象力和JavaScript編程的功力了。

後來經過驗證,這個攻擊在FireFox裏沒有效果,只有在IE裏可以彈出對話框。具體原因我也懶得去深究了。實際攻擊時也沒有上面寫的這麼順利,我先試<script>標籤,注入了但是沒執行,再試<a οnmοuseοver=,可以執行,但是onmouseover觸發不好用,最後試<img src=才獲得了理想的結果。另外,注入的腳本要生效還有一個條件(大概是,不完全確定),就是輸入的關鍵字,在“打聽一下”裏面必須要能搜到結果,並且在“美容達人心得榜”裏面必須搜不到結果,只有在這兩個條件都滿足時,“打聽一下”的界面纔會顯示出來,從而注入JS纔會被實際插入到頁面的HTML代碼裏並觸發執行。如果想嘗試用其他的注入語法或者注入其他的JS語句,這個問題需要注意一下。

回顧

淘寶的開發人員在頁面裏只使用了HTML編碼,並且只編碼了<>&"這幾個最常見的特殊字符,這是上面這個漏洞的主要原因。這似乎也是一個在Web開發安全編程中比較常見的誤解。其實要全面防治跨站腳本,僅僅對這個幾個特殊字符進行HTML編碼是遠遠不夠的,JavaScript、URL、CSS、字符集、Web服務器、瀏覽器環境等等,任何一個環節的疏漏,都可能會引起跨站腳本注入問題。而需要編碼的可能有危險的字符,當然也遠遠不止那幾個。

一個廣泛推薦的做法是,使用白名單進行字符編碼。白名單的意思就是說,除了字母數字這些個無論何時也沒有特殊語法含義的普通字符之外,其他所有的特殊字符都進行編碼。假如淘寶的開發人員採用了白名單編碼方法,就算他們沒有意識到JavaScript需要自己特有的編碼邏輯,也可以防治前面演示的攻擊。因爲反斜槓會被HTML編碼爲\,導致var word = "\x3c\x3e\x22";會變成var word = "\x3c\x3e\x22";。反斜槓在JS代碼裏消失了,大於號等字符被僞裝,但是再也脫不下僞裝,無法還原並實施攻擊了。

對於那些邏輯簡單的網站,白名單方式的HTML編碼算是比較簡單有效的跨站腳本解決方法。但是要徹底解決問題,尤其是對於功能複雜,有大量混合使用JavaScript、HTML標籤、事件處理等語法元素的Web應用程序,如果不做好正確的、足夠的編碼,僅僅依賴於白名單方法,畢竟不是正道,總還是有缺陷的。下面就有個例子。

一點引申

<script>function showDetails(param) {}</script>

<body οnlοad="showDetails('');alert('1')">Tom</body>

這是一段HTML代碼,粗體字部分是用戶輸入的一些數據,已經被進行了白名單方式的HTML編碼,也就是說所有的特殊字符都被編碼了。但是這裏面還會存在跨站腳本問題嗎?讀者可以把這段代碼另存到一個HTML文件裏面,用瀏覽器執行試試看結果,想想爲什麼。如果有機會,再和大家多談談跨站腳本攻防的話題。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章