Chapter 13 – Building Secure Remoted Components

 

Retired Content

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

patterns & practices Developer Center

Improving Web Application Security: Threats and Countermeasures

J.D. Meier, Alex Mackman, Michael Dunner, Srinath Vasireddy, Ray Escamilla and Anandha Murukan
Microsoft Corporation

Published: June 2003

Last Revised: January 2006

Applies to:

  • Remoting (.NET Framework version 1.1)

See the "patterns & practices Security Guidance for Applications Index" for links to additional security resources.

See the Landing Page for the starting point and a complete overview of Improving Web Application Security: Threats and Countermeasures.

Summary: This chapter provides recommendations and guidance to help you build secure components that rely on the .NET Framework remoting infrastructure. The chapter covers security issues associated with components that use ASP.NET and the HttpChannel, and those that use custom executables and the TcpChannel. By hosting your remote components in ASP.NET, you benefit from the security features provide by ASP.NET and IIS.

Note   The .NET Framework 2.0 has introduced a new channel named IpcChannel limited to the same machine communication. This channel is more secure and delivers better performance than the TCP channel.

Contents

In This Chapter
Overview
How to Use This Chapter
Threats and Countermeasures
Design Considerations
Input Validation
Authentication
Authorization
Sensitive Data
Denial of Service
Exception Management
Auditing and Logging
Code Access Security (CAS) Considerations
Summary
Additional Resources

In This Chapter

  • Authenticating and authorizing callers
  • Preventing denial of service attacks against remote components
  • Implementing secure serialization
  • Protecting sensitive data

Overview

The Microsoft .NET Framework Remoting infrastructure has no default authentication or authorization mechanisms. However, if you host remote components with ASP.NET and use the HttpChannel for communication, you can use ASP.NET and IIS authentication and authorization services.

If performance is an issue, you might decide to use a custom host with the TcpChannel. You should only do so in trusted subsystem scenarios, where the range of possible callers is carefully controlled through out-of-band techniques such as the use of IPSec policies, which only allow communication from specified Web servers. With the TcpChannel, you must build your own authentication and authorization mechanisms. This is contrary to the principle of using tried and tested platform level security services, and requires significant development effort.

Note   The .NET Framework 2.0 now provides built-in support for authentication (identification/impersonation) and authorization for IPC and TCP channels. Therefore, you do not need to build custom authentication and authorization mechanisms when using .NET 2.0.

This chapter gives recommendations and guidance to help you build secure remote components. This includes components that use ASP.NET and the HttpChannel, and those that use custom executables and the TcpChannel. The typical deployment pattern assumed by this chapter is shown in Figure 13.1, where remote objects are located on a middle-tier application server and process requests from ASP.NET Web application clients, and also Windows applications deployed inside the enterprise.

Ff648645.f13thcm01(en-us,PandP.10).gif

Figure 13.1

Typical remoting deployment

In this common scenario, the remote component services requests from front-end Web applications. In this case, ASP.NET on the Web server handles the authentication and authorization of callers. In addition, middle-tier remote components are often accessed by Enterprise Windows applications.

How to Use This Chapter

This chapter discusses various techniques to design and build secure components that you communicate with using the .NET Framework remoting technology.

To get the most from this chapter:

  • Use in conjunction with Chapter 17, "Securing Your Application Server." Chapter 17 gives an administration perspective on securing a middle-tier remoting solution.
  • See "Checklist: Securing Remoting" in the Checklists section of this guide. This gives a summary of the security measures required to build and configure secure .NET Framework remoting solutions.

Threats and Countermeasures

To build secure solutions that use remoting technology, you need to know the associated threats. The top threats to components that use remoting are:

  • Unauthorized access
  • Network eavesdropping
  • Parameter manipulation
  • Serialization

Figure 13.2 shows these threats.

Ff648645.f13thcm02(en-us,PandP.10).gif

Figure 13.2

Main remoting threat

Unauthorized Access

Remote components that provide sensitive or restricted information should authenticate and authorize their callers to prevent unauthorized access. Weak authentication and authorization can be exploited to gain unauthorized access to sensitive information and operations.

Vulnerabilities

Vulnerabilities that make your remoting solution susceptible to unauthorized access include:

  • No application level authentication because a custom Windows service host is used
  • No IPSec policies to restrict which computers can communicate with the middle-tier application server that hosts the remote components
  • No role-based authorization
  • No file authorization to restrict access to remoting endpoints
  • Trusting IPrincipal objects passed from the client

Countermeasures

Countermeasures that may be implemented to prevent unauthorized access include:

  • Ensure that the front-end Web application authenticates and authorizes clients, and that communication to middle-tier application servers is restricted by using IPSec policies. These measures ensure that only the Web server can access the middle-tier application server directly.

  • Use ASP.NET to host remote components and use Windows authentication to restrict access to remote components.

    Note   In .NET 2.0, authentication and authorization is also supported for IPC and TCP channels, thus eliminating the requirement to use ASP.NET for hosting remote components.

  • Use the ASP.NET FileAuthorizationModule. This requires specific configuration and the creation of a physical file (.rem or .soap) to match the remoting endpoint.

  • Use role-based authorization to restrict access to remote components, remote component classes, and methods. This can be done by using URL authorization to control access to the remoting endpoint (.rem or .soap) or, at the class or method level, by using principal-permission demands.

  • Do not trust IPrincipal objects passed from the client unless the client is trusted. This is generally only the case if IPSec is used to limit the range of client computers.

Network Eavesdropping

With network eavesdropping, an attacker is able to view request and response messages as they flow across the network to and from the remote component. For example, an attacker can use network monitoring software to retrieve sensitive data. This might include sensitive application level data or credential information.

Vulnerabilities

Vulnerabilities that can lead to security compromises from network eavesdropping include:

  • Basic authentication used over an unencrypted communication channel
  • No transport level encryption
  • No application level encryption

Countermeasures

Countermeasures that may be implemented to prevent successful network eavesdropping attacks include:

  • Use transport level encryption such as SSL or IPSec. The use of SSL requires you to use an ASP.NET host and the HttpChannel. IPSec can be used with custom hosts and the TcpChannel.
  • Encrypt the request at the application level to provide privacy. For example, you could create a custom encryption sink to encrypt part of the entire message payload.

Parameter Manipulation

Parameter manipulation refers to the unauthorized modification of data sent between the client and remote component. For example, an attacker can manipulate the request message destined for the remote component by intercepting the message while it is in transit.

Vulnerabilities

Vulnerabilities that can lead to parameter manipulation include:

  • Messages that are not digitally signed to provide tamperproofing
  • Message that are not encrypted to provide privacy and tamperproofing

Countermeasures

Countermeasures that may be implemented to prevent successful parameter manipulation include:

  • Digitally sign the message. The digital signature is used at the recipient end to verify that the message has not been tampered with in transit.
  • Encrypt the message payload to provide privacy and tamperproofing.

Serialization

Serialization is the process of converting an object's internal state to a flat stream of bytes. The remoting infrastructure uses the serialization services of the .NET Framework to pass objects between client and server. It is possible for malicious code to inject a serialized data stream to your server in order to coerce it into performing unintended actions. For example, malicious client-side code can initialize an object that, when de-serialized on the server, causes the server to consume server resources or execute malicious code.

Vulnerabilities

The main vulnerability that can lead to successful serialization attacks stems from the fact that the server trusts the serialized data stream and fails to validate the data retrieved from the stream.

Countermeasures

The countermeasure that prevents successful serialization attacks is to validate each item of data as it is deserialized on the server. Validate each field for type, length, format, and range.

Design Considerations

Before you begin to develop remote components, there are a number of issues to consider at design time. The key security considerations are:

  • Do not expose remoted objects to the Internet.
  • Use the HttpChannel to take advantage of ASP.NET security.
  • Use the TcpChannel only in trusted server scenarios.

Do Not Expose Remoted Objects to the Internet

You should only host remoted objects on middle-tier application servers that are not directly accessible from the Internet, and that are only accessible from front-end Web applications and Web services. If you need to expose functionality provided by a remoted object to Internet clients, use a Web service to wrap the middle-tier object and expose the Web service to the Internet.

Use the HttpChannel to Take Advantage of ASP.NET Security

If security is your primary concern, use ASP.NET to host remoted objects. This allows you to take advantage of the authentication, authorization, and secure communication features provided by ASP.NET and IIS. For example, you can use Windows authentication and use SSL to provide privacy and for the integrity of requests and responses sent over the network.

Use the TcpChannel Only in Trusted Server Scenarios

If you use the TcpChannel with a custom host process for performance reasons, remember that no built-in authentication services exist.

For this reason, you should only use the TcpChannel in trusted server scenarios, where the upstream Web application or Web service authenticates and authorizes the original callers before it calls your middle-tier remoted components. To secure this scenario, use IPSec for machine-level authentication and secure communication. The IPSec policy should only permit traffic from the nominated Web server(s) to the middle-tier remote component host. This trusted server scenario is shown in Figure 13.3.

Ff648645.f13thcm03(en-us,PandP.10).gif

Figure 13.3

Remoting in a trusted server scenario

For more information about IPSec, see "How To: Use IPSec for Filtering Ports and Authentication" in the "How To" section of this guide.

Note   Because .NET 2.0 now provides built-in support for authentication (identification/impersonation) and authorization for IPC and TCP channels, you no longer need to build custom authentication and authorization mechanisms.

TcpChannel Considerations

If you use a custom executable host and the TcpChannel, and you cannot rely on an upstream Web application to perform client authentication and authorization, you have to develop your own authentication and authorization solutions.

As part of a custom solution you might decide to pass principal objects as method parameters or in the call context. You should only do so in a trusted environment to prevent malicious client-side code from creating an IPrincipal object with elevated roles and then sending it to your server. Your server implementation must be able to trust IPrincipal objects before using them for role-based authorization.

An alternative approach is to use the underlying services of the Security Support Provider Interface (SSPI). For more information about this approach, see MSDN article, ".NET Remoting Security Solution, Part 1: Microsoft.Samples.Security.SSPI Assembly," at https://msdn.microsoft.com/en-us/library/ms973911.aspx.

To provide secure communication when you use the TcpChannel, use IPSec or a custom encryption channel sink to encrypt the request data.

Input Validation

In trusted server scenarios in which remoting solutions should be used, front-end Web applications generally perform input validation. The data is fully validated before it is passed to the remoted components. If you can guarantee that the data passed to a remoted component can only come from within the current trust boundary, you can let the upstream code perform the input validation.

If, however, your remoting solution can be accessed by arbitrary client applications running in the enterprise, your remote components should validate input and be wary of serialization attacks and MarshalByRefObject attacks.

Serialization Attacks

You can pass object parameters to remote components either by using the call context or by passing them through regular input parameters to the methods that are exposed by the remote component. It is possible for a malicious client to serialize an object and then pass it to a remote component with the explicit intention of tripping up the remote component or causing it to perform an unintended operation. Unless you can trust the client, you should carefully validate each field item in the deserialized object, because the object parameter is created on the server.

MarshalByRefObject Attacks

Objects that derive from System.MarshalByRefObject require a URL in order to make call backs to the client. It is possible for the callback URL to be spoofed so that the server connects to a different client computer, for example, a computer behind a firewall.

You can mitigate the risk of serialization and MarshalByRefObject attacks with version 1.1 of the .NET Framework by setting the typeFilterLevel attribute on the <formatter> element to Low. This instructs the .NET Framework remoting infrastructure to only serialize those objects it needs in order to perform the method invocation, and to reject any custom objects that support serialization that you create and put in the call context or pass as parameters. You can configure this setting in Web.config or programmatically as shown below.

<formatter ref="binary" typeFilterLevel="Low" />

or

BinaryServerFormatterSinkProvider provider = new BinaryServerFormatterSinkProvider();
provider.TypeFilterLevel = TypeFilterLevel.Low;

Authentication

If your remote component exposes sensitive data or operations, it must authenticate its callers to support authorization. The .NET Framework remoting infrastructure does not define an authentication model. The host should handle authentication. For example, you can use ASP.NET to benefit from ASP.NET and IIS authentication features.

If you use a custom Windows service host, develop a custom authentication solution.

ASP.NET Hosting

The following guidelines apply if you use the ASP.NET host with the HttpChannel:

  • Turn off anonymous authentication in IIS.
  • Configure ASP.NET for Windows authentication.
  • Configure client credentials.
  • Increase performance with authenticated connection sharing.
  • Force clients to authenticate with each call.
  • Control the use of authenticated connections.

Turn off Anonymous Authentication in IIS

To ensure that callers are authenticated by IIS, make sure that your application's virtual directory does not support anonymous authentication. On Windows Server 2003, you should also ensure that .NET Passport authentication is disabled.

Since you have disabled IIS anonymous authentication, you can use any of the supported IIS authentication mechanisms to authenticate callers over the HttpChannel, for example Basic, Digest, and Integrated Windows. To avoid credentials being passed over the network and to take advantage of Windows 2000 security account and password policies, use Integrated Windows authentication.

Configure ASP.NET for Windows Authentication

Configure your application for Windows authentication with the following setting in Web.config:

<authentication mode="Windows" />

You cannot use Passport or Forms authentication because these require redirection to a login page.

Note   When you use Windows authentication, you are recommended to enable File authorization. For more information, see "Authorization" later in this chapter.

Configure Client Credentials

To successfully communicate with a remote component that is configured for Windows authentication, the client must configure the remoting proxy with the credentials to use for authentication. Failure to do so results in an access denied error.

You can configure the use of default credentials to use the client's current thread or process token, or you can set explicit credentials.

Using Default Credentials

To use the client's process token (or thread token if the client thread is currently impersonating), set the useDefaultCredentials property of the client proxy to true. This results in the use of CredentialsCache.DefaultCredentials when the client receives an authentication challenge from the server. You can configure the proxy either by using the configuration file or programmatically in code. To configure the proxy externally, use the following element in the client configuration file:

<channel ref="http client" useDefaultCredentials="true" />

To set default credentials programmatically, use the following code:

IDictionary channelProperties;
channelProperties = ChannelServices.GetChannelSinkProperties(proxy);
channelProperties ["credentials"] = CredentialCache.DefaultCredentials;

If you use default credentials in an ASP.NET client application that is configured for impersonation, the thread level impersonation token is used. This requires Kerberos delegation.

Using Alternate Credentials

To use a specific set of credentials for authentication when you call a remote object, disable the use of default credentials within the configuration file by using the following setting.

<channel ref="http" useDefaultCredentials="false" />

Note   Programmatic settings always override the settings in the configuration file.

Then, use the following code to configure the proxy to use specific credentials:

IDictionary channelProperties =  
                         ChannelServices.GetChannelSinkProperties(proxy);
NetworkCredential credentials;
credentials = new NetworkCredential("username", "password", "domain");
ObjRef objectReference = RemotingServices.Marshal(proxy);
Uri objectUri = new Uri(objectReference.URI);
CredentialCache credCache = new CredentialCache();
// Substitute "authenticationType" with "Negotiate", "Basic", "Digest", 
// "Kerberos" or "NTLM"
credCache.Add(objectUri, "authenticationType", credentials);
channelProperties["credentials"] = credCache;
channelProperties["preauthenticate"] = true;

Increase Performance with Authenticated Connection Sharing

When you set useDefaultCredentials="true", you should also set the useAuthenticatedConnectionSharing property on the client side to true. This enables the server to reuse authenticated connections, rather than authenticating each incoming call.

<channel ref="http client" useAuthenticatedConnectionSharing="true" >

This feature only works with the HttpChannel on version 1.1 of the .NET Framework.

Force Clients to Authenticate With Each Call

Set unsafeAuthenticatedConnectionSharing to false so that clients are not able to supply their own credentials and connection group name to the server.

If you set it to true, unauthenticated clients can possibly authenticate to the server using the credentials of a previously authenticated client. This setting is ignored if the useAuthenticatedConnectionSharing property is set to true. This setting has some performance implications since it closes each connection with the server, which means that clients must authenticate with each call. If you use this setting, you should also specify a ConnectionGroupName for each user that uses the connection.

<channel ref="http client" unsafeAuthenticatedConnectionSharing="false" >

This feature only works with the HttpChannel on version 1.1 of the .NET Framework.

Control the Use of Authenticated Connections

If you set unsafeAuthenticationConnectionSharing to true, you should provide a name to group together authenticated connections by setting the connectionGroupName property. If you use default credentials, the connectionGroupName is based on the user account used to run the thread.

<channel ref="http client" connectiongroupname="<name>" />

Custom Process Hosting

If you use a Windows service host and the TcpChannel, either use this approach only in a trusted server scenario, or provide a custom authentication scheme.

Note   Because .NET 2.0 now provides built-in support for authentication (identification/impersonation) and authorization for IPC and TCP channels, you no longer need to build custom authentication and authorization mechanisms.

The following guidelines apply if you use a custom host with the TcpChannel:

  • Do not pass plaintext credentials over the network.
  • Do not trust IPrincipal objects passed from the client.

Do Not Pass Plaintext Credentials over the Network

If your server requires the client's plaintext credentials, encrypt them before you send them over the network. If your server needs to validate the client credentials, use a challenge/response scheme to validate the credentials on the server. This could include sending a hash, keyed hash, a nonce encrypted with the hash, or a using a digital signature.

However, even in these scenarios, you should use an encrypted communication channel to prevent replay attacks.

Do Not Trust IPrincipal Objects Passed From the Client

Use caution if you pass IPrincipal objects from the client to the server. Untrusted code can create an IPrincipal object, initialize it with roles, and then send it to the server. If the server accepts the IPrincipal without validating it, the client can elevate the privileges of the caller on the server. For example, a malicious caller could create an IPrincipal object that contains common, highly privileged role names such as Administrators, Managers, ExpenseReportApprovers, and Supervisors. When the object is received on the server and placed in the Thread.CurrentPrincipal property, code that calls IsInRole on this object can be deceived into executing privileged code.

Authorization

Within the context of .NET Framework remoting, you can apply authorization to restrict the ability of computers and users to access functionality exposed by your remote objects. Use the following guidelines to ensure that you have an effective authorization approach:

  • Use IPSec for machine level access control.
  • Enable file authorization for user access control.
  • Authorize users with principal-based role checks.
  • Consider limiting remote access.

Use IPSec for Machine Level Access Control

You can define an IPSec policy to ensure that only a nominated Web server or cluster of servers can connect to the application server that hosts your remote objects. This significantly reduces the attack surface area.

Enable File Authorization for User Access Control

If your remote object is hosted by ASP.NET and uses Windows authentication, you can configure Windows access control lists (ACLs) on the remoting endpoints to authorize callers. ACLs are evaluated on a per-request basis by the ASP.NET FileAuthorizationModule. Under normal circumstances, a physical file representing your remoting endpoints to which your clients connect does not exist. The request for a file with a .rem or .soap extension is sufficient for IIS to be able to route the request based on application mappings defined in the IIS Metabase, to the remoting infrastructure in the appropriate ASP.NET application.

To configure the ASP.NET FileAuthorizationModule for .NET Framework remoting

  1. Create a file with the same name as the value specified in the objectUri property in Web.config, for example, RemoteMath.rem, in the root of the application's virtual directory.

    You can obtain the objectUri from the Web.config file used to configure the remote object on the server. Look for the <wellknown> element, as shown in the following example:

    <wellknown mode="SingleCall" objectUri="RemoteMath.rem" type="RemotingObjects.RemoteMath, RemotingObjects, 
          Version=1.0.000.000 Culture=neutral, PublicKeyToken=4b5ae668c251b606"/>
    
  2. Add the following line to the top of the file, and then save the file.

    <%@ webservice class="YourNamespace.YourClass" ... %>
    
  3. Add an appropriately configured ACL to the file using Windows Explorer to determine which users or user groups can and cannot access the object.

Authorize Users with Principal-Based Role Checks

The FileAuthorizationModule approach described above allows you to control who can and cannot access the remote object. For finer grained authorization that can be applied at the method level, you can perform authorization checks using the IPrincipal object attached to the current request.

If your remote object is hosed by ASP.NET and you use Windows authentication, an IPrincipal object based on the authenticated caller's Windows identity is automatically created and attached to Thread.CurrentPrinicipal.

If you use a custom host, create an IPrincipal object to represent the authenticated user. The mechanics depend on your authentication approach. For example if you use a named pipe transport, you can impersonate the caller to obtain their identity and construct an IPrincipal object.

With the IPrincipal object in place you can perform authorization using principal permission demands both declaratively and imperatively and you can call IPrincipal.IsInRole.

Note   Additionally, if you are running ASP.NET 2.0 and you have enabled the Role Manager feature you can use the Roles API to perform role checks. For more detailed information on using the Role Manager feature in ASP.NET 2.0, see "How To: Use Role Manager in ASP.NET 2.0."

Consider Limiting Remote Access

In some scenarios, where you use remoting for inter process or cross application domain communication on a single computer, you can set rejectRemoteRequests to true to ensure that your object cannot be accessed from remote computers as shown below.

<channel ref="http server" rejectRemoteRequests="true" />

Sensitive Data

If you need to pass sensitive data over a remoting communication channel across a network, to address the network eavesdropping threat, consider the privacy and integrity of the data. You have three basic choices that are likely to be determined by your deployment environment and your choice of host. Your options include:

  • Using IPSec
  • Using SSL
  • Using a custom encryption sink

Using IPSec

You can use IPSec policies to secure the communication channels to your remote objects, for example, the channel from a Web server. You can use IPSec to encrypt all of the TCP packets sent over a particular connection, which includes packets sent to and from your remote objects. This solution is generally used by secure Internet and intranet data center infrastructures and is beneficial because no additional coding effort is necessary.

The additional benefit of using IPSec is that it provides a secure communication solution irrespective of the remote object host and channel type. For example, the solution works when you use the TcpChannel and a custom host.

Using SSL

If you use the ASP.NET host, you can use IIS to configure the virtual directory of your application to require SSL. Clients must subsequently use an HTTPS connection to communicate with your remote objects.

Using a Custom Encryption Sink

If you do not have a secure data center with IPSec policies that secure the communication channels between your servers, an alternative strategy is to implement a custom encryption sink. You may also want to consider this option if you have a requirement to secure only the sensitive parts of the messages passed from client to server rather than the entire payload. This approach is shown in Figure 13.4.

Ff648645.f13thcm04(en-us,PandP.10).gif

Figure 13.4

Using custom encryption sinks

An encryption sink is a custom channel sink that you can use when you use a custom host with the TcpChannel. On the client side, the sink encrypts request data before it is sent to the server and decrypts any encrypted response data received from the server. On the server side, the sink decrypts the request data and then encrypts response data.

Implementing a Custom Encryption Sink

The sink should use asymmetric encryption to exchange session level encryption keys. After exchanging a session key, the client and server maintain a copy of the key and either side may choose to create a new key at any time during the lifetime of the channel sink. The server should maintain a different key for each client it communicates with.

The following steps outline the basic approach to implement a custom encryption sink:

  1. Create a public/private key pair for the solution.

    const int AT_KEYEXCHANGE =  1;
    CspParameters cspParams = new CspParameters();
    cspParams.KeyContainerName = "<container name>";
    cspParams.KeyNumber = AT_KEYEXCHANGE;
    cspParams.ProviderName = "Microsoft Base Cryptographic Provider v1.0";
    cspParams.ProviderType = PROV_RSA_FULL;
    RSACryptoServiceProvider rsaServerSide = new 
                                      RSACryptoServiceProvider(cspParams);
    rsaServerSide.PersistKeyInCsp = true;
    Console.WriteLine(rsaServerSide.ToXmlString(true)); // Writes the public key
    
  2. Expose the public key for clients to consume.

    The client maintains a copy of the public key in a file.

  3. Initialize the client channel sink and create a random key for encryption.

    byte[] randomKey = new byte[size];
    RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
    rng.GetBytes(randomKey);
    
  4. Encrypt the random key with the pubic key of your server. Use IClientChannelSink.ProcessMessage to send the encrypted key to the server.

    RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(csp);
    rsa.FromXmlString("<server's public key>");
    AsymmetricKeyExchangeFormatter formatter = new 
                                       RSAPKCS1KeyExchangeFormatter(rsa);
    byte[] encryptedSessionKey =  formatter.CreateKeyExchange(_sessionKey);
    
  5. Initialize the server channel sink and create an RSA object using the specific key container name.

    const int AT_KEYEXCHANGE =  1;
    CspParameters cspParams = new CspParameters();
    cspParams.KeyContainerName = "<container name>";
    cspParams.KeyNumber = AT_KEYEXCHANGE;
    cspParams.ProviderName = "Microsoft Base Cryptographic Provider v1.0";
    cspParams.ProviderType = PROV_RSA_FULL;
    RSACryptoServiceProvider rsaServerSide = new RSACryptoServiceProvider(cspParams);
    
  6. Retrieve the encrypted key from the client. This key is normally sent in the request headers.

  7. Decrypt the session encryption key using the private key of the server.

    AsymmetricKeyExchangeDeformatter asymDeformatter = new 
                                         RSAPKCS1KeyExchangeDeformatter(_rsa);
    byte[] decryptedSessionKey =  asymDeformatter.DecryptKeyExchange(
                                                             <encrypted key>);
    
  8. Use a mechanism for mapping clients to encryption keys, for example, by using a hash table.

At this point, the client and server both share an encryption key, and can encrypt and decrypt method calls. Periodically during the object lifetime, new keys can and should be created.

Denial of Service

Denial of service attacks can occur when a malicious client creates multiple objects and continues to renew the lifetime lease to consume server resources. Server-side remote objects contain a default lease. In this state, a client can continue to renew the lease forever. However, you can implement the ILease interface on the server and explicitly control sponsors and renewals. To do this, override InitializeLifetimeService on your MarshalByRefObject object. The remoting infrastructure calls this method when the object is created. The lease can also be set programmatically by using the <lifetime> element.

Exception Management

Make sure you do not return full exception details to the caller. If you use an ASP.NET host, make sure ASP.NET is configured so that generic error messages are returned to the client, as shown below.

<configuration>
  <system.runtime.remoting>
   <!-- Valid values for mode attribute are
        on - callers receive default error messages
        remoteOnly - clients on the same computer as the remote component receive
                     detailed exception information. Remote calls receive a 
                     default error message
        off - callers receive detailed exception information -->
    <customErrors mode="on"/>
  </system.runtime.remoting>
</configuration>

Use mode="on" or mode="remoteOnly". Do not use mode="off" on production servers.

Using a Custom Channel Sink

You could implement a custom channel sink to perform client-side and/or server-side exception logging. You can log exception details in the SyncProcessMessage, ProcessMessage, or SyncProcessMessage methods if an exception occurs. The IMessage and Exception parameters provide exception details.

Auditing and Logging

If you use the ASP.NET host, you can use IIS auditing features. If you use a custom host, implement custom auditing. To do this, you could implement a custom channel sink.

Using a Custom Channel Sink

You could implement a custom channel sink to perform client-side and/or server-side auditing. You can get details from the SyncProcessMessage, ProcessMessage, or SyncProcessMessage methods.

Code Access Security (CAS) Considerations

Remoting clients require full trust on version 1.0, 1.1 and 2.0 of the .NET Framework. The System.Runtime.Remoting.dll assembly is not marked with AllowPartiallyTrustedCallersAttribute.

To use remoting to call a remote component from partial trust code such as a partial trust Web application, you must create a full trust wrapper assembly and sandbox the remote object method calls. For more information about sandboxing code and using wrapper assemblies, see Chapter 9, "Using Code Access Security with ASP.NET."

Summary

The .NET Framework remoting infrastructure is designed for use in trusted server scenarios where you can limit callers to trusted clients, for example by using IPSec security policies. If you use an ASP.NET host and the HttpChannel, you benefit from being able to use the underlying security features provided by ASP.NET and IIS. If you use a custom host and the TcpChannel, perhaps for performance reasons, you must implement your own authentication and authorization solutions. IPSec can help in these scenarios by providing machine level authentication and secure communication.

Note   The .NET Framework 2.0 has introduced a new channel named IPCChannel limited to the same machine communication. .NET 2.0 now provides built-in support for authentication (identification/impersonation) and authorization for IPC and TCP channels, you no longer need to build custom authentication and authorization mechanisms.

Additional Resources

For more information, see the following resources:

  • For a printable checklist, see "Checklist: Securing Remoting" in the "Checklists" section of this guide.

  • For information on how to host a remoted component in a Windows service, see "How To: Host a Remote Object in a Windows Service" in the "How To" section of "Microsoft patterns & practices Volume I, Building Secure ASP.NET Applications: Authentication, Authorization, and Secure Communication" at https://msdn.microsoft.com/en-us/library/aa302410.aspx.

  • For more information about how to create a custom authentication solution that uses SSPI, see MSDN article, ".NET Remoting Security Solution, Part 1: Microsoft.Samples.Security.SSPI Assembly," at https://msdn.microsoft.com/en-us/library/ms973911.aspx.

    Note   The implementation in this article is a sample and not a product tested and supported by Microsoft.

patterns & practices Developer Center

Retired Content

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

© Microsoft Corporation. All rights reserved.