Posted by intrepiddeveloper on August 24, 2008

Source: http://intrepiddeveloper.wordpress.com/2008/08/24/message-authentication-failure-timestamp-clock-skew-issue/

 

Recently I came across an interesting issue with service binding and message security in WCF. The service was hosted in IIS and used message level security with UserName Credential and https for transport security. The two exposed bindings are as follows:

01<wshttpbinding>
02  <binding name="wsHttpWithMessageSecurity">
03    <security mode ="TransportWithMessageCredential">
04      <message clientCredentialType="UserName" negotiateServiceCredential="true"/>
05    </security>
06  </binding>
07</wshttpbinding>
08
09<basichttpbinding>
10  <binding name="MyBasicHttpBinding">
11    <security mode="TransportWithMessageCredential">
12<transport clientCredentialType="None" proxyCredentialType="None" realm =""/>
13      <message clientCredentialType ="UserName"/>
14    </security>
15  </binding>
16</basichttpbinding>

 

Everything worked fine when I testing my client and service hosted on the same machine i.e. local IIS but when I deployed the service to a remote server (IIS6/Win2K3 server) the service started throwing “Error verifying security of the message” exceptions/faults. I made sure there where no server/client certificate or SSL issues but that did not seem to be the issue.

Here is the stack trace of the exception caught on the client side:

System.ServiceModel.Security.MessageSecurityException was caught
Message=”An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail.”
Source=”mscorlib”
StackTrace:
Server stack trace:
at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.ProcessReply(Message reply, SecurityProtocolCorrelationState correlationState, TimeSpan timeout)
at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)

InnerException: System.ServiceModel.FaultException
Message=”An error occurred when verifying security for the message.”

I enabled Security Auditing on the service for MessageAuthenticationAuditLevel =”Failure” and retested the client and checked the auditing log on the server. The log had the following entry:

Message authentication failed.

Service: https://mytestserver.com/service.svc/endpoint01

Action: http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT

ClientIdentity:

ActivityId: 00000000-0000-0000-8f01-0060000000a2

MessageSecurityException: The security timestamp is stale because its expiration time (’2008-08-04T20:29:58.924Z’) is in the past. Current time is ’2008-08-04T20:45:18.828Z’ and allowed clock skew is ’00:05:00

Basically the  client message failed message authentication since it is outside the acceptable time range when processed by the service. The main reason for this being the server & client clocks out of sync or mismatched.

 

When using  Message level security with UserName credential in some WCF bindings, you might get into a situation where you start getting Message Authentication Failure(See my earlier post for more details) .

The reason for this is due to the fact that WCF frameworks implementation of WS-Security by default enables Message Replay Detection. Message replay is an attack where a message is presented to a processor more than once in the hopes of fooling the processor into taking some action. One protection against message replay and other timing-based attacks is to have the sender timestamp messages. Security timestamps are only valid for a limited window of time, typically represented by a creation time and an expiration time. The processor may declare that messages have a limited lifetime, which can be checked by using the security timestamp.

The sender and receiver have to agree on what time means. Since the two sides don’t share a common clock, they need to each have a clock and those clocks need to agree on the current time to a certain precision. It’s impossible to make two clocks exactly agree and there’s some threshold after which you have to assume that the clocks are measuring two different times. The difference between the clocks is called the skew and the threshold is called the maximum allowed clock skew.
When checking creation and expiration times, the maximum clock skew becomes a factor because it determines whether two times might be the same. Here are the interesting checks for a security timestamp.

  • If the creation time is after the local time plus the maximum clock skew, then the creation date is actually in the future.
  • If the expiration time is before the local time minus the maximum clock skew, then the expiration date is actually in the past.
  • If the creation time is before the local time minus the maximum clock skew and minus the message lifetime, then the message is too old and may be part of a replay attack.

This clock skew is a configurable setting on the SecurityBindingElement through the local client settings or local service settings. Changing that value changes the tolerance for comparing times. The default clock skew value is 00:05:00.

Keep in mind that this message timestamp value is checked both ways i.e. from the client to the Service(checked at the service side) AND from the Service to the client (check on the client side).

There are two solutions to this:

  1. Make sure both the server and client clocks are synced with a standard time server. This approach may not be applicable when you don’t have control over the server or the client machines.
  2. Change the default values from the Service configuration by defining a custom binding. An example as as below.

 

1<binding name="CustomDevWSHttpBinding">
2  <security authenticationMode=“UserNameOverTransport“ requireSecurityContextCancellation=“true“>
3    <localservicesettings maxClockSkew=“00:10:00“ />
4    <localclientsettings maxClockSkew=“00:10:00“ />
5    <secureconversationbootstrap />
6  </security>
7  <textmessageencoding />
8  <httpstransport />
9</binding>

 

Note: For some reason, when I generate the client proxy’s configuration using SvcUtil, the clients ClockSkew value still default to 00:05:00 but you can manually change that to a suitable value.

Recently came to find out that the settings I mentioned above are going to be local to the service and the domain it operates in, hence the ClockSkew can be set on the service side to a suiable value or to turn it off set the maxClockSkew=Infinite“/maxClockSkew="11.13:46:40" --TimeSpan.Maxvalue

However the generated Client configuration will always default to 5 mins and will have to be changed manually if required.

posted on 2012-03-08 17:17  Alan Yang  阅读(2613)  评论(4编辑  收藏  举报