一個可大規模悄無聲息竊取淘寶/支付寶賬號與密碼的漏洞 -(埋雷式攻擊附帶影片演示)

wyzsk發表於2020-08-19
作者: gainover · 2014/04/17 10:59

0x00 說在前面的話


下面是一段如何利用flash xss rookit漏洞來竊取淘寶/支付寶帳號密碼的演示影片,當前漏洞已經修復

由於影片網站上傳的均不給透過,只好給出一個URL了:

http://static.wooyun.org/files/taobaoxss.swf

網速好的可以下載並觀看清晰版本:

http://static.wooyun.org/files/taobaoxss.wmv

2月底我們PKAV團隊在烏雲(http://www.wooyun.org/index.php)上向阿里(淘寶/支付寶)報告了該漏洞,漏洞的標題看起來有點恐怖,但它絕對不是“標題黨”。 烏雲的漏洞稽核人員在看了漏洞中的影片演示後,為其附加了一個生動又有一點霸氣的名字:"埋雷式攻擊"。

為何叫埋雷呢?本文中也會給出具體的解釋。

當時阿里推出了5W的獎勵計劃,有人問我這個漏洞為什麼不上報asrc(阿里巴巴漏洞應急響應中心),報烏雲沒獎勵的。

我給出的答覆是:“ 思路靈感都是烏雲來的,自當報還之”。

本人乃至本團隊,還是更喜歡並贊同烏雲上這種透明的機制,從我們自身角度來講能學習到不少,從使用者角度來講,至少可以讓使用者知道發生過什麼,怎麼保護自己 (試想,如果本文中的漏洞曾被駭客拿來竊取過使用者帳號與密碼,然後某天廠商修復了,使用者並不知道曾經有這個漏洞發生過,也不知道自己密碼是如何被盜的)。

從廠商角度來講:Oh shit! 不要拿漏洞恐嚇使用者!

下面帶大家一起來感受一下,這個來自烏雲,又迴歸烏雲的漏洞歷程。

0x01 第一次漏洞報告


這個有意思的漏洞最初在烏雲上由白帽子neobyte報告( WooYun: 一個flash的0day導致的淘寶網儲存xss(可形成永久後門) ),該漏洞描述了在一些FLASH應用中,因使用Local Shared Object (以下簡稱LSO)與ExternalInterface.addCallback而導致的一類XSS漏洞。由於此前並沒有見到類似的報告,從開發人員角度來說,並不會 十分去注意並防禦此類漏洞。我們來看看,在開發人員的角度,透過js與as的互動來實現讀取FLASH本地快取功能的流程圖:

enter image description here

在這個示意圖中,紅色的箭頭表示函式的呼叫,藍色的箭頭表示使用者資料的流向。普通的開發人員僅僅在意功能是否完整的實現;帶有一些安全意識的開發人員會注意到,jsGetData所獲得的資料需要經過過濾再進入DOM, 如果沒有考慮這點會造成什麼安全問題呢?烏雲上的p.z大神也給我們舉了一個好例子( WooYun: 淘寶某處儲存型XSS漏洞 ); 但是現在,我們將會遇到一個最糟糕的情況:“不論你是否是一個有安全意識的程式設計師,你都十分可能掉入這個坑中!”。

這是一個什麼樣的坑呢?

我們得先更深入瞭解下javascript呼叫FLASH所提供的函式介面時,到底做了哪些事情。下圖描述了當我們呼叫jsGetData函式來獲取FLASH本地快取資料的呼叫過程:

enter image description here

上面是一個正常獲取資料的流程,假設LSO中存放的資料是AAAAAAAAAAAA,最終,我們的data變數的值也為AAAAAAAAAAAA,當然,這是理想狀態下的情況。

如果你對DOM XSS有一定了解,也知道eval是多麼evil!(不瞭解但有興趣的參見本人馬甲貼: WooYun: [騰訊例項教程] 那些年我們一起學XSS - 10. Dom Xss進階 [邂逅eval] ),那麼你一定不難想到下面的做法:將儲存在LSO中的資料做以下改變:

AAAAAAAAAAAA 返回資料過程中會執行: eval('"AAAAAAAAAAAA"');

如果我們將儲存的資料更換為:

#!javascript
AAAAAA";alert(1);//AAAAAA 

返回資料將執行:

#!javascript
eval('"AAAAAA";alert(1);//AAAAAA"');

可以看到,我們在eval的資料中插入了一個alert(1),當eval執行時,就會執行彈窗操作!(你也可以開啟F12的console,然後複製上面的程式碼執行試一試!

然而,上面只是我們假想的情況。實際上FLASH會對返回資料進行轉義操作,將雙引號 (") 轉義為反斜線+雙引號 (\"),即我們更改儲存的資料後,實際執行的是下面的程式碼:

#!javascript
eval('"AAAAAA\";alert(1);//AAAAAA"');

正是這個轉義,使得我們上面的想法泡湯了。但是,別灰心,FLASH對返回資料的過濾是存在問題的,雖然過濾了雙引號 ("),但是FLASH並沒有過濾反斜線 (\),我們只需將上面的程式碼稍加修改,如下:

#!javascript
AAAAAA\";alert(1);//AAAAAA 

返回資料將會是以下的情況:

#!javascript
"AAAAAA\\";alert(1);//AAAAAA"

隨後返回內容進入eval被當作指令碼執行。

eval('返回內容');

其中雙引號 (")被轉義為反斜線+雙引號("),但是該反斜線卻被我們新增的反斜線所轉義。

//如果你想在控制檯測試效果,可以執行以下程式碼

#!js
eval('"AAAAAA\\\\";alert(1);//AAAAAA"');

//-- 此處由 @piaca 指出並更正描述,由於實際內容寫成字串時,反斜線需要被寫成轉義形式。

小總結:到了這裡,我們可以知道的是,如果我們可以在LSO中儲存惡意資料,當HTML頁面中透過javascript呼叫jsGetData函式,繼而透過actionscript中的asGetData函式, 從Flash本地儲存中讀取該惡意資料時,就會觸發我們的惡意程式碼。

接下來的問題,我們如何往LSO中新增我們的惡意資料呢?最暴力的方法是,搶你電腦,拔你網線,拆你硬碟,而後改之!,&@……!%&!%@ ... 溫柔,一定要溫柔!

在我們的第一個圖中,開發人員同樣為我們實現了

jsSetData -> asSetData -> LSO

的流程,也就是說,我們可以透過Javascript呼叫jsSetData來實現修改LSO中的資料。從功能角度上是這麼設計的,然而出於安全考慮,FLASH所提供的外部函式介面,並不是什麼時候都可以呼叫的,在預設情況下,只有http://A.com的網頁檔案才能呼叫http://A.com下的FLASH檔案所提供的函式介面,如下圖:

enter image description here

這樣看來,其實在預設的安全設定下,我們並沒有直接的辦法來修改資料。此外,每個域名下FLASH檔案所使用的快取是獨立的,因而正常情況下,我們也無法使用http://B.com的FLASH檔案來修改http://A.com下的FLASH快取(不排除有猥瑣的辦法哦~)。

然而,這種”js讀寫FLASH快取“的功能模組,天生會要求有一種特性,就是寫一次,四處皆可用,從開發的角度來講,這是天經地義的事情,方便,很方便。於是乎,開發人員在程式碼中加上了下面這麼一句:

#!javascript
Security.allowDomain("*");

這一句程式碼的具體作用,可參見官方手冊(Flash CS4 Professional ActionScript 2.0)),簡單來說,這一句話,打破了我們上面所述的FLASH預設安全設定,使得任何域名下的網頁均可以呼叫A.com下FLASH檔案所提供的addCallback介面。

這樣一來,我們整個漏洞的原理圖就可以建立起來了:

enter image description here

這個圖箭頭比較多。當駭客建立了惡意頁面後,我們以受害者作為起點,當受害者訪問了惡意頁面後,會執行一系列操作,從而將惡意資料存入LSO中,這個過程,我們稱之為“埋雷”。哪裡會被“埋雷”呢?答案是很多地方:

譬如:

低階一點的:駭客A向你傳送一個連結,你點開了。

不知不覺一點的:當你到處點網頁的時候!

高階一點的:你看了一篇駭客寫的博文/日誌,或是有駭客給你的QQ空間日誌發表了一條留言或者評論,內容裡被植入了XSS程式碼(需結合QQ的XSS漏洞),你點開了。

再高階再不知不覺一點的:某天你QQ收到了一條禮物訊息(QQ空間禮物功能XSS可以攻擊任意指定QQ號碼使用者),或者是某天突然來了一個陌生人的QQ對話方塊(微博上正在瘋傳的那個QQ客戶端聊天就中的XSS(可登陸和控制他人賬號))。

總之,如果是有心而為之,你!,被埋雷的可能性非常大。

當受害者被埋下雷之後,受害者再次訪問目標站(比如本次漏洞中的淘寶,或者是支付寶),駭客所埋下的惡意程式碼就會被觸發,Bomb! 雷就爆炸了!當然,實際上駭客不大可能去惡作劇式的“Bomb!"的嚇你一跳,而是偷偷的,悄無聲息的利用這顆無聲的”雷“來竊取受害者的帳號與密碼。

看我敲了這麼多,發了這麼多張圖,你們覺得這個漏洞的潛在危害大麼?反正我覺得挺大的,再來看看廠商對neobyte提交漏洞的響應:

危害等級:中

漏洞Rank:8

確認時間:2013-10-12 16:44

是的,廠商似乎沒有感覺到這個漏洞的危害。

0x02 第二次漏洞報告


到了2013年10月24號,我已經可以檢視neobyte所提交的漏洞詳情,於是就對他所提交的這個漏洞進行了研究,由於自己對FLASH也推敲過一些,在明白成因之後,也下載了漏洞中所提到的那個存在缺陷的FLASH檔案(http://acjstb.aliyun.com/actionlog/flash/JSocket.swf)。以下是對方的修復程式碼:

#!as3
public function getlso():String{
    var _local1:SharedObject = SharedObject.getLocal("kj");
    var _local2:RegExp = new RegExp("[a-zA-Z]");
    if (_local1.data.key == undefined){
        return ("");
    };
    if (_local2.test(_local1.data.key)){
        this.setlso("");
        return ("");
    };
    return (_local1.data.key);
}

由於業務上,淘寶此處儲存在LSO的資料,並不需要字母,但是惡意程式碼中卻需要使用到字母,例如:alert。所以開發人員這裡加上了一個正則判斷:“如果所獲取的資料中存在字母,則返回空字串”。是的,看起來是被修復了,但是依然存在問題,一來,開發人員並沒有過濾掉真正導致潛在危害的反斜線(),二來,Javascript中呼叫函式完全可以不需要存在任何字母,納尼??一起來看看:

#!as3
//我們可以使用以下方式建立一個函式:
new Function("alert(1)");
//也可以不要new
Function("alert(1)")()
//可以將Function轉換下
"...".substr.constructor("alert(1)")()
//再轉換下
"..."["substr"]["constructor"]("alert(1)")()
//字串全部轉義
"..."["\163\165\142\163\164\162"]["\143\157\156\163\164\162\165\143\164\157\162"]("\141\154\145\162\164\50\61\51")()

這樣我們就實現了不需要字母即可執行alert(1)的目的。再利用在上一小節中所說的惡意程式碼構造技巧,我們只需將AAAAAAAAAAAAAA替換為以下程式碼:

#!javascript
...\"["\163\165\142\163\164\162"]["\143\157\156\163\164\162\165\143\164\157\162"]("\141\154\145\162\164\50\61\51")()//..

漏洞就這樣再次出現了,雖然當時已經想到這個漏洞用來釣魚的危害挺大,但是並沒有動力去做一個釣魚演示,並且漏洞剛被阿里修復不久,只是出於技術上的好意,想提醒開發人員完美的修復。於是,我“不好意思”的登上了我另外一個馬甲號,發了一個續集: WooYun: 一個flash的0day導致的淘寶網儲存xss 【續集】 。當時我給漏洞自評了8分,因為漏洞的原作者neobyte也只要了8分,我也沒敢多要。但是,對方竟然只給了我5分:

危害等級:中

漏洞Rank:5

確認時間:2013-10-24 14:19

0x03 第三次漏洞報告


恩,不得不說,為什麼還會有第三次呢?主要是因為上面這個5分!個人覺得,如果一個漏洞被修復後,又被繞過,這是更加嚴重的情況,怎麼說也不應該給5分,起碼也得6分是不!。這個5分大大刺激了我的“報復欲”,讓我想再次繞過他們的修復方案,然後做一個大規模的釣魚演示,讓他們知道這個絕對不能是5分!!!。但是呢,這一次他們的修復方案並沒有好的繞過方法! 雖然如此,隔三差五的,我還是會去研究研究,不怕賊偷,就怕賊惦記.......,直到有一天,我發現FLASH中的修復方案竟然被換掉了,並且,第一眼,我就看出這個換掉的方案又出現問題了。新的修復程式碼如下:

#!javascript
private function getlso():String{
    var _local1:SharedObject = SharedObject.getLocal("kj");
    var _local2:RegExp = new RegExp("[\\({]");
    if (_local1.data.key == undefined){
        return ("");
    };
    if (_local2.test(_local1.data.key)){
        this.setlso("");
        return ("");
    };
    return (_local1.data.key);
}

可以看到,正規表示式 _local2 僅僅過濾了 ( 和 { ,而前面也已提到,正確的過濾方法應該是過濾 \ 。經過前面2輪的洗禮,我覺得安全人員應該是知道\的危害了,為什麼還會出現過濾失誤呢?我在漏洞描述中也已經給出了以下猜測,後確認,答案是B。畢竟我也是寫了很多年前端的,RegExp這個坑在我曾經也數次掉入。

A. 響應漏洞的同學並沒看到我的修復建議並轉告開發同學。

B. 開發的同學,認為 [\\({] 是 \ , ( 和 } 的集合, 而實際上,RegExp方式建立正規表示式時,需要寫成 [\\\\({] ,原因是:\在字串裡是轉義符,在正則裡也是轉義符。

當然,還需要注意的是,這個正則,不允許(和{,那麼還可以執行javascript程式碼嗎?答案是可以的,如下:

#!javascript
location.href="javascript:alert%28129";

使用location.href來執行js,並且將其中的括號與花括號進行URL編碼。

嗯,這個漏洞就這樣再次出現了,這一次我可不想再得到那可憐的5分!於是花了時間寫了一個真實可利用的程式碼,並錄製了本文最開始的影片,撰寫了漏洞報告( WooYun: 一個可大規模悄無聲息竊取淘寶/支付寶賬號與密碼的漏洞 -(埋雷式攻擊附帶影片演示) )。阿里這次給出了15分,還是沒有給出我心中的20分。怎麼說呢,從使用者角度來講,它的危害肯定是值20分的,但是廠商並不總是站在使用者考慮問題的。

危害等級:高

漏洞Rank:15

確認時間:2014-02-26 10:25

0x04 對於開發人員


注意addCallback: 在Flash中使用addCallback向外部提供函式介面時,如果as中對應函式的返回值是String, Array, Object等型別,並且返回資料中有使用者可控的資料時,建議對返回值進行過濾操作,將反斜線()過濾掉。如果沒有進行過濾的話,則可能出現與( WooYun: QQ空間某功能缺陷導致日誌儲存型XSS - 14 )相類似的案例。這裡我就不給出具體的過濾程式碼了,相信一般的開發人員的as都比我寫的好,以下是虛擬碼:

#!javascript
function asFunction():String{
     var data:String="xxx某些使用者可控資料xxx";
     var obj:Object={"name":"使用者可控資料"};
     ....
     data = 過濾(data);
     obj = 遍歷過濾(obj); 

     return data; 或 return obj;
}

勿濫用*|*Security.allowDomain("*"): **不是非常、極其、十分需要的情況下,建議將allowDomain限定在指定的域名下面,而不要為了方便而使用*。因為使用*,可能還會導致其它安全問題。

0x05 對於普通使用者


由於這類漏洞十分隱蔽,目前應該沒有安全軟體能防禦此類攻擊。鑑於絕大部分廠商並不會“舉一反三”的修復同類問題,我們不能完全指望廠商,安全還得靠自己。如果我們儘可能的定期清理Flash player快取,理論上會大大降低此類漏洞造成的危害。

Flash的本地快取一般存放在一個叫做 #SharedObjects的目錄中,如果有使用Everything這款搜尋工具的網友,可以使用Everything查詢所有#SharedObjects目錄,然後這些目錄下的目錄(8位的數字/字母組成)下的內容進行刪除處理。(當然,刪除#SharedObjects目錄下資料,可能導致一些FLASH遊戲或者FLASH應用的資料需要重新下載,但是相比之下,安全更重要。)

如果你沒有使用Everything,下表列出了IEchrome中Flash的快取目錄所在,找到對應目錄進行清理即可,其它瀏覽器使用者,如360***|||||*,搜狗,可自行搜尋C盤下SharedObjects目錄進行相應刪除操作。

IE瀏覽器

C:\Documents and Settings\使用者名稱 \Application Data\Macromedia\Flash Player\#SharedObjects (Win XP 系統)

C:\Users\使用者名稱\AppData\Roaming\Macromedia\Flash Player\#SharedObjects\ (Win 7)

Chrome

C:\Documents and Settings\使用者名稱 \Local Settings\Application Data\Google\Chrome\User Data\【使用者目錄】\Pepper Data\Shockwave Flash\WritableRoot\#SharedObjects (Win XP 系統)

C:\Users\使用者名稱 \AppData\Local\Google\Chrome\User Data\【使用者目錄】\Pepper Data\Shockwave Flash\WritableRoot\#SharedObjects (Win 7)

*【使用者目錄】可能是Profile+數字 或者 Default

常見的“衛士”軟體,自帶了垃圾清理功能,但是可能在預設設定中,並未開啟清理FLASH快取功能,所以需要使用者手動勾選“清理Flash player快取”。這裡以金山衛士為例:清理垃圾->其它常用軟體產生的垃圾檔案->Flash player快取。 但是該方法也許並不會完全清理乾淨,例如:並不會清理chrome瀏覽器的flash快取,因此還是建議使用以上方法手工清理。

0x06 說在後面的話


這個漏洞雖然標題是在說“竊取淘寶/支付寶的帳號與密碼”,有些人覺得反正不知道支付密碼,不要緊!但是這個漏洞所造成的潛在危害,並不是只有淘寶/支付寶帳號與密碼那麼簡單。試想,如果在淘寶的登入頁面上再結合一個QQ的xss漏洞,我們可以得到什麼資訊呢?淘寶/支付寶帳號、密碼,QQ帳號及QQ相關資訊(關於QQ的XSS可以做什麼,參見烏雲一哥jannock的  WooYun: 跨站指令碼-可以讓戰場離得更遠(淺談騰訊架構缺陷) ,這個2012年時候的情況,現在已經有所好轉,但是當前狀況似乎依然不是太好)。此外,由於淘寶/支付寶這類涉及現金的帳號,密碼等級往往十分高,可能會出現支付寶登入密碼同樣是QQ密碼的情況,所以這類密碼一旦洩漏,可能會涉及後續更嚴重的資訊洩漏。

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章