WCF message security without certificate and windows auth - wcf

I have a WCF service and client which is going to be deployed to several companies (hundreds). Some companies will run the software in their network and some will run it over the Internet (WCF server at on office, WCF client at another).
We want to encrypt the communication between the WCF server and client. We don't have any need to authenticate the cient / subscriber using WCF security, because we have our own username/password log-in which the clients will use to log on the server.
We can't rely on Windows auth because some of the users will run it over the Internet, and the WCF server may not be on the same domain as the WCF client.
If we use "real" certificates*, companies running the software would have to purchase certificates from a CA and install it, and then configure our software to use it, but this is too complicated for most of them.
We could auto-create certificates during installation of the WCF server, but then we would have to automatically install it into a certificate store and somehow automatically grant IIS permissions to read the certificate. This is more complicated than we would like.
In short, we want a simple solution where the encryption is just based upon a shared secret, in our case the username / password the user is logging on with. I do understand that this won't give the best available encryption, but we're willing to trade some of the security to make the software easier to deploy.
Is this possible?
*With "real" certificates, I mean certificates purchased from a certificate authority, and not one I've created myself / self-signed.

If you want to encrypt the messages on the transport (which is a really good idea!), there has to be some shared knowledge between the sender (the client) and the server. This can be hardcoded, but that's really not a good idea at all - if that "common shared" knowledge is ever compromised, an attacker could decipher and read all your messages.
Also, since it's definitely not recommended practice, there's no support of any kind in WCF to simplify using a shared secret. You're on your own - you have to roll your own 100% of the way.
The only viable way to have a common shared secret exchanged in a safe way is to use a certificate. No way around this, sorry. The certificate doesn't even have to be used for user authentication or anything - but it establishes a shared secret between the caller and the service and thus allows the caller to encrypt the messages in such a way only the intended recipient can actually decrypt and use them.
So I really don't see any way you can get around having certificates on your servers - doesn't need to be on every client, but on every server where your service runs.
Marc
PS: if you really want to investigate the "hardcoded shared secret" approach, you'll need to think about this:
how do you store a shared secret safely on each and every single one of your clients?
how do you use information from that stored shared secret to encrypt your messages?
Typically, the approach would be two-fold:
exchange some form of a private/public key pair; the server generates a key pair and keeps the private key to itself and shares the public key with the client (e.g. over a WCF message, for instance)
using that private/public key pair, exchange a common shared secret, e.g. an "encryption key" that will symmetrically encrypt your messages (and since it's symmetrical, the server can use the same key to decrypt the messages)
setup infrastructure on your client (e.g. a WCF extension called a behavior) to inspect the message before it goes out and encrypt it with your shared secret
All in all, it's really not trivial - anything simpler than that is not worth being called "security" at all.
If you look at all that work you will have to do - wouldn't it be easier to just use the WCF built-in certificate mechanisms??
Decent security worth its salt is hard - so why not leverage what's available instead of doing all the work yourself, or worse: come up with a half-baked solution that's so easy to crack you could just as easily send everything in cleartext..... don't under estimate the complexity and amount of code needed to handle even the most basic security scenarios - WCF does this all for you - for free and in a reliable and safe manner - use it! You won't regret it!

Well, with WCF you could use Password credential at message level and SSL at transport level, which I think would be enough in your case.
See here.

For message security, your client provides some credentials and server provides some credentials. For this setup and with your scenario could you not use the client username and password with a Custom Username Validator, and a server certificate to provide the server credentials. This Application Scenario provides a fair chucnk of the configuration setup you would need to achieve this, except the aspNet membership sections, which you would have to replace with your custom validation config.
You would still need valid certificates on your servers (no certificates required on the clients), but I can't see any way around this.

Take a look at the following sample:
http://www.codeproject.com/KB/WCF/wcfcertificates.aspx
It uses certificates but without a certificate store - so no setup is necessary.

Hmm.. maybe something simple could be used. Move the encryption from software to hardware. VPN from each client network to your own and then you can do whatever you like for WCF transport. The line is not clear text and the problem is solved.
Of course this is easier said than done, but most network vendors provide a pretty easy VPN config and it maybe easier than trying to develop an installer for SSL certs and configure the client.
I hope it helps!

Related

WCF Service with Message Level Encryption over HTTPS

I have seen one or two questions about this but no definite answers. I have a customer requirement to implement a WCF-based client/server solution using Message Encryption AND HTTPS. I understand that WCF doesn't support this as standard, and the options are HTTP with Message Encryption, HTTPS without Message Encryption, or HTTPS with Message Credentials.
None of these will satisfy the customer requirement. I have control over both the service and the desktop-based clients. The service is hosted at my location and the clients access it over the internet.
I have dug around for days (and nights :( ) trying out custom bindings and so on, but whenever I try to combine message encryption with Https, I come up against this error:
"The binding contains both a SymmetricSecurityBindingElement and a secure transport binding element. Policy export for such a binding is not supported."
I would prefer to user username/password for authentication but I am prepared to use client certificates if this makes it possible. So far I haven't found any combination which is acceptable to WCF.
Is there any way to achieve this or am I just wasting my time? I would value a quick answer because my customer's deadline is drawing very near!
Thanks!
According to this, the special both mode for security (meaning both message and transport) is only supported in the NetMsmqBinding binding, which I'm guessing, is not an option for you. Does your client happen to be the NSA? (Just wondering why anyone would need their communication encrypted twice).
OK I've found a solution ...
Using IMessageInspector I intercepted the incoming and outgoing messages so that they can be encrypted and decrypted. Encryption uses a symmetric technique - best because asymmetric only allows encryption of short strings and is very slow.
The downside is that both ends need to have the private key of the certificate - so the cert needs to be installed on both client and server machines (or the key could be placed in config). This works for me though because the number of users is limited and all are under the control of the IT dept.
If I had more time I would have looked at setting up a second SSL connection with a different cert, purely to handle the certificate negotiation and avoid placing the cert on the client machine. Using SslStream was a possibility but I wasn't sure whether I could access key information to use for my own encryption, or whether this is held privately within SslStream class.
For now I'm just pleased to have it working before my deadline (only just though :) ) ...

Add RSA based encryption to WCF service without certificates

I am looking for a way to encrypt messages between client and server using the WCF. WCF offers a lot of built in security mechanisms to enrcypt traffic between client and server, but there seems to be nothing fitting my requirements.
I don't want to use certificates since they are too complicated, so don't suggest me to to use certificates please. I don't need confidentiality, so I though I'll go best using plain RSA.
I want real security, no hardcoded key or something. I was thinking about having a public/private keypair generated every time the server starts. Both keys will only be stored in RAM.
Then wen a client connects it should do exactly like SSL. Just as described here.
1.exchange some form of a private/public key pair; the server generates a key pair and keeps the private key to itself and shares the public key with the client (e.g. over a WCF message, for instance)
2.using that private/public key pair, exchange a common shared secret, e.g. an "encryption key" that will symmetrically encrypt your messages (and since it's symmetrical, the server can use the same key to decrypt the messages)
3.setup infrastructure on your client (e.g. a WCF extension called a behavior) to inspect the message before it goes out and encrypt it with your shared secret
That would be secure, wouldn't it?
Is there any existing solution to archive what I described? If not I'll create it on my own. Where do I start best? Which kind of WCF custom behaviour is the best to implement?
EDIT:
As this is NOT secure, I'll take the following approach:
When Installing the server component a new X509 certificate will be generated and automatially added to the cert store (of the server). The public part of this generated certificate will be dynamically included into the client setup. When running the client setup on the client machine the certificate will be installed into the trustet windows certificate store of the client.
So there's no extra work when installing the product and everything should be secure, just as we want it.
You've said you don't want to use certificates. I won't push certificate use on you, but one thing you are missing is that certificates serve a purpose.
A certificate proves that key you are negotiating an SSL connection with belongs to the entity you think it belongs to. If you have some way of ensuring this is the case without using certificates, by all means, use raw keys.
The problem is, in step 1:
1.exchange some form of a private/public key pair; the server generates a key pair and keeps the private key to itself and shares the public key with the client (e.g. over a WCF message, for instance)
How does the client know that the public key it received from the server wasn't intercepted by a man-in-the-middle and replaced with the MITM's key?
This is why certificates exist. If you don't want to use them, you have to come up with another way of solving this problem.
Do you have a small, well-known set of clients? Is it possible to preconfigure the server's public key on the client?
Alexandru Lungu has created an article on codeproject:
WCF Client Server Application with Custom Authentication, Authorization, Encryption and Compression
No, it would not be secure!
since there's no confidentiality, an attacker could do a men in the middle attack, and all the security is gone.
The only real secure way of encrypting messages between server and client IS to actually use digital certificates.
I'm sorry, the only two methods of providing secure communications are:
Use a public key infrastructure that includes a chain of trust relationships, a.k.a. certificates
or
Use a shared secret, a.k.a. a hardcoded key.
Nothing else addresses all of the known common attack vectors such as man-in-the-middle, replay attack, etc. That's the hard truth.
On the other hand I can offer you an alternative that may alleviate your problem somewhat: Use both.
Write a very, very simple web service whose only job is to generate symmetric keys. Publish this service via SSL. Require end user credential authentication in order to obtain a symmetric key.
Write the rest of your services without SSL but using the symmetric keys published via the first service.
That way your main app doesn't have to deal with the certificates.

How secure this signature based authentication for mobile devices is

I am implementing an app where I don't have a system requiring username and password. What I do require is a name and a phone number.
The scenario is like this:
1) user opens the app for the first time
2)app makes a request to my server and gets a unique UserKey
3)from now one any request the app makes to my REST service also has a signature. The signature is actually a SHA(UserKey:the data provided in the request Base64Encoded)
4)The server also performs the same hash to check the signature
Why I don't use SSH:
not willing to pay for the certificate
I don't need to send sensitive data like passwords, so I don't see the benefit of using it
I just need a simple way to call my own WCF REST services from own app
I understand that there is a flow of security at step2 when the UserKey comes in cleartext, but this happens only once when the app is first opened. How dangerous do you think this is?
What would you recommend? Is there any .NET library that could help me?
Actually, there are several problems with that approach. Suppose there's man-in-the-middle whenever you make a request to the server. By analyzing, for example, 100 sent packets he would recognize similar pattern with signature in your requests. Then he would forge his own request and add your signature. The server checks the hash - everything's alright, it's you and your unique user key. But it's not.
There's a notion of asymmetric keys in cryptography which currently is really popular and provides tough security service. Main concept is the following: server generates two keys - public and private; public key is used to encode texts; they can be decoded only with the use of private key, which is kept by the server in secure location. So server gives client the public key to encode his messages. It may be made double: client generates public key and gives it to the server. Then server generates keys and gives encoded with client's public key his own public key. This way it's almost impossible for man-in-the-middle to make an attack.
Better yet, since the problem is really common, you could use OAuth to authorize users on your website. It is secure, widely used (facebook, g+, twitter, you name them) and has implementations already in variety of languages.
Since you control both the application itself and the webservices, you can do this with SSL (which gets rid of the problems with your current approach) without paying for anything. You can create a self-signed certificate and install that on your webserver; configure the SSL context of your client application to only trust that one certificate. Then, create a client-side self-signed certificate and install that within your application. Set the server up to require mutually-authenticated SSL and only allow your self-signed certificate for access.
Done. You client will only talk to your legitimate server (so no one can spoof your server and trick the client in to talking to it) and your server will only talk to your legitimate clients (so no one can steal information, ID, etc). And it's all protected with the strong cryptography used within SSL.

WCF - Authenticate the client with Message Security using Certificates

Hopefully a quick question.
I want to secure my WCF service that will be consumed by a known party. Our organisation trust theirs and vice versa.
This service is already restricted by IP address, so we know the caller must have come from their network.
However I would like it to be protected against malicious developers within that organisation. In theory they could write a Bad App and install it anywhere on this network, and call our service, which would return the data.
I think a way around this would be to also use Client Certificates, which would be validated using Peer Trust. Each request would send this certificate, which we would validate on the WCF service, and send back the data.
My question - is this going to protect against the malicious developer scenario outlined above? We would know that the request would have to originate on the server with the client certificate installed (right?) - and I imagine it should be difficult for a malicious developer to get a Bad App on there. It is a shame we can't tie it down to exactly the client application - or could we?
Any help appreciated - just want to make sure I nail my understanding of this!
If you will be granting access to your service based on the specific incoming client certificate, it should be as secure as the private key of that certificate. That is, if the private key is kept safe in the other organization, your service will be as safe (as safe as that public/private key pair of the certificate in terms of encryption).
If the private key is compromised within the other organization, for example, an attacker has access to it on the remote server, or is able to copy it to another remote server, then that attacker has access to your service. Because, once they have the private key, they can use the client certificate to connect using an SSL connection, and then they just have to pass the IP address check. Protect the client certificate's private key.
You may check on the service side if the client has authenticated itself with specific certificate. You may also write Custom Certificate Validator and validate certificate according to your own needs. However, if you assume that the attacker may be able to use private key of trusted certificate in your environment, then I guess you may assume that the attacker can basically do anything and there is no way you can secure your service.

Verifying caller/server in WCF

My scenario:
Many WCF clients which are in environments outside of my control
Server will either be mine OR in an environment outside of my control
So worst case the client and the server is outside of my control. More specifically, I might assume that someone hosting this code could try to maliciously impersonate either the server or the client (the server being more likely). However, the client needs to verify that the server is my code and the server needs to verify that the client is my code. I've seen all the recommendations to use certificates; however, is that an option given my scenario?
One approach I've considered is to write an IClientMessageInspector and an IDispatchMessageInspector to set and verify a custom SOAP header on both sides. I would create an HMAC signature based on a secret key contained within the source code (assume I have a way to keep this hidden) and then verify the digest based on the message body.
I feel like this would work; however, I feel like there might be something more out-of-the-box that I'm missing here. Am I close, way off track? Thanks for any guidance!
Certificates are definitely the way to go in your situation.
Your server will easily be authenticated by clients because it will provide a certificate known to each client, SSL is a good option here.
The server will also be able to authenticate clients by requesting that every client should provide a certificate (server can check for a specific issuer of the certificate - your own issuer in that case).
Now you just need to correctly manage/secure your certificate server to make sure that it won't be compromised.
I don't think there is anything out of the box to do this, simply because it is an unusual requirement for the server to verify that the code on the client calling the service is authorized code.
Generally, it is sufficient to establish trust as follows:
Server has a certificate and service uses SSL - this way clients are confident that they are connecting to the correct server machine.
Clients provide authentication details (eg username/password, certificate etc) to the server so the server knows the connecting client can be trusted.
You are attempting to go the extra step to verify that not only are the users/machines verified, but also that the code running is verified - this is simply overkill. If the code running is not verified, either:
One of the machines has been compromised, in which case you have bigger issues to worry about.
One of your users has written code against your service and is using it 'illegally'. This should not be a problem if your service only allows authorized users to perform 'dangerous' operations.