Posted by: Cirilo Meggiolaro | 12/27/2008

Tip of the day #74 – Using timestamp to avoid replay attacks to WCF Services

Overview

In a very general way, replay attack (a.k.a. man-in-the-middle attack) is a network attack where messages are intercepted and then used to simulate future authentication and authorization or retransmitted, causing duplicated transactions.

The most common ways to avoid replay attacks are:

  • Session tokens: Based commonly on a hash generated to be used once (during the session), avoiding future tries using the same token;
  • Timestamps: The idea behind the use of timestamps is to generate a synchronization mechanism between the message requester and receiver. The server keeps broadcasting in a secure communication protocol its current clock time + a message authentication code (MAC). This MAC must be sent back with the estimated clock time and the message to be processed. The server may decide, based on a time tolerance if the request will be processed or not. It means that the man-in-the-middle may try to retransmit a message later without success because is not synchronized.

Windows Communication Foundation (WCF)

When we expose a service using WCF the default behavior for bindings with integrated security is to include the timestamp on the message to be used by the service to decide if the request is under the tolerance time that determines if the request must be accepted or not. The default value is 5 minutes and this value is defined by a property called MaxClockSkew available under the big named LocalServiceSecuritySettingsElement class.

How to…

Unfortunately, there is no way to set a value for the MaxClockSkew property in a built-in binding. You need to create a custom binding to achieve that.

Define a custom binding using a config file

To define the custom binding properties for the client, you may use the following xml:

<customBinding>
<
binding name=MyBinding>
<
transactionFlow />
<
security authenticationMode=SecureConversation>
<
secureConversationBootstrap authenticationMode=UserNameOverTransport>
<localClientSettings maxClockSkew=00:10:00 />
</secureConversationBootstrap>
<
localClientSettings maxClockSkew=00:10:00 />
</security>
<
httpsTransport />
</
binding>
</
customBinding>

To define the custom binding properties for the service, you may use the following xml:

<customBinding>
<
binding name=MyBinding>
<
transactionFlow />
<
security authenticationMode=SecureConversation>
<
secureConversationBootstrap authenticationMode=UserNameOverTransport>
<localServiceSettings maxClockSkew=00:10:00 />
</secureConversationBootstrap>
<
localServiceSettings maxClockSkew=00:10:00 />
</security>
<
httpsTransport />
</
binding>
</
customBinding>

Define a custom binding programmatically

To change the MaxClockSkew property programmatically you need to perform the following steps:

  • Create an instance of the wsHttpBinding class with the security mode set to Message;
  • Create a custom binding object based on the wsHttpBinding object;
  • Find a security binding element from the binding elements collection available under the binding object;
  • Set the MaxClockSkew property value for both client and service
  • Create a service host;
  • Add the custom binding as the endpoint.

Code snippet

/// Declares the service host object.
ServiceHost host = null;

try
{
    /// Defines the binding.
    WSHttpBinding httpBinding = new WSHttpBinding();

    /// Defines the custom binding based on the original binding.
    CustomBinding customBinding = new CustomBinding(httpBinding);

    /// Gets the SecurityBindingElement from the binding element
    /// collection available under the custom binding object.
    SymmetricSecurityBindingElement securityBinding =
(SymmetricSecurityBindingElement)customBinding.Elements.Find<SecurityBindingElement>();

    /// Change the MaxClockSkew to 2 minutes on both service and client settings.
    TimeSpan newClockSkew = new TimeSpan(0, 2, 0);

    securityBinding.LocalServiceSettings.MaxClockSkew = newClockSkew;
    securityBinding.LocalClientSettings.MaxClockSkew = newClockSkew;

    /// Instantiates the service host.
    host = new ServiceHost(typeof(Order), new Uri(http://localhost:8000/order&#8221;));

    /// Adds the endpoint.
    host.AddServiceEndpoint(typeof(IOrder), customBinding, “”);

    /// Opens the service host.
    host.Open();

    Console.WriteLine(“Listening from the following uri: {0}”, host.BaseAddresses[0].AbsoluteUri);
    Console.Read();
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}
finally
{
    if (host != null)
    {
        if (host.State != CommunicationState.Closed)
            host.Close();

        host = null;
    }
}


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: