<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            原文地址:http://drops.wooyun.org/web/10798

            0x00 引言


            首先聲明,這不是一個新洞,看過 Homakov 文章(最后附)以及譯文的人想必對這種漏洞有所了解。

            但原文寫的太過簡單(沒有說明利用條件、情景和特性),且譯文和我的理解略有偏差,于是就有了這篇文章。

            這種漏洞已經存在一段時間了,有沒有被利用過尚不得知,雖然利用條件較苛刻,但是當符合條件的站點被攻擊后, 影響面和影響程度巨大,并且普通用戶不知如何清除, 可導致長期持續攻擊。

            2014年底的時候,這種漏洞的利用條件沒有現在苛刻(比如沒有Service-Worker-Allowed頭),一年過來 W3C 對規范優化了不少(包括安全方面), 相信不久的將來,很快會被標準更新所扼殺了。

            彌留之際,讓這個漏洞放點異彩吧。

            0x01 一切都從 serviceWorker 說起


            Service Worker是基于Web Worker的事件驅動的,他們執行的機制都是新開一個線程去處理一些額外的,以前不能直接處理的任務。對于Web Worker,我們可以使用它來進行復雜的計算,因為它并不阻塞瀏覽器主線程的渲染。而Service Worker,我們可以用它來進行本地緩存,相當于一個本地的proxy。說起緩存,我們會想起我們常用的一些緩存技術來緩存我們的靜態資源,但是老的方式是不支持調試的,靈活性不高。使用Service Worker來進行緩存,我們可以用javascript代碼來攔截瀏覽器的http請求,并設置緩存的文件,直接返回,不經過web服務器,然后,做更多你想做的事情。

            相信很多人看到這句已經明白了,通過 js 來代理瀏覽器 http 請求,也就是說通過執行 js 代碼來控制瀏覽器的請求, 很容易想到,利用 xss 來修改瀏覽器請求的返回內容。

            可怕的是,即便 xss 漏洞被修復了,攻擊仍然持續,并且滲透到攻擊范圍內的每一個 url。

            并且,當用戶察覺到攻擊,并且理解這種攻擊,進入chrome后臺(chrome://appcache-internals), 進行手動清除攻擊緩存,攻擊仍未失效!當然了,還是有辦法清除的,且無須用戶手工操作(下文會演示)。

            0x02 漏洞原理和演示


            serviceWorker 的官方標準文檔:http://www.w3.org/TR/service-workers/

            其操作可以參考:https://github.com/w3c-webmob/ServiceWorkersDemos

            首先 serviceWorker 只有在 https 頁面中才可以調用 regist。

            而 serviceWorker 需要 Promise 支撐,目前支持的瀏覽器如下:

            支持 serviceWorker 的瀏覽器:

            firefox 默認關閉 serviceWorker,可以通過 about:config 打開開關:

            支持 fetch 方法(抓包)的瀏覽器:


            開始嘗試攻擊:

            首先在 https 站點中找到一個 Xss,利用 Xss 注冊一個 serviceWorker.registration 實例:

            #!js
            navigator.serviceWorker.register(url).then(function(registration) {
              console.log(registration);
            });
            

            注意到有個未知參數 url,這個 url 就是拿來放我們的攻擊代碼(假設我們能上傳一個js到根目錄):

            #!js
            var url = '//victim.com/evil.js'
            

            有人說這太難了,往根目錄上傳 js 文件不可能,那么可以嘗試在子目錄/任何一個可能的目錄上傳js文件, 或者和 Homakov 一樣,利用 jsonp 接口來代替這個惡意 js 文件。

            serviceWorker.register 只支持請求文件返回頭的MIME類型為:text/javascript, application/x-javascript, application/javascript

            我們知道,jsonp 的 callback 經常是可控的,那么找到一個這樣可以寫代碼的 jsonp 難不難?

            Google it !

            點擊第一個鏈接:

            可以看到,以 taobao.com 為例,第一個 jsonp 接口就存在這樣的弱點:callback 可以寫入任意代碼。

            退一步說,只要能輸入 []!() 等幾個符號,就能構造任意代碼了。

            以往安全工程師修復 jsonp 接口的 xss 漏洞,都是將頁面的 mime 修改為 application/javascript, 或者將 callback 的參數中的html符號實體轉義,就覺得杜絕 xss 了,看來以后得換個修法了

            若 callback 僅僅代表一個函數名,何不只允許數字、字母和下劃線呢?

            往 “js/jsonp接口” 里寫入惡意代碼:

            #!js
            onfetch = function(e) {
              e.respondWith(new Response('任意內容',{
                  headers
                  ...
                });
              );
            }
            

            通過 onfetch 方法攔截 http 請求,并構造返回內容,比如返回:<script>alert(/xss/)</script>

            所有在 evil 路徑下的請求的內容都被篡改。


            讓我們本地測試還原一遍場景(注意:本地測試不需要 https):

            首先打開網站:

            打開正常頁面:

            這時候點擊被攻擊頁面,此頁面事先被注入了 XSS 腳本:

            可以看到,這時候 serviceWorker 已經成功注冊了

            刷新頁面,此時返回內容以及被修改了:

            這時候再看正常頁面,也被攻擊了:

            首頁也是相同的情況:

            關閉瀏覽器,再打開,依舊如此:

            0x03 優勢、局限性

            實際利用中,若弱點JSONP路徑中不存在網站業務,這個漏洞依然能發揮一定價值。

            比如:殺死該JSONP路徑以及其子目錄的全部接口,從而導致網站無法正常使用。

            0x04 中止及防范攻擊


            1. 如何中止攻擊

            從上文可以知道,即便 xss 被修復了或者消失了,攻擊依然生效,那么如何中止攻擊呢?

            作為一個普通用戶,首先嘗試打開 chrome://inspect/#service-workers 查看存活:

            的確可以看到被用作攻擊的 Worker,點擊 terminate 嘗試中止:

            可以看到以及被清理了,但是打開頁面,攻擊仍然存在!

            瀏覽器中打開F12,在console中輸入:navigator.serviceWorker., 可以看到有 getRegistration 和 getRegistrations 這兩種屬性。

            查詢文檔:https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerContainer/getRegistration

            嘗試獲取注冊器,并且調用注銷(由于用到 Promise,需要使用 then 調取結果):

            #!js
            navigator.serviceWorker.getRegistration()
              .then(function(registration) {
              registration.unregister();
            });
            

            這一次終于清除了。

            而對于網站方,如何清除所有攻擊呢?

            只要將“清除代碼”部署在一個未受感染的同域的頁面里,當用戶訪問過后,自然就清除了。

            2. 防范方法:

            1. Jsonp 接口的 callback 可以做白名單,或者只允許特定字符(比如數字、字母和下劃線)。
            2. Jsonp所在域不應該存在 XSS(一切類型),至少不應該存在業務頁面。
            3. 如果做不到2,Jsonp 所在 url 路徑下不應該存在網站業務。
            4. 域名內不應存在用戶可控的 js 文件。

            reference:

            <span id="7ztzv"></span>
            <sub id="7ztzv"></sub>

            <span id="7ztzv"></span><form id="7ztzv"></form>

            <span id="7ztzv"></span>

                  <address id="7ztzv"></address>

                      亚洲欧美在线