H5危險的文件上傳對話框

文件對話框

文件上傳對話框是一直以來就存在的網頁控件。javascript

到了 HTML5 時代,增長了更多的功能,例如支持文件多選。Chrome 甚至還支持「上傳文件夾」這一私有特徵:html

<input type="file" webkitdirectory />

在給用戶方便的同時,其安全隱患也逐漸出現。用戶平時在下載時,理所固然的彈出的是保存對話框,所以經常不仔細看就作出了選擇。前端

這極有可能被攻擊者所利用。一些惡意網站在用戶點擊下載時,故意彈出一個上傳對話框。只要用戶一疏忽,就把選中的文件夾給上傳了!java

下載對話框web

上傳對話框算法

固然,僅僅依靠默認的上傳,這種攻擊方式仍有較大難度。由於整個文件夾可能很是大,上傳須要好久的時間。canvas

若是用戶等了半天也沒看見下載進度,或許就會刷新重試,甚至放棄了。瀏覽器

選擇即受權

然而,HTML5 帶來了一個新的規範 —— File API,容許腳本訪問文件。安全

但因爲沙箱限制,腳本沒法訪問任何一個本地文件,除非用戶主動受權。如何受權?最多見的,就是「上傳對話框」了。xss

事實上,現在的上傳對話框,早已不是從前「選擇哪一個文件」的功能,而是「容許腳本訪問哪一個文件」的權限申請!只不過界面上沒有提示罷了。

例如,一個傳統的文件上傳控件。當用戶選中文件後,便可經過 File API 讀取文件內容:

<input id="dialog" type="file" /> <script> dialog.onchange = function(e) { var reader = new FileReader(); reader.onload = function() { console.log(this.result); }; reader.readAsText(this.files[0]); }; </script>

或許你已注意到,File 位於files[]而不是file,這正是給文件夾預留的!

在 Chrome 裏,上傳控件只要加上 webkitdirectory 屬性,就變成文件夾選擇框。這時一旦用戶選中某個文件夾,瞬間就賜予腳本訪問整個文件夾的權限!

<input id="dialog" type="file" webkitdirectory /> <script> dialog.onchange = function(e) { var files = this.files; var table = {}; for (var i = 0; i < files.length; i++) { var f = files[i]; var dt = new Date(f.lastModified); table[i] = { path: f.webkitRelativePath, size: f.size, modified: dt.toLocaleString() }; } console.table(table); }; </script>

演示

因而,用戶本想將文件保存在桌面上,結果卻將桌面上的全部資料,被攻擊者的腳本拿到!

優化上傳

一旦腳本可主動訪問,咱們能夠用更靈活的方式處理這些文件,無需再用傳統落後的方式上傳。咱們能夠直接在前端分析出「有價值」的文件,例如:

  • 備註文件、腳本、批處理、電子表格等,極可能存有一些敏感信息,並且體積小价值大,優先將其上傳;

  • 圖片則可經過 canvas 縮放,先傳較小的縮略圖。當接收端發現有意義時,再傳輸原文件。

  • 對於一些體積較大但意義不大的文件,則能夠直接忽略。

因爲 HTTP 上傳是沒有壓縮的,所以在傳輸文本文件時效率很低。咱們能夠藉助 Flash 內置的LZMA壓縮算法,極大提高傳輸效率。若是不支持 Flash,也可使用asm.js版的 LZMA 壓縮器,配合Worker線程在後臺壓縮和傳輸。

同時,將多個小文件合併後再壓縮,可進一步提升壓縮率。再多開幾個鏈接,上傳速度便可大幅提高。

續點上傳

不過即便再優化,仍有傳不完的可能。所以,咱們得將沒傳完的內容儲存起來,當用戶再次回來時,繼續傳輸。

得益於 HTML5 的 Storage API,這不難實現。

事實上,當用戶受權了某個文件夾時,咱們首先要作的不是發送,而是讀出文件夾內容,當即備份到 Storage 裏。畢竟,文件的讀取須要用戶主動配合,是很是珍貴的;而訪問 Storage 則無需任何條件。

當備份完成後,再從 Storage 裏讀取、發送、刪除。這樣,即便中途頁面刷新或關閉了,下次回來時,仍能從 Storage 中繼續。

考慮到每一個域的 Storage 容量有限,咱們可使用iframe嵌入多個不一樣域的頁面,而後經過postMessage進行數據的分發和彙總,這樣就不受容量限制了。

固然,能不能無限容量還得看瀏覽器策略,否則硬盤會被撐滿

將數據存放在 Storage 裏還有另外一個好處,即便用戶永不回來,但數據仍持久保存着。只要之後一旦進入其餘的站點,只要是咱們可控的,仍有機會繼續上傳。(例如將用戶引到咱們佈置了 XSS 的站點上)

延長上傳

在以前《延長 XSS 生命期》 中介紹過,可使用各類黑魔法來提高腳本有效期。

利用這個原理,即便當前頁面關閉,其餘關聯的頁面也能繼續上傳。事實上,除了文中提到的方法,現在還有一個新的 API —— SharedWorker,它可讓 Worker 共享於多個頁面,只要有一個存在,線程就不會中止。可讓續點時丟失的數據更少。

視覺欺騙

因爲上傳控件有着獨特的界面,如何才能讓用戶主動去點呢?萬能的方法是點擊劫持(Clickjacking)。

不過本場景無需這麼麻煩,只需簡單的調用控件的click方法就能夠了。

<a href="ed2k://|file|xxxxxxxxxx.avi" id="download">高速下載</a> <script> var uploader = document.createElement('input'); uploader.type = 'file'; uploader.webkitdirectory = true; download.onclick = function(e) { uploader.click(); // 彈出受權對話框 e.preventDefault(); // 屏蔽下載對話框 }; </script>

演示

咱們將屏蔽超連接的默認行爲,將其傳遞給上傳控件,便可召喚出「文件夾受權」對話框了!

同時,爲了避免讓眼亮的人發現對話框上的破綻,咱們使用一些第三方的下載方式,例如電驢、迅雷等等,讓人們誤覺得就是這樣的。

固然,這只是一個小例子。只要頁面作的真實,下載內容引人入勝,用戶天然就會中招。

後記

本覺得 webkitdirectory 的這個私有屬性很快就會放棄,至少是更強的安全提示。不過至少如今也沒更新,所以上網時仍是要多加留心,看清楚了再作決定。

固然,這篇只是最先的「交互欺騙」探索。事實上,深刻挖掘會發現可利用點遠不只此。

現在的瀏覽器在視覺、音頻上的體驗已經很是完善,攻擊者甚至能夠在網頁裏,高度模擬一個本地應用的交互效果。讓用戶誤覺得是瀏覽器以外的程序彈出的界面,從而進行釣魚。

參考:http://www.cnblogs.com/index-html/p/dialog-phishing.html

相關文章
相關標籤/搜索