Pages

Wednesday, September 29, 2010

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.

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.

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.

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.

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.

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...

Monday, September 27, 2010

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.

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!

Sunday, September 19, 2010

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:

publicstringGetData(intvalue){thrownewException("Data is not available");}

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:

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.

Saturday, September 18, 2010

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.

Friday, September 10, 2010

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.

Monday, September 6, 2010

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: