What do I need to secure communication between Client, Server, AdminConsole (on another Client Computer).
I've the following scenario:
AdminConsole (Client2) perform some action (call WCF Server) --> WCF Server (handle action and transmit it to the specific client via another WCF call) --> Client1 (with WCF Service in Windows Service)
Do I have to create for all Clients like Client1 a SSL certificate?
-> So for 100 clients = 100 client SSL certs?
Or is it enough to secure just the WCF Server with a SSL certificate?
To a degree it depends on what you're trying to do.
If you simply want the client to know its connected to the right server and make the communication confidential and with guaranteed integrity (no one can change things without you knowing) then you just need an SSL cert on the server
If you need the server to know who the client is so it can do audit / authorization then the client must have some way to identify itself to the server. There are a number of options here depending on your requirements from Windows credentials, to custom usernames and password, to client certificates to SAML tokens
You only need an SSL certificate for the Server - each client doesn't need one :)
Related
I have client and server application on C#. The client and server contact each other through a network socket.
I need pass some data from the client to the server. I used binary serialization for it, but I need to check that the users who starts the client part have permission to do that on the server part.
Only sending the user name is not enough, because it could be compromised.
Maybe it should be able to do with serialization of WindowsIdentity.GetCurrent(), but I couldn't do it.
How do I send credentials from the client to the server and check it on the server side? Is it possible?
I am using WebClient to implement a secure account check before a customer can use my application. but what I am worrying about is "does connecting to a website that uses SSL Certificate using HTTPS protocol prevent MATM attack and makes the whole communication encrypted ?".
In another words: will some programs like Wireshark be able to get the requests and responses in plain text as with using normal HTTP requests ? and is there an ability to alter the sent and received packets ? in order to change my application behavior or something.
[NOTE] I am not talking about getting my application pirated as I know that there is no way to get away from that fate.
HTTPS does prevent Man in the middle attack, as long as both sides are implementing the protocol properly and I assume that WebClient is implemented properly.
That means that even wireshark that is installed on your local box won't be able to decrypt the traffic
If someone in the middle would alter packets on their way, the other side won't be able to read them and the communication would break.
Some clarification given our discussion in your comments:
The above holds if your client is not compromised (HTTPS does work), since you are assuming that your clients will compromise themselves and use tools that will cheat your application by adding fake trusted certificates (which requires admin rights), I can suggest you to use two way ssl.
The tools that I know like Fiddler won't be able to decrypt this just by adding their trusted certificates, thus making it more difficult for your clients to attack your application this way, and bring them to use a debugger or patch it, because it is easier than implementing a two way ssl proxy.
You can also do what's described in this post to override the framework's certificate verification with code that expects one specific certificate and ignores the system's trusted certificates, which is compromised by tools like Fiddler (this implements What Mark suggested).
HTTPS encrypts the transmitted data and prevents man in the middle attacks by authenticating the HOST you are connecting to. However, in regards to a desktop application and also a web application, the user can use wireshark or an http proxy to view the contents of the https transmissions on the local host.
A way to mitigate this problem is to hard code the thumb print of your server cert so that you r application can encure that the server it's connecting to is presenting a specific certificate.
An example, would be if you were to install Fiddler on your local box and install the fiddler root certificate. Your application would think it's securely connecting to the server, but fiddler would be in the middle decrypting traffic. If your application code looks for a specific certificate thumbprint, you can throw an exception when a certificate other than the certificate you expect is used to connect, thus preventing the transmission of any data when a local proxy is in use.
Wireshark will always be able to see the packets being transmitted over the network but you won't necessarily be able to see the contents of the transmission unencrypted. However I'm not an expert in using Wireshark, so maybe someone else here can expound on that.
UPDATE
Ok to clarify more.... this question is discussing the encryption of contents being sent from a desktop application to a server.
Let's layout some assumptions:
The user of the desktop application, controls their desktop.
The application installed on the desktop is using a public key to encrypt.
Anyone with the corresponding private key can decrypt.
Since the user controls their desktop they can also run an http proxy on their desktop.
Now the way SSL(HTTPS) works is that your browser starts a secure handshake, at which point the server will return the public certificate, and your browser will attempt to authenticate that certificate with the authority you puchased the certificate from like (godaddy, geotrust, or versign, etc)
Assuming the user installed fiddler and it's root certificate, your desktop application would connect to fiddler, and be served fiddlers public root certificate, which it would validate against the locally certificate store and deem it trusted. Fiddler would then contact the server, which would send it the real public certificate.
Subsequently your http request from the browser is encrypted by the browser using the fiddler root public key, fiddler then decrypts the contents, and then reencrypts it using the public key from your server (mydomain.com) and forwards the request to the server, which then decrypts it and processes it.
Here is more information: http://en.wikipedia.org/wiki/HTTP_Secure
SSL offloading(https://f5.com/glossary/ssl-offloading) is also a feature used in network infrastructure for offloading the SSL load on other devices than web services. This is a form of man in the middle decryption of content. Also, Instrustion Detection systems in enterprise networks can have SSL certificates installed in them allowing these devices to decrypt the contents of requests and inspect them for behaviors indicative of network attacks.
When using C# and TCP, what is the best approach to let a client identify himself using a username and password and then allow multiple packets to be sent from the server to the client and from the client to the server without sending the username & password each time? Thread for each user? Token that's sent with each packet?
Also, how to make sure that only the client is able to read the data that the server is sending & vice versa? Just using SSLStream?
You are too low-level. What you need is an application protocol on top of TCP that supports authentication. One of the options may be HTTP. When working with .NET, the commonly used approach is leveraging WCF (Windows Communication Foundation). You can build a WCF service that will require authentication, such as “username and password” as you mention, while still being flexible about what underlying means of communication are used (e.g. SOAP and HTTP, or plain TCP and WCF's custom binary protocol, etc.).
I am writing a proxy with TcpListener in C#.
This proxy listens a port that users send request to. And when accepted a user request, it will parse the request header and find the host name. Then it creates a TcpClient to the host server.
Here comes the problem. When http request comes, it should connect the port 80 of the server; while https request comes, it should connect the port 443 of the server. But I have no idea of how to distinguish http request and https request.
Question in one sentence: how to know it is a http request or https request that TcpListener accepted?
Many thanks!
You've stepped in a problem that has flustered web server administrators for a long time.
Here's the process:
Web browser establishes a TCP connection to a particular IP on the web server.
The web server knows what IP it's getting a connection from, knows that that IP is only ever used for secure.example.com, and so loads the SSL certificate for secure.example.com.
The web server and web browser negotiate a SSL connection.
The web browser sends vanilla HTTP headers down the SSL pipe, which include the "HOST: secure.example.com" line that indicates the virtual host to use.
The web server processes the request and sends the response using vanilla HTTP headers sent down the SSL pipe.
The web server has to decide which virtual host to use before it has any HTTP headers. This is because it has to negotiate an SSL connection first, and it has to know which certificate to use first. The vanilla solution is to use IP-based virtual hosts - run the web server on IP address X; whenever the server gets a request sent to address X, it knows the request belongs to the configured vhost for that address.
The problem with that scheme is that the server has to have separate IP addresses for each secure website it runs. That might be many, many IP addresses, and is either costly or impractical.
Step in Server Name Indication. When the web browser is negotiating the SSL connection to the web server, the web browser includes the hostname it wants to connect to in the SSL negotiation information. Now the web server can use that information to do normal name-based virtual hosts, and so the web server can run a thousand different secure websites each with their own SSL certificates all on exactly one IP address. Everything is right in the world again.
You want to get in the middle of this, which means that you have to understand the SSL/TLS negotiation phase, parse the server name information, and forward the request down to the right web server.
Your new flow looks something like this:
Web browser establishes a TCP connection to the proxy.
Proxy begins recording the SSL exchange.
Web browser starts to do SSL negotiation, and as part of such, sends the Server Name Information down.
The proxy parses the Server Name Information, decides which web server should handle the request, and forwards the SSL negotiation information to the web server.
The proxy does not otherwise participate in the negotiation; it reads the SNI, but otherwise is completely "pass-through".
The web browser and server complete the SSL negotiation, the server picks the right vhost, and the browser sends vanilla http headers for a request.
The web server reads the vanilla headers via the SSL connection, and processes the request.
Now that that's been said, you might realize that sticking your nose in the SSL connection negotiation might be more trouble than it's worth. Turns out a few other people have already had the same idea as you and have implemented a few programs that seem to do exactly what you're trying to do - do a search for "http sni proxy" - I came up with this: https://github.com/dlundquist/sniproxy
The headers are entirely encrypted. The only information going over the network 'in the clear' is related to the SSL setup and D/H key exchange. This exchange is carefully designed not to yield any useful information to eavesdroppers, and once it has taken place, all data is encrypted.
Update By the way After the SSL negotiation, normal HTTP headers will travel inside the encrypted stream, so there is really no difference between the two.
In my corporate environment there is a transparent proxy that requires credentials for internet access (every four hours). In my application I successfully passed credentials like this:
var client = new WebClient();
client.Credientals = new NetworkCredential("username", "password");
string result = client.DownloadString("http://...");
// this works!
However, when my intial request is to a "https://" url, there is an Exception throw: "The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel."
Now my current work around is to:
catch the WebException thrown when accessing the "https://" url
add my Credentials to a new request to an arbitrary "http://" site
(this should "open up" the internet for a four hour window)
go back and re-try the "https://" request
I am wondering if there is a better/cleaner way to do this?
What you are using right now is an HTTP proxy with authentication. So far so good. But it won't work for HTTPS requests, and here's why:
SSL/TLS is endpoint security. This means that the data must be sent between the client and the server via the single encrypted channel.
When you connect to the HTTP proxy, you tell it "GET the remote resource and send it to me", which contradicts to endpoint security. Here you don't have direct connection to the remote server and you can't validate its credentials. Also the proxy can peep into your data.
In general, it's possible to connect to regular HTTP proxy using HTTPS OR it is possible to ask the HTTP proxy to access HTTPS resource, but this breaks security cause in both cases the client can't validate server's credentials and HTTP proxy can log or alter the data being transferred.
HTTPS proxy works in a different way. Here you tell the HTTPS proxy server "CONNECT to remote address and then only resend whatever is passed". This way the proxy creates an opaque secure channel between the client and the server thus preserving endpoint security. Actually, HTTPS proxy can be used to tunnel any traffic, not necessarily SSL.
Consequently you need to establish the tunnel by sending CONNECT request (with your authentication included), and then send regular HTTP GET (without host/address in the URL) over the same channel - this request will go to the destination server, not to the proxy.
I have serious doubts that your WebClient can be made to establish a tunnel before sending a request. As an option, you can use HTTPBlackbox package of our SecureBlackbox product which lets you access HTTP and HTTPS resources, and supports HTTPS proxies (called WebTunneling in SecureBlackbox) with authentication.