I'm currently working on a project that requires encrypted data be passed between WCF hosts. As I understand it there are only 2 ways to ensure that data passed over WCF is secure.
Using Certificates
Using a Domain (or having the same username and password on every machine on the network)
Using certificates can be expensive and complicated to manage and since we're not guaranteed to have a server class machine at every deployment a Domain is also out of the question. Having every machine use the same username and password is also problematic if that password ever needs to be changed.
Currently we use OpenSSH to tunnel our connections between hosts. Is there another option built into the framework that I'm unaware of?
Encryption requires a key. Keys are usually implemented as certificates. If you own both sides of the communication, you can create your own certificate for free without having to go buy one from a trusted root authority.
Here is an alternative. Works without IIS and SSL/X509 certificates.
If you are using a http endpoint, you can use a secure transport such as https.
Use traditional encryption of the data that you are placing inside the WCF container. Maybe something like the following:
http://www.obviex.com/samples/EncryptionWithSalt.aspx
The cheapest method is probably to run your own certification authority. This means you have total control over the certificates, but you do not have to pay for external certification. If you automate this appropriately, you can give every machine on your net a cryptographic identity and use your local certification to tie everything together.
Related
I'm writing a system in C#, which consists of REST API server, written with HttpListener and WPF client app, with HttpClient and I want to use HTTPS.
As far as I know, on the server side all I have to do is run HttpListener with prefix with https and bind my certificate (creted for example with makecert) to proper port - now all communication is encrypted.
On the client side, I have to put the public part of certificate in Current User store, so that it can be trusted.
The server is not public, each client has his own instance accesible only after logging in to their VPN.
My questions:
1. Are self-signed certificates secure enough? Is generating new certificate for new client more secure(for example, from license data)?
2. How do I generate the "public part" and "private part" of certificate? How do I ship it?
It isn't a bank, so I don't want to overkill security, but I don't want to go "trust all certificates" way.
Security in general hinges on how well protected your private key is. The algorithm used can be the same as on a public signed certificate.
There is no inherit security gain or loss in using a self signed certificate.
The bigger problem is the distribution of your public key among the member systems. If you run a domain wide CA on your domain controller, it should be relatively easy.
If you do not, you might be able to do it via Group Policy.
In any case it requires admin intervention to get it to run on all your systems and again should the private key be compromised.
The problem arises should you have external clients not connected to your DC. Then LetsEncrypt is definitely the better choice.
I believe that you'll have to add the public key of the self signed certificate to the Trusted Root Certification Authorities store as well.
That is offcourse cumbersome since you'll have to do this on every client ...
Can't you use certificates issued by LetsEncrypt ?
We want to implement https to our website. But given that our team have no experience with https/ssl things, it will take us a bit time to learn how to use encrypted connection on our website.
We want to make our website the more secure as possible during the time we try to implement an SSL certificate.
So, we heard about a temporary solution we could use. Something like to ask the user (With a popup confirmation) each time he goes our website if he want to use a secure connection (Like a new certificate for each connection to our website).
I don't know anything about this "method", I don't even know what to search on google.
Is this even possible ? If yes, how you call this ?
You probably refer to self-signed certificates as the temporary solution.
To implement them you already have to implement https at your server and the only difference to "real" https is that you don't buy a certificate from an established CA, but that you create your own. In this case the browser will not trust the certificate by default and need to ask the user to trust the certificate. Of course, not all users will simply trust some stranger so expect to loose more users of your site this way than you would loose if you don't use https at all.
I asked a question here a while back on how to hide my http request calls and make them more secure in my application. I did not want people to use fiddler 2 to see the call and set up an auto responder. Everyone told me to go SSL and calls will be hidden and information kept safe.
I bought and installed an SSL Certificate and got everything set up. I booted up fiddler 2 and ran a test application that connect to an https web service as well as connected to an https php script.
Fiddler 2 was able to not only detect both requests, but decrypt them as well! I was able to see all information going back and fourth, which brings me to my question.
What is the point of having SSL if it made zero difference to security. With or without SSL I can see all information going back and fourth and STILL set up an auto responder.
Is there something in .NET I am missing to better hide my calls going over SSL?
EDIT
I am adding a new part to this question due to some of the responses I have received. What if an app connects to a web service to login. The app sends the web service a username and a password. The web service then sends data back to the app saying good login data or bad. Even if going over SSL the person using fiddler 2 could just set up an auto responder and the application is then "cracked". I understand how it could be useful to see the data in debugging, but my question is what exactly should one do to make sure the SSL is connecting to the one it was requesting. Basically saying there cannot be a middle man.
This is covered here: http://www.fiddlerbook.com/fiddler/help/httpsdecryption.asp
Fiddler2 relies on a "man-in-the-middle" approach to HTTPS interception. To your web browser, Fiddler2 claims to be the secure web server, and to the web server, Fiddler2 mimics the web browser. In order to pretend to be the web server, Fiddler2 dynamically generates a HTTPS certificate.
Essentially, you manually trust whatever certificate Fiddler provides, the same will be true if you manually accept certificate from random person that does not match domain name.
EDIT:
There are ways to prevent Fiddler/man-in-the-middle attack - i.e. in custom application, using SSL, one can require particular certificates to be used for communication. In case of browsers, they have UI to notify user of certificate mismatch, but eventually allow such communication.
As a publicly available sample for explicit certificates, you can try to use Azure services (i.e. with PowerShell tools for Azure) and sniff traffic with Fiddler. It fails due to explicit cert requirement.
You could set up your web-service to require a Client-side certification for SSL authentication, as well as the server side. This way Fiddler wouldn't be able to connect to your service. Only your application, which has the required certificate would be able to connect.
Of course, then you have the problem of how to protect the certificate within the app, but you've got that problem now with your username & password, anyway. Someone who really wants to crack your app could have a go with Reflector, or even do a memory search for the private key associated with the client-side cert.
There's no real way to make this 100% bullet proof. It's the same problem the movie industry has with securing DVD content. If you've got software capable of decrypting the DVD and playing back the content, then someone can do a memory dump while that software is in action and find the decryption key.
The point of SSL/TLS in general is so that the occasional eavesdropper with Wireshark isn't able to see your payloads. Fiddler/Burp means that you interacted with the system. Yes, it is a very simple interaction, but it does require (one) of the systems to be compromised.
If you want to enhance the security by rendering these MITM programs useless at such a basic level, you would require client certificate authentication (2-way SSL) and pin both the server and client certificates (e.g. require that only the particular certificate is valid for the comms). You would also encrypt the payloads transferred on the wire with the public keys of each party, and ensure that the private keys only reside on the systems they belong to. This way even if one party (Bob) is compromised the attacker can only see what is sent to Bob, and not what Bob sent to Alice.
You would then take the encrypted payloads and sign the data with a verifiable certificate to ensure the data has not been tampered with (there is a lot of debate on whether to encrypt first or sign first, btw).
On top of that, you can hash the signature using several passes of something like sha2 to ensure the signature is 'as-sent' (although this is largely an obscure step).
This would get you about as far in the security way as achievable reasonably when you do not control (one) of the communicating systems.
As others mentioned, if an attacker controls the system, they control the RAM and can modify all method calls in memory.
I am developing a TcpClient/TcpListener based client-server application.
Now I have come to the point where I need to authenticate the user. I could use the PrincipalContext-Class on the server side and request username/password/domain from the client, but I don't want to send the credentials over the network. Additionally, I don't want to ask the user for their credentials again.
So, I know the Citrix Receiver which supports pass-through authentication. It uses the current logged on user and does not request any credentials and authenticates the user against the server. It just works.
How can I do this in my application? I thought about some kind of token which can be sent to the server, but I could not find any solution.
Wrap the NetworkStream in a NegotiateStream, and call the appropriate NegotiateAs... methods on both client and server.
The client can specify what impersonation level to allow, and the server can specify what level it requires (minimally Identification in order to determine client identity, but if you need to access local or network resources as the client, you could also specify Impersonation or, with the right network configuration, Delegation).
Once authenticated, the server can determine the client's identity and/or impersonate using the NegotiateStream's RemoteIdentity property.
As I mentioned in my comment, I don't know how Citrix affects this setup (never having used it), but if it's basically completely transparent to the application and everything uses standard Windows credentials, then this should work.
The .net Framework does have functions for Diffie-Hellman Key Exchange:
http://de.wikipedia.org/wiki/Diffie-Hellman-Schl%C3%BCsselaustausch
http://www.codeproject.com/Articles/24632/Shared-Key-Generation-using-Diffie-Hellman
If you are writing both the client and the server parts of the application, then you can encrypt the user's credentials for passing across the network and decrypt at the other end.
Working on the assumption that on the client machine, a malicious user could extract the encryption key from your application (using strings or similar) then symmetric encryption is not suitable. Therefore asymmetric (public-private) encryption seems suitable. Generate a pair of keys and the server's key should remain private (and only on the server) and the clients' key can be included in the application on the client machines. Then it doesn't matter if the key is extracted from the app as credentials can only be decrypted with the secret and secure private key on the server. This class has done most of the ground work for you.
I'm building a system that consists of many clients connecting to a server. The clients automatically push data to the server via a web service call.
I've built an authentication mechanism in order for the clients to authenticate with the server so only authenticated clients can upload data.
The problem is that I've hardcoded the password into the client code and it is accessible if someone uses a reflector.
In this scenario, where I have no user input, what would be the best way to store the static password on the client?
Thanks
(.Net version on the client is 2.0 and the .net version on the server is 3.5)
You have a number of methods that you can use, but one of the easiest to implement would be to encrypt the password and then just store it in the app.config for the application that gets deployed to the user.
Have you looked at http://msdn.microsoft.com/en-us/library/system.security.cryptography.protecteddata.aspx?
Also, are your webservices WCF? If so, you could use mutual certificate security. It is much more robust than a password.
HTH
"I've built an authentication mechanism in order for the clients to authenticate with the server so only authenticated clients can upload data."
How are they authenticated to become "authenticated clients"?
Can someone just copy your application to their home computer and now they are an authenticated client?
This seems like a huge security oversight if you're trying to decide who can upload based on a value in your assembly.
If you can do IP based validation, if you want to avoid passwords and login mechanisms.
I would consider getting a good obfuscator for your code, for one thing. That will prevent (or at least deter) people from using reflector on your assemblies.
However, your authentication system doesn't sound too secure. Even if you did encrypt the password, if the password is always the same, it would be as easy as sniffing packets to figure out what needed to be sent to your server to authenticate. Because it would have to be decrypted before it was sent.
You'd have to go over an SSL at the very least.
Also you might want to look into using Asynchronous Encryption with Signed XML using a Machine Hash if you're installing this in some public client's environment. Something like a Licensing Scheme.
I don't know anything about your architecture or the environment you're running in, so I can't make any recommendation as to what would be the best security implementation, but I can tell you the current setup doesn't sound secure to me.