Wednesday, September 29, 2010

WCF: Server signs response with a different certificate than client uses for encryption

@YaronNaveh

A lot of Wcf users encounter the below error when consuming a secured non-Wcf web services:

The incoming message was signed with a token which was different from what used to encrypt the body.  This was not expected.

Understanding the problem

When we configure the service x.509 certificate in the client the latter sees this certificate as the service identity. So whenever we interact with this service the client verifies that this certificate is still the service identity, and if not it assumes some sort of phishing occur and drops the connection.

example

This is our client config:

<behavior name="NewBehavior0"> 
 
<clientCredentials> 
   
<serviceCertificate> 
     
<defaultCertificate findValue="CN=WSE2QuickStartServer" /> 
    </
serviceCertificate> 
 
</clientCredentials> 
</behavior> 

We have declared the above certificate here since we want Wcf to use it for encryption and to verify signature. Wcf does all this and also something else: it assumes this is the service “identity”. We’ll see how this afefcts us later.

This is our client request:

<Envelope> 
… 
 
<EncryptedKey> 
   … 
   
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"> 
     
<wsse:SecurityTokenReference> 
       
<wsse:KeyIdentifier ValueType="http://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1#ThumbprintSHA1" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">asPwlS8jh3W+klJJov4=</wsse:KeyIdentifier>  
     
</wsse:SecurityTokenReference> 
   
</KeyInfo> 
   …  
 
</EncryptedKey> 
… 
</Envelope> 

The client uses the service public key to create a session key which is used to encrypt the request body. Only the owner of the matching private key knows how to decrypt this and since this owner is the server the client gets the authentication it wants.

This is the service response:

<o:BinarySecurityToken wsu:Id=”uuid-a687c39f-f848-481b-8552-35de5b5a4d51-2”> 
MQ+PASL89QWEQW2367ASDDASjn7812ASDDAS781mFSDJK78…
</o:BinarySecurityToken> 
 
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#"> 
   
<SignedInfo> 
     
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></CanonicalizationMethod> 
     
<SignatureMethod Algorithm="...rsa-sha1"></SignatureMethod> 
       … 
   
</SignedInfo> 
   
<SignatureValue>tWTQzQhKg3zJb75P4sUfMPa3...</SignatureValue> 
   
<KeyInfo> 
     
<o:SecurityTokenReference> 
       
<o:Reference ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" URI="#uuid-a687c39f-f848-481b-8552-35de5b5a4d51-2"></o:Reference> 
     
</o:SecurityTokenReference> 
   
</KeyInfo> 
</Signature> 

The service signs the response message. Anyone who has the service public key can now verify that the service is the one who sent this response and not some MITM. And since our client has the server public key (it’s the one we configured in the config, which is the same one the client used for encryption) the client can now validate the signature source.

So when do we get this “signed with a different token” error?

We can see in the service response a “binarySecurityToken” element. The service uses it to notify the client which certificate it used for signature. The content of this element is just a base-64 encoded certificate, so the client can easily extract it and compare to the certificate it has configured for the service. If they are not the same we get this exception.

Why must they be the same?

Remember that when we configure the service certificate on the client, Wcf treats it as the service identity. When a response comes back the client expects the service to prove its identity by signing the response with its key. If the response is signed – but using a different key – Wcf throws this authentication error since service identity has not been proved.

I am not using any encryption. Why do I get this error?

Even if you use ProtectionLevel.Sign, Wcf still requires you configure a service certificate. Since the service signs the response Wcf will compare the signing token to the certificate you configured.

Solution

If there is indeed a requirement for the service to use a different signing and encryption certificates, what we would like to do is to configure both of them on the client, so Wcf would know that both of them can authenticate the service. Unfortunately Wcf only allows us one slot of service certificate per configuration. So we need to look in other places.

Option 1

If the scenario is Wcf-2-Wcf, and we are ready to use the proprietary duplex communication, then there is a way to use separate X.509 certificates for signing and encryption.

