views:

42

answers:

2

Ok,

I have developed this WinForms client, which interacts with a server (ASPX Application) by means of WCF calls. I would now like to deploy the server to my shared webhost, but I'm kinda new to WCF and especially the security possibilities behind it.

The goal is to kind of secure the WCF service, so that not everybody that knows or finds out the endpoint address can call it. Rather, only my WinForms client must be able to call the WCF service.

I do not need authentication on a user basis, so no authentication is required from the user of the client. But I want only instances of this WinForms client to be able to interact with the service. The information passed between server and client is not very sensitive, so it's not really required to secure it, but it's a plus if it can easily be done.

Is this possible with a Shared Host (IIS) environment (no HTTPS at disposal) ? What bindings and options should I use ? I suppose wsHttpBinding, but how would I setup the security options ?

Using .NET 4.0

Thanks

+1  A: 

The first thing you need to ask your self is: "What can someone do to your WCF service if they connected their own customized client?" Look at all of the functionality that is being exposed via WCF and assume that it could be accessed at will. You have absolutely no control over the client, and you will never have this ability.

HTTPS is beautiful, its a damn shame that your forced to be vulnerable to OWASP A9: Insufficient Transport Layer Protection. If it where up to me, I would move to a different host that cared about security. If you are throwing usernames and passwords over the network, then your putting your users in danger.

One of the biggest problems I have seen with a WCF service is that they had a "executeQuery()" function that was exposed. The developer allowing the client to build queries to be executed by the server. This approach is fundamentally flawed as you are just handing your database over to an attacker. This type of vulnerability isn't SQL Injection, it falls under CWE-602: Client-Side Enforcement of Server-Side Security.

Along the same lines as CWE-602 is OWASP A4: Insecure Direct Object References. Could an attacker fool your WCF service into thinking its another user by providing a different user id? Are you trusting the client to tell the truth?

The next classification of vulnerabilities that you must take into consideration is OWASP A1: Injection, other wise known as "Taint and Sink". For instance if you are exposing a function where one of its parameters is being used in a CreateProcess() which is invoking cmd.exe. This parameter could be controlled by the attacker, and there for this variable is "tainted", the call to CreateProcess() is a "sink". There are many types of vulnerabilities along these lines, including but not limited to; SQL Injection, LDAP Injection, XPATH Injection. These types of vulnerabilities affect all web applications.

Rook
The functions exposed by the service are all of type "GetSomeEntityFromDatabase()". The queries are built on the server, and the clients cannot pass custom queries, so I think I'm safe on that part. Also, it's "read-only", I only expose "Get" operations, and no "save"
tjeuten
A: 

From what I understand, you have an internet-facing service which you want to limit to only your client app to be able to call - correct? Or do you envision other clients (like PHP, Ruby etc.) also wanting to call into your service at some point?

To secure your message, you have two options in WCF - message or transport security. Over the internet, with an unknown number of hops between your client and your service, transport security doesn't work - you're left with message security (encrypting the message as it travels across the 'net). For this to work, you typically add a digital certificate to your service (only server-side) that the client can discover and use to encrypt the messages with. Only your service will be able to decrypt them - so you're safe on that end.

The next point is: who can call your service? If you want to be totally open to anyone, then yes, you need wsHttpBinding (or the RESTful variant - webHttpBinding). If you want to allow non-.NET clients, you're typically limited to no authentication (anyone can call), or username/password schemes which you will validate on the server side against a database of valid users.

If you only want to allow your own .NET client in, then you can do several things:

  • disable metadata on your service; with this, you would "hide" your endpoints and the services they provide - someone using a "metadata scanner" (if that exists) wouldn't be able to just stumble across your service and find out what methods it provides etc. This however also makes it impossible for another developer outside your organization to do an Add Service Reference to your service.

  • you could define and use a custom binary http binding - only other clients with this setup could even call your service. The binary http binding would bring some speed improvements, too. See this blog post on how to do this.

  • you need to somehow identify those callers that are allowed in - one possible method would be to put an extra header into your WCF messages that you then check for on the server side. This would simply make sure that a casual hacker who discovers your service and figures out the binary http binding would still be rejected (at least for some time). See this blog post here on how to implement such a message inspector extension for WCF.

  • the ultimate step would be to install a digital certificate on the client machine along with your service. You would then set up your client side proxy to authenticate with the service using that certificate. Only client machine that have that certificate could then call into your service.

It really depends on how far you want to go - WCF gives you a lot of options, but you need to decide how much effort you want to put into that .

marc_s
I have no intention of sharing this service with other clients, and especially non .NET ones. With that in mind, and of the 4 possibilities you mentioned, which one would you advise ? I think the certificate step would be a bit too far fetched and don't think it would be possible on my shared host (being Softsys, for the record). Also, I'd like to keep it free as it's for a hobbyist project, nothing commercial. And I don't think certificates are free, are they ?
tjeuten
@tjeuten: you are creating the WCF client side proxy yourself? E.g. can you supply an assembly to your callers, or even a full app? In that case: disable the metadata on the service so no one can "stumble" across it, and create that custom binary http binding. Plus I would probably put some fixed header into your messages, to prevent external callers with other tools like SoapUI. Create a small WCF message inspector extension - no big deal, really.
marc_s
@tjeuten: added some links to my answer to show how to do the custom binary http binding, and how to write a WCF message inspector to add a custom header to your WCF messages.
marc_s
thanks for the comprehensive post !
tjeuten
-1 an attacker will be able to recover the digital certificate from the binary and access the remote WCF process using an exploit. I gave you a -1 because i think you are misleading the op.
Rook
Security though obscurity. You absolutely must lock down the WCF service, trying to hide its interface is a mistake.
Rook
@The Rook: hiding the interface can be a first step - it's not perfect, but it keeps away a certain group of freaks
marc_s
@marc_s You shouldn't worry about the people that this fools. You should worry about the people with real skill.
Rook
@THe Rook: yes, if you're the Federal Reserve and this service transfers billions of dollars - sure. But that doesn't seem to be the case here - it's more about keeping away those annoying script kiddies that will hammer your service with crappy bogus requests. If they can't see it, it doesn't exist to them...
marc_s
@marc_s The attacker has access to a debugger, it is trivial for the attacker to obtain any keys used in the makeshift transport connection you are establishing. Further more a breakpoint could be set prior to transmission thus obtaining the request in clear text. This is security though obscurity, you are not preventing **any** attack, your are misleading people when he should lock down his WCF service. Based on your recommendation he may get hacked, my -1 stays for this reason.
Rook
@The Rook: you're building Fort Knox to protect a dime ..... your protection needs to be proportional to the threat(s).
marc_s
@The Rook: so, being the security hot-shot around here: how would **you** secure this service?? Keep in mind: it's a hobbyist project, doesn't have infinite funds for the latest, greatest gadgets, needs an easy, workable solution - what is it?? Let us know ! I'm curious myself !
marc_s
@marc_s I posted and you voted me down, i suggest that you *actually* lock down the service. You patch the real vulnerabilities in the service instead of trying to hide them. If you think you need to hide something like this then you just messed up and you are going to get burned. You cannot hide anything in a client<->server interaction, and you cannot control the client (period end of story).
Rook