Automatic Deserialization in .NET Framework Remoting

This topic is specific to a legacy technology that is retained for backward compatibility with existing applications and is not recommended for new development. Distributed applications should now be developed using the  Windows Communication Foundation (WCF).

Remoting systems that rely on run-time type validation must deserialize a remote stream to begin using it and an unauthorized client might try to exploit the moment of deserialization. To help protect against this type of attack, .NET Framework remoting provides two levels of automatic deserialization, Low and Full. Low, the default value, protects against deserialization attacks by deserializing only the types associated with the most basic remoting functionality, such as automatic deserialization of remoting infrastructure types, a limited set of system-implemented types, and a basic set of custom types. The Full deserialization level supports automatic deserialization of all types that remoting supports in all situations.

Do not assume that controlling deserialization is the only security your application requires. In distributed applications, even a high degree of control over serialization does not prevent unauthorized clients from intercepting the communication and using it in some way, even if that is merely showing the data to others. Therefore, although the Low deserialization level provides some protection against certain types of attack based on automatic deserialization, you must still evaluate whether to use authentication and encryption to help protect your data. For details, see Security.

The following lists describe the .NET Framework remoting deserialization levels:

  • Low (default level)

    The default deserialization level in .NET Framework remoting supports deserialization of the following types:

    • Remoting infrastructure objects. These are the types required to make remoting work at a basic level.

    • Primitive types, and reference and value types that are composed of primitive types.

    • Reference and value types that are marked with the SerializableAttribute attribute but do not implement the ISerializable interface.

    • System-provided types that implement ISerializable and make no other demands outside of serialization.

    • Custom types that have strong names and live in an assembly that is not marked with the AllowPartiallyTrustedCallersAttribute attribute.

    • Custom types that implement ISerializable and make no other demands outside of serialization.

    • Types that implement the ILease interface and are not MarshalByRefObject objects.

    • ObjRef objects used for activation (to support client-activated objects); that is, the client can deserialize the returned ObjRef but the server cannot.

  • Full

    The Full deserialization level in .NET Framework remoting supports all other scenarios, including the deserialization of the following additional types:

    • ObjRef objects passed as parameters.

    • Objects that implement the ISponsor interface.

    • Objects that are inserted between the proxy and client pipeline by the IContributeEnvoySink interface.

    • Delegate types passed as parameters.

    • Objects that inherit from MarshalByRefObject passed as parameters.

    • ISerializable types passed as parameters.

    • Types stored in the GAC and not marked with the AllowPartiallyTrustedCallersAttribute attribute.

    If your application requires the use of remoting features that are available only at the Full deserialization level, you must provide the type of authentication and the level of encryption necessary to protect any resources that might be at risk by using these advanced features in remote scenarios.

You can set the deserialization level programmatically or by using an application configuration file.

Setting the Deserialization Level Programmatically

To set the deserialization level programmatically, pass the following property to the SoapServerFormatterSinkProvider object or BinaryServerFormatterSinkProvider object on creation. The remoting system then sets the value on the formatter when it is inserted into the sink chain. The following example demonstrates how to set the deserialization level to Full in a host application domain.

// Creating a custom formatter for a TcpChannel sink chain.
BinaryServerFormatterSinkProvider provider = new BinaryServerFormatterSinkProvider();
provider.TypeFilterLevel = TypeFilterLevel.Full;
// Creating the IDictionary to set the port on the channel instance.
IDictionary props = new Hashtable();
props["port"] = 8085;
// Pass the properties for the port setting and the server provider in the server chain argument. (Client remains null here.)
TcpChannel chan = new TcpChannel(props, null, provider);

Setting the Deserialization Level Using an Application Configuration File

To use a configuration file to set the deserialization level, you must explicitly specify the typeFilterLevel attribute of the <formatter> element. Although this is typically done on the server side, you must also specify this attribute to control the deserialization level for any channel on the client registered to listen for a callback. The following example explicitly sets the deserialization level to Low for both the SoapFormatter and BinaryFormatter in the application domain.

type="ServiceType, common" 
<channel ref="http">
<provider ref="wsdl" />
<formatter ref="soap" typeFilterLevel=Low />
<formatter ref="binary" typeFilterLevel=Low />

See Also

Community Additions