Best way to connect two servers and prevent MITM attacks - c#

What do you think is the best way to connect two servers through a C# web service?
I don't want to use SSL, because it consumes to much server CPU and I don't want to add more load on the machines. And besides, it's slower.
Perhaps OAuth2, WS-Security or any custom service like sending tokens (nonce+timestamp) maybe to prevent resend attacks. Thanks for any suggestions.

My bet would still be on SSL. Use client certificates in order to verify incomming requests. It's in use on a large scale to protect sensitive information exchange and is especially well suited to protect against MITM.
The overhead of SSL will most likely not affect your CPU-usage noticably, have you measured? The handshake might be an issue if you're handling large amounts of small requests but if I understand you correctly you only have two servers and in that case that overhead (if my understanding of SSL/TLS is correct) will be amortized over the lifetime of the SSL session.
Short answer: It's unlikely that your CPU-usage will be adversly affected by adding SSL but you should always profile your scenario before jumping to conclusions.
More reading
HTTP vs HTTPS performance (StackOverflow)
How much overhead does SSL impose? (StackOverflow)

WS-Security has mutual authentication and message signing. This mode requires that the sending server has a certificate (public ky) of the receiver. The sender can then check that the response has not been tampered with by verifying the signature and can check that the signing certificate use to sign the response was the correct one for receiver.

Related

Encryption with client,server situation?

I have a Client & Server application set, both written in C# but some client versions might be distributed in other languages in the future. I want to protect my applications.
I was looking for some kind of advice to stop just random people sending messages to a server and acting like a client, what kind of validation can I put in place?
My client applications I distribute will be obfuscated but is this enough? I'm just looking for some advice in this situation, is it wise for me to add some kind of encryption other than SSL, or am I just being over protective and over curious? Any input is welcomed & accepted.
It is impossible to determine if you are communicating remotely with "your client" or another piece of software that also knows how to communicate in the way that your client does.
What you can do is ensure that you are communicating with someone that is authorized to communicate with you by using client certificates for your SSL session.
The server proves who it is to the client and the client proves who it is to your server. The security then rests in whoever holds the private key to the client certificate (and the password for this key file).
The C# SslStream Class has support for this. Namely the AuthenticateAsClient method is relevant here.
In summary, if your software is only secure when communicating with a client you wrote, then your software isn't secure period. Instead, design your server in such a way that you can serve client requests securely. Using authentication is one of these ways.
You would want to do two things....one is look up certificate pinning. Your app will validate your SSL cert to thwart man in the middle attacks and it makes it hard to circumvent. The other is when making requests to the server have some type of user name / password block on the server side script before the server side does anything so the requests will simply be discarded by the server if they are from an unknown source.

Secure Communication Between .Net Application and Website

