Friday, September 24, 2010

Securing WCF REST services for smartphone clients

In one of the projects that I’m working on we have to define the security model for calling REST services (WCF) from smartphone apps (iPhone/iPad, Android). The security requirements are the following:

  • Both the clients and servers are owned by the same organization so it’s basically the smartphone calling “home”.
  • The data to be transferred is not sensitive, so we can safely skip confidentiality concerns.
  • The services are read-only so integrity is ruled out as well.
  • Even though data is not confidential, users need to be authenticated (so for example we can establish quotas per user).

As REST over HTTP is all about HTTP standards, let’s have a look at what standard methods we can use for authenticating our users

  • HTTP Basic: The username and password are sent in clear text over the wire, this is not really an option unless you want to use HTTPS as well. As there is no need for confidentiality in our scenario, we’d rather not take the overhead of HTTPS on the smartphone devices which in some cases may be using slow internet connections.
  • HTTP Digest: The request is signed with a secret shared between the client and the server (password) and a salt (challenge) obtained by the client in a previous request to the server. The shared secret is not sent over the wire (no need for HTTPS), but an extra request is needed to get the challenge from the server .
  • WSSE Username token: This is an OASIS standard used by the SOAP WS-Security. The ATOM 1.0 protocol design committee, not having the possibility to use HTTP Basic or HTTP Digest, went for this option for providing an authentication mechanism to the ATOM API. Like the Digest method,  it uses the shared secret to sign some parts of the message. More info here: http://www.xml.com/pub/a/2003/12/17/dive.html
  • OAuth 1.0: OAuth is an open standard for authorization delegation: You can authorize 3rd party sites to access, for example, your profile in Facebook or Twitter without having to hand out your credentials to those sites. In our case we don’t need credential delegation but OAuth defines another workflow, known as 2-legged authentication (as opposed to the 3-legged default one) which follows a similar approach of the HTTP Digest and WSSE: the request is signed and verified with the shared secret.

WCF implementation

IIS implements HTTP Basic and HTTP Digest but it's tightly coupled to the company Active Directory, so obviously this is not suitable for Internet scenarios. The WCF REST Starter kit defines some extensibility points that allow to implement custom authentication methods like it’s explained here for HTTP Basic:

http://weblogs.asp.net/cibrax/archive/2009/03/20/custom-basic-authentication-for-restful-services.aspx

I've implemented HTTP Digest and WSSE UsernameToken methods (along with the HTTP Basic sample) by following that same approach. The code is available in github under the name WcfRestAuth. If you don’t use git, you can get the source code here. Any feedback will be welcome!

For OAuth and WCF you can check DevDefined.OAuth

Friday, September 17, 2010

Using soapUI to consume a WS-Addressing service

soapUI is a handy tool to test web services. You receive a WSDL document of an external service and you can use this tool do some quick testing before actually getting to write some code to consume the service.

If the service implements WS-Addressing you should know that when generating requests, by default soapUI 3.5 will only add the Action header (the SOAP RPC operation name)

<soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
   <wsa:Action>http://myuri/IHello/SayHello</wsa:Action>
</soapenv:Header>

When you send a request like that to a WCF service, you’ll get an exception like this from the server:

<s:Fault>
<faultcode>a:DestinationUnreachable</faultcode>
<faultstring xml:lang="en-US">
The message with To '' cannot be processed at the receiver,
due to an AddressFilter mismatch at the EndpointDispatcher.
Check that the sender and receiver's EndpointAddresses agree.
</faultstring>
</s:Fault>

Indeed there was no “To” header in the request message. We can edit the WS-Address headers in soapUI though: just open the Message Editor window and click on the WS-A tab button at the bottom. You can set values for headers like MessageId or From but just setting the To value by clicking this checkbox will do the trick

clip_image002

Now your request messages will look like this

<soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
<wsa:Action>http://myUri/IHello/SayHello</wsa:Action>
<wsa:To>http://localhost/Hello/HelloWorld.svc</wsa:To>
</soapenv:Header>

Where the To header value is the service URI.

The WCF service won’t complaint anymore about WS-Addressing issues.

Thursday, September 16, 2010

Replay detection in a web farm with WCF

If you are securing web services, replay attacks is one of the things that you should watch out for. Replayed messages can cause duplicate transactions and can be used to create DOS attacks. Note that replay messages don’t necessarily have to come from malicious users; in environments where exactly-once message delivery is not guaranteed, they are actually expected to happen.

The countermeasures to detect these situations are basically these two:

  • Timestamping: Incoming messages include a timestamp field that is checked by the server against its clock. If the timestamp from the client message differs by a predefined factor from the current server time, then the message is suspicious of being replayed an it’s discarded. With timestamping we can avoid replay attacks that happen over the server replay window maximum value (for example 5 minutes) but what  if the hacker manages to replay the message within the window? Nonces to the rescue.
  • Nonce tracking. Incoming message includes a nonce (randomly generated string by the client). The server keeps track of the nonces arrived within the replay window. When a new message arrives with a timestamp that falls within the valid window, the server checks if the message nonce can be found in its nonce cache and  if it does, we have proof that the message has been replayed. In a server farm scenario, all nodes in the farm should share the same nonce cache, otherwise in the worse-case scenario messages could be successfully replayed N-1 times, where N is the number of nodes in the farm.

Note: It goes without saying that both Timestamp and Nonce must be signed otherwise they could (and they would) be tampered.

Now, WCF implements a replay detection mechanism and provides a bunch of configuration options to tune the Timestamping and nonce tracking procedures (i.e: ReplayWindow, ReplayCacheSize for the nonce cache).

However, there doesn’t seem to be any extensibility point for custom nonce cache implementations. Internally (thanks Reflector!), WCF uses the class NonceCache (declared as Internal and Sealed) which is a in-memory cache.  If you’re using IIS to host your services, you can imagine what happens to the cache when IIS pool is recycled!

Interestingly enough, the missing hook in WCF was available in WSE 3.0. In you look at that WSE article, you’ll see that for that sample, they used back then a DB table as a nonce cache; today I’d probably go for an AppFabric cache for a better performance and high availability, but this is a different story!

Maybe in WCF 5.0?

I started a thread in the msdn forums regarding this.