Option 2

If we use ProtectionLevel.Sign, meaning we only sign messages but do not encrypt them, then the service certificate which we configure on the client is only used for the purpose of validating the response signature. So we are free to change it to be the actual signing certificate. In some cases we may not know what this certificate is. Apart from asking the service author to provide it we can examine the response (as above) and extract the certificate from the binary security token (which may not always exist though).

Option 3

This is a workaround that reduces the security level of the communication. Use it only if you have other means to verify the service apart form the signature or if you are willing to have reduced security.

Step 1: Implement a custom message encoder which removes from the response the Envelope/Header/Security element all together.

Step 2: Configre EnableUnsecuredResponse to true:

<customBinding>
 
<binding>
   
<security enableUnsecuredResponse="true" />
  </
binding>
<customBinding>

This is a Wcf 4.0 new feature but it is also available in a patch to Wcf 3.5 SP1. Strive to use 4.0 if you can since some users have problems with the patch.

This solution requires to use a custom binding. If you need help converting your wsHttpbinding to a custom one use the binding converter.

The implication of this workaround is that your client will not verify the service identity at all – this is usually not desired from security perspective.

@YaronNaveh

What's next? get this blog rss updates or register for mail updates!

Free MSDN Ultimate - Reminder

@YaronNaveh

We're just 8 days away from your chance to win a $11899 MSDN Ultimate subscription.
All you need to do is leave a comment to the original post describing (in detail) a project you were involved with where web services interoperability was used. There are 3 prizes waiting so you have pretty good chances...

@YaronNaveh

What's next? get this blog rss updates or register for mail updates!

Tuesday, September 28, 2010

Having fun with blogger layouts

@YaronNaveh

Once again, it's time to renovate my blog layout. This time the motivation is not only visual - the previous layout left no space for long code samples.

Some of the new layout highlights:

  • Featured links under the title (CUB, binding box)
  • More space for the blog content
  • Removed the blogger navigation bar
  • "Search this blog" in the top right corner

    The process of fine tuning the layout reminds me a little the process of software development. You be the judge:

    Early prototype (procedural design, all defaults):


    Beta (More cohesive design, some limitations):


    Release (post-refactoring):

    @YaronNaveh

    What's next? get this blog rss updates or register for mail updates!
  • Monday, September 27, 2010

    Wcf and Asp.Net compatibility gotcha

    @YaronNaveh

    Ido had noticed a bottleneck in Wcf services which use the Asp.Net compatibility mode. Asp.Net synchronizes by default requests that come from the same session, so such requests are executed sequentially instead of concurrently. If this behavior is not desired by your service you should consider turning the compatability mode off or apply one of the other workarounds.

    @YaronNaveh

    What's next? get this blog rss updates or register for mail updates!

    Friday, September 24, 2010

    Developers machine survey

    @YaronNaveh

    Ken has published a developers machine survey. I used to look at three 24" screens as overkilling (excpet for special UI debugs) but I was wrong.

    @YaronNaveh

    What's next? get this blog rss updates or register for mail updates!

    Monday, September 20, 2010

    Free MSDN Ultimate subscriptions (+VS 2010) - Giveaway contest

    @YaronNaveh

    Last July I was nominated as a Microsoft MVP. A few days ago I got my "MVP Package":


    It is a very cool package!

    The package also includes this:



    What's this?
    Three MSDN ultimate subscription keys. Each one includes:


  • Windows Azure Platform


  • Visual Studio 2010 Ultimate


  • Visual Studio TFS 2010


  • Expression Studio Ultimate


  • Windows 7, Windows Server 2008 R2 and SQL Server 2008


  • Microsoft Office Professional Plus 2010, Project Professional 2010, Visio Premium 2010


  • and much more...

    This package is worth $11,899. And you will get it for free.

    How do I get a $11,899 MSDN Ultimate for free?
    Publish a comment to this post describing a project you were involved with where web services interoperability was required. The three most detailed descriptions by 8 October 2010 will grant their author a $11,899 MSDN Ultimate for free!

    Edit: detailed = in quality, not length :) chosen by me.

    @YaronNaveh

    What's next? get this blog rss updates or register for mail updates!

    Sunday, September 19, 2010

    What does the Asp.Net security vulnerability mean for Web Services and Wcf?

    @YaronNaveh

    The "padding oracle" Asp.Net vulnerability will surely affect many production web sites. Does this have any effect on web services and Wcf?

    To put this in concrete terms, can a web service become a "padding oracle"?

    Without getting too much into details, I believe it is possible in some situations. The best way to protect against this is to ensure all your messages are digitally signed. With Wcf this behavior is actually built in to the framework and you cannot send messages which are encrypted but not signed. With older frameworks such as Wse, and some non-MS soap stacks, this is possible, so you might want to check any relevant production application.


    Regardless of this it is always a best practice to sanitize customer facing error messages.

    I have actually did a little test. I have configured a Wcf service to emit debug information in error responses (this is the most verbose response Wcf is capable of). I have then created a valid encrypted request, manually altered the encryption to make it not valid, sent it to the server and got this soap fault:

    An error occurred when verifying security for the message.


    No secret data is enclosed here. I have then changed my server implementation to throw a logical exception:

    public string GetData(int value)
    {
       
    throw new Exception("Data is not available");
    }

    I initiated a legal request and this time got this response:

    <Message>Data is not available</Message>
    <StackTrace>
    at Service.GetData(Int32 value) in C:\Users\naveh\Documents\Visual Studio 2008\Projects\WCF Self Hosted Service37\WCF Self Hosted Service37\Service.cs:line 23
    at SyncInvokeGetData(Object , Object[] , Object[] )
    at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
    at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
    at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
    at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc)
    at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc& rpc)
    at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc& rpc)
    at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc& rpc)
    at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
    </StackTrace>

    So Wcf did return a full stack trace with an application exception. This means that Wcf shields us from verbose errors when security exceptions are thrown.


    So are we safe?
    You never are. For this reason take these precautions when using Wcf:

    Disable debugging information in responses
    Even though we saw Wcf tries not to disclose security information you should still protect from such information leaking into application level exceptions (or Wcf bugs). Just make sure your service has this behavior:

     <behaviors>
           
    <serviceBehaviors>
             
    <behavior name="ServiceBehavior">
                  
    <serviceDebug includeExceptionDetailInFaults="false" />
              </
    behavior>
           
    </serviceBehaviors>
         
    </behaviors>

    Protect your trace files at all cost
    They may contain the detailed exceptions hackers look for.

    What about Asp.Net web services?
    Asp.Net web services (asmx) are inherently insecure (WRT message level) unless Wse is used with them. You should apply the same technique and sanitize your Wse error messages as explained in this walkthrough.

    @YaronNaveh

    What's next? get this blog rss updates or register for mail updates!

    Saturday, September 18, 2010

    Asp.Net critical security vulnerability

    @YaronNaveh

    Edit: Some information in the original version of this post was not correct. I have fixed it.

    A few hours ago Microsoft had publicly disclosed a critical Asp.Net security vulnerability. In short, a hacker can get sensitive data from an Asp.Net application in a few minutes. This information includes any file on the server (e.g. web.config) and any viewstate data even if it is encrypted. To block this attack, site owners should immediately direct all errors to a single page (custom errors redirect).

    If you have a production Asp.Net system read this now and go fix it.

    How does the vulnerability work?

    Without making this a walkthrough to my hacker readers, this is the general flow:

    Some common encryption algorithms (among them TripleDes and AES) divide the encrypted data to blocks of equal size, where the last block is padded with additional data to make all blocks equal. A few years ago a security researcher had published an article explaining how to hack such an algorithm provided that a "padding oracle" exists. What is a padding oracle? It is an application (or some abstract... oracle) which tels us if the padding of an encrypted data is in the correct format.

    Well, it turns out that Asp.Net uses TripleDes, and that some specific feature of Asp.Net turns it into a "padding oracle", you get the idea...


    How to avoid this?

    1. The single most important rule is this:

    When there is an error in your application, never let the end user know what it was. In particular never allow an end user to distinguish between 404 and 500 status codes.


    The way to do it is to redirect all errors to one page.
    ScottGu's post explains how to do it.

    2. The hacker that found this hole wrote his in this twitter account:

    error message setting is irrelevant. no error? there's always HTTP status. always the same HTTP status? there's always big timing different

    He means that even though we hide from him the real Http status (by redirecting to a single error page) the real status still "leaks" by computing the response time.

    This means that adding a random wait before sending the error page can help us. ScottGu's post has the details too.


    If you are really interested in the bits & bytes (&blocks) of this kind of attacks this is a nice introduction.

    @YaronNaveh

    What's next? get this blog rss updates or register for mail updates!

    Friday, September 10, 2010

    Wcf on iPhone?

    @YaronNaveh

    Apple's announcement yesterday on relaxing the strict AppStore SDK policy is good news for web services interoperability. Why is that? We need to get some background first:

    With the rising popularity of iPhone development, people seek for web services support.

    One known Mac framework is wsdl2objc (wsdl to objective-C, the iPhone development language). It give the basic functionality of creating a proxy and calling the service.

    If your web service is relatively simple and you can afford to build the soap payload by hand, you could also consider using the native Http library CFNetwork or a the ASIHTTPRequest wrapper.

    The latter option also enables transport level security (ssl).

    Message level security
    This is a known pain point. I have yet to find a WS-Security implementation for the iPhone. If you are doing simple stuff (mainly username token) you can get away with manually pushing these headers. But more advanced scenarios (involving X.509) are harder and Apple does not seem to develop a ws-security implementation soon.

    So why doesn't any third party develop one?
    Until yesterday, apple banned the usage of code generators for AppStore applications. While a soap stack may be developed in pure objective-C, the realm of web services highly relies upon code generation and libraries.
    Yesterday, Apple announced that it now allows any development tools to be used for AppStore applications. While the media mainly mentioned the implication on Adobe Flash, the announcment also positively affected the MonoTouch framework which enables C# development for iPhone. And while MonoTouch WCF support is still experiential and does not include advanced WS-*, there is now hope to have all the advanced stuff in a future version.

    UPDATE 1: It seems MonoTouch does support the Wcf Silverlight stack. I assume username token is in but not sure about binary encoding and tcp transport. Looking at Mono WCF support page shows that Wcf is still not fully supported there, which may be an indication.

    UPDATE 2: Carlos mentions that Silverlight is supported on Mac. After yesterday's announcement there is a reason to believe that SL will be officially supported in iPhone either which makes standalone SL applications a prospect too.

    @YaronNaveh

    What's next? get this blog rss updates or register for mail updates!

    Monday, September 6, 2010

    Better Username token for WCF

    @YaronNaveh

    Gerwin Postma had commented on my ClearUsernameBinding post with an interesting link. It seems aszego had published a username token class for WCF which has improved capabilities comparing to the built-in one (in terms of interoperability). Some of the great features are support for digest password and nonce:

    <UsernameToken>
    ...
    <Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">S5Of09Zuan02wWpbSEx7EDZsefE=</Password>

    <Nonce>Ka+AC6oq5ROJ/pHX1sW+Ng==</Nonce>

    </UsernameToken>

    This is a great library for many people struggling with ws-security interoperability, although username issues are relatively easy to workaround by writing custom inspectors.

    @YaronNaveh

    What's next? get this blog rss updates or register for mail updates!