Recently, We developed an application that we want it's users to pay for a monthly subscription in order to use it. So the first thing that came to our minds how to implement a secure way for our application to check for the User validity and those ideas came up
Using WebClient to enter to our website and Login using the user
provided credentials : However, this might be vulnerable to MITM
attack.
Using the first approach but using SSL certificate (to make sure
that we are connecting to our server and not the attackers') :
However, Fiddler can easily do a MITM attack and decrypt the SSL
communication, which will result in the same vulnerability as the
first approach.
Due to the internet's lack of documentation of what we need, we had to ask here for someone to explain how could we make sure that:
Our application only connects to our server and not any fake hosted
server (by the attacker).
The communication is secure. Not altered or edited some how in order to
grand unfair access to our application. (by sending a fake response
to the app or editing the original response before the application receives it).
Note: we totally understand that the attacker may just deobfuscate the application and do whatever he want to it. So we are planning to get a goodobfuscatorin order to at least make it harder for the attacker to do so.
You can use SSL Certificate Pinning.
Set the ServerCertificateValidationCallback to only accept your certificate's public key, or one of its signers. (this means you can never change certificates)
This will completely prevent SSL MITM (which works by using a different certificate and making the computer trust it).
Of course, it doesn't prevent attackers from cracking open your app and bypassing the check altogether, especially if you store local state.

How to create a stateful encrypted connection between two C# applications?

I am currently looking for the best way to establish a stateful and encrypted connection between a C# client and server application. First, I thought about using IPsec, but as it works on a low level (OSI: Internet Layer), I would be very hard to implement, if you want the functionality inside your program and don't want to rely on the OS.
What technologies would you recommend for this purpose? Is there some functionality already built into .NET (4.5)? It does not neccessarily have to be stateful, working with some kind of heartbeat would be a valid option, too.
You'll want to use a standard protocol such as SSL rather than trying to make your own. First the implementation will be much easier because the .NET framework will support it, and the transport protocol that runs underneath it is stateful (e.g. TCP). Second developing a cryptographic protocol that is secure is very difficult, and SSL has already been implemented so why reinvent the wheel?
SSL works by using PKI (Public Key Infrastructure) to generate a shared symmetric key. The handshake consists of a number of steps. First the client sends a request for a secure session, then the server responds with it's certificate, the client verifies the certificate by crawling up the ladder through the certificate authorities (e.g. Verisign, Thawte, GeoTrust etc...) or if it already trusts the server it can just accept the certificate that is self signed.... and once it finds the certificate is trustworthy it generates a symmetric key and picks an algorithm (e.g. AES, 3DES, RC4, IDEA etc...). The client then encrypts the key and algorithm being used with the public key, then the client sends that value to the server and a secure session can proceed using symmetric encryption which is much faster.
SSL itself is can be used in a stateful manner because it actually works over the transport layer in the OSI Model, HTTPS on the other hand is not a stateful protocol by design. HTTPS is HTTP over SSL so the two technically don't really have anything to do with each other, except that in HTTPS SSL is used to secure the application data that is being requested. With HTTPS as with HTTP once a request is made to the server it basically forgets about you (not exactly how it happens but for all intents and purposes you can think of it this way). I myself would prefer the use of HTTPS if you can get around having to have a stateful protocol. The main reason for doing so is so that I wouldn't have to write the code and possibly have a mistake in the implementation of SSL. All you have to do is build a WCF or REST based service that runs on IIS and get a certificate for your server.
That being said, if you still want to create your own SSL server that doesn't use HTTP on the application level you can use the TcpListener and TcpClient classes along with the SslStream class provided as part of .NET to create your own. MSDN has a good example of how to create an SSL server and client: http://msdn.microsoft.com/en-us/library/system.net.security.sslstream%28v=vs.110%29.aspx
Side Notes
Securing the transport of your data does not secure your app, do not make the mistake of thinking you get automatic security
If you choose to make your own server and client you can use either openssl to generate your certificate or you can use makecert which is part of .NET to make your certificate.
Just form a regular TCP connection between the applications, and write up a simple packet protocol (EG, 4 bytes indicate packet size, followed by packet data)
Except the data within this base-level packet is encrypted through System.Cryptography.AesManaged
If you have trouble encrypting the packets using AesManaged, try using The Encryptamajig - if that doesn't help, post further questions and we'll give you further specific help.
-- You can either have both sides know the password ahead of time (EG, tell the person at the other end the password in person), or quickly pass it unencrypted at the start of the connection (or, rather, encrypted with a default known password)
Not necessarily the best method but it should do the job.
Why not just the regular HTTPS? HTTP is just one level above TCP but it is far easier to work with and firewalls tend to be generally easy on HTTP/HTTPS ports namely 80 and 443. Of course, plain HTTP is not suitable for you but can you not use HTTPS instead of coming up with your own encrypted communication mechanism? In the client side (C#), all .NET classes such as HttpClient supports HTTPS very well. I quote Ayende in support of my suggestion to go with HTTP :)

Windows network authentication the right way

I am about to start on a project that will be running as a windows service listening for incoming connections and doing some things locally then sending a reply message. I understand the basic concepts with sockets and communicating over the network, however the things the service are doing could very easily abused. I would like to authenticate the person connecting, preferably against the windows local users on the machine the service is running, to see if they have windows administrative/power user rights.
I know how to do it check the rights once I have their information but I know sending the user name and password to the application over the network in the clear is a no no. I was thinking of just encrypting the password with some secret key but I know "trying to be clever" is the worst possible thing you can do in cryptography so I wanted to know what is the "correct" way to handle this situation.
My second idea was just create a shared self signed certificate between the client and the server and just use TLS for the entire connection.
I may as well post what I was thinking of doing, if it is the right thing to do say so in the comments.
Both the client and server will have a PSK at run-time the server will send a random number to the client. the client will encrypt the credentials with the PSK and the random number as the IV. It will send back the encrypted blob plus whatever commands it needs done.
I am not concerned about replay or mitm attacks. I just want to authenticate the user and not have peoples passwords blasted all over the network.
Scott,
this may be a bit overkill and a bit off topic, but have you considered using a web service interface to serve your clients (instead of using raw sockets)?
ASP .Net web service interfaces are easy to implement, and in the end, you'll end up with a very well defined interface. They also have support for authentication and secure communication.
ASP .Net Web Service Tutorial
HTTP Security and ASP.NET Web Services

Server/Client Verification?

We're considering creating a program which sends a POST request to a server-side program for some processing. We'd like to consider some sort of verification to make sure the POST request isn't a random spammer attempting to overwhelm our system or something. I don't know too much about this stuff, but I was thinking the client might send a date-num and an "encrypted" date-num (not securely encrypted, just using some special algorithm). The server would then both encrypt the date-num AND decrypt the client-encrypted date-num. If either the encrypted date-nums or the decrypted date-nums didn't match, obviously it wasn't a request from our client, so the server will not act on the request.
As I said, I don't know that much about this. Am I going about it the right way? Is there a better way? If this is an ok way, whereabouts might I go looking for "encryption" algorithms? (most of the algorithms I find are for secure-encryption and can only be decrypted on the same machine. I don't care that much about security--I just am looking for verification).
Thanks a bunch for your help.
PS I'm not sure if this is a duplicate, because I didn't really know what to search. I couldn't find any other questions about this, but that doesn't mean anything.
EDIT:
To clarify, the server code should be as "drop-in" as possible -- e.g. if it can be done using straight PHP or ASP.NET rather than mucking around with server configurations, then that would be better. Same on the client end. Keep in mind this does not have to be secure, we're just attempting to keep spammers from POSTing random data a million times.
You could use ssl and client certificates and let the webserver handle it transparently. This way both the server and the client can be (more or less) sure about whom they are talking to.
What will your webserver be? IIS, Apache, ... ?
If it's an apache take a look at httpd 2.2 docs, Client Authentication and Access Control.
If it's an IIS see Enabling Client Certificates in IIS 6.0 (IIS 6.0)
Try using a cryptographic nonce.
On the page from which the POST is launched, a random number is generated and stored in the database with the requesting IP address and an expiry time (15-30 minutes?).
The same random number is stored as a POST variable.
On POST, in order for the processing to occur, there must be a successful lookup matching the nonce and IP address before the expiry time.
Combined with a honeypot captcha, it should do a good job of preventing bots from straining your system.
The usual approach for a problem like this is the inclusion of an HMAC. It allows integrity checking and sender authentication by the use of a secret key.

Categories