We have developed a .NET 4.5 application that runs an embedded (OWIN) webserver on localhost.
Some of its functionality requires us to make AJAX requests to that webserver from a public website on the Internet.
The problem is that that site uses HTTPS. Chrome now complains that there is unsafe content being loaded (which is correct).
To solve this, we would need to have our embedded webserver use SSL, so that there is no HTTPS-HTTP traffic. There are plenty of examples online of creating a self-signed certificate and binding that to a port, but our application needs to be distributed as well.
Is it possible (and how) to create a self-signed certificate for localhost (OWIN) that is actually redistributable?
I understand that this means that the connection is not trusted, because it's not verified by an SSL Authority, but we're only trying to use it so that there is no cross-protocol communication between the localhost and the public website.
We solved this in the end;
We are using SignalR and we distribute/install a certificate on the clients that is bought specifically for this purpose.
So our setup installs both the application and the certificate and binds it to the OWIN server. We got most of the information on how to do this via this blog:
https://weblog.west-wind.com/posts/2013/Sep/23/Hosting-SignalR-under-SSLhttps
It contains a detailed step-by-step description on how to get this to work.
EDIT:
Binding the certificate to the port is done by using the netsh command. We use InnoSetup to execute this for us. Info on how to do this is here.
Please note that we use a single certificate, and the command needs the certificate key in order to bind it.
This might be an issue using multiple (different) certificates, I'm not sure if it's possible to extract the key from the certificate to dynamically issue the command for different certificates. For a single certificate we had only a single key, and that was hardcoded.
It might be possible to extract the key, this is some info that might help in that regard.
Related
I have an application that can be downloaded from my website and run on user PC. This application doesn't do anything special and just allows the web page to access the scanner. It uses SignalR for communication.
Basically, I run SignalR server under WinForms application and have javascript client that tries to access it through http://localhost:8084/signalR.
Everything works fine when I use HTTP version of the web application, but fails, when I use HTTPS for my web application: Most of the browsers don't allow unsecured connections from a secure page.
So, I've created a self-signed certificate that is installed on user system during installation and it works fine for Chrome, IE and Opera, but fails for Firefox and Edge.
So I was thinking, is there a better way to access SignalR applications that are running on localhost from webpage under https?
There isn't a better way. You are correct in your understanding that "[m]ost of the browsers don't allow unsecured connections from a secure page". I believe there isn't a browser that will allow this. Therefore if you want to call out from a secured website, you must use a secured connection as well.
I don't know the issue you're experiencing with Edge, as I can confirm that it does work. Firefox will NOT trust a certificate in the cert store, even if it is a trusted root or has a trusted root certificate. You have to manually add an exception for this certificate. Details, or at least information that will let you find the correct method to do this, can be found here.
There are some things you have to do in order to make sure your certificate and configuration is correct. First, you have to have a well formed certificate with a public and private key and a well formed certificate authority cert with only its public key. By "well formed" I mean it must contain all information required by browsers for full trust, such as a Subject Alternative Name entry.
You can use OpenSSL to generate the CA, then use that to sign a certificate you will use for the SSL port. Export the CA's public key and the SSL certificate's public and private keys. Exporting the CA's private key is a MAJOR no no. That would allow third parties to create new certs from it and install them on your client's machine. The CA gets installed in the machine's Trusted Root Certification Authorities store. The SSL cert can go into the Personal/Certificates store.
Once you have these, you have to configure the URL/Port you will use for access and SSL using the netsh command line tool. Add a URLACL to allow the application to access the url and port (netsh.exe http add urlacl), and then assign the certificate to the port (netsh.exe http add sslcert ).
Having done all this, you should be good to go. The only real problems you should have are Chrome being very demanding about the configuration of your certificates and Firefox refusing to trust your CA certificate even though it is in your trusted certificate store. Bastard.
And for Edge, I can definitely guarantee if you do all the above it will work. If it doesn't, you need to consult the js console to see what errors it is throwing.
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.
All -
I'm using C#'s WebClient class to gain access to a resource on a remote server via https. The resource I am interested in is a file on the remote server. I'm using the following call to gain access to the file:
WebClient client = new WebClient();
client.DownloadData("https://someuri/file.txt");
When calling the above code I get the an System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.
I have manually visted the site via IE and added the cert. as a trusted issuer and can browse to the resource without an issue in IE. Does C# not use the standard windows certificate store ? or do I have to write my own CertificatePolicy?. I'd really like to use the built in authentication algorithms.
Thanks in advance.
In order to get this working properly you one can't just accept the the end certificate in the browser. You must use the cmd: mmc console to load certificates into the Machines trust store rather then just the users trust store.
Are you running this code through ASP.Net? If so, you may have to install the cert for the Local Computer, as the cert you installed for your login cant be used by ASP.net
We've been working a lot in an application developed in VS 2010, C#, and WCF. We use Transport as the security mode, and in the TransportSecurity Properties set to None and None.
We are hosting the service in IIS6. After working a lot we managed to make it work using https. The Certificate we used was a self created one, created with the selfssl.exe tool. After creating the Certificate and storing it in the "Trusted Certificates" list, we set it as the Server Certificate in IIS for our Site, and also do the "binding" between the Certificate Thumbprint and the localhost address with the 443 port, using the httpcfg tool.
Well, we also use the famous piece of code not recommended for production (we are aware of that) that enables the validation of a Certificate that is not issued by a valid Certification Authority. This piece of code we took it from the MSDN WCF Hands On Lab. In this piece of code we give it the CN=NAME of the certificate and it works.
Ok, we finally got it to work. This was all in development. Now we are in the testing stage and they agreed to use the piece of code that enables the certificate. The problem is that the Certificate that we need to use, after setting it in the IIS and setting it to use the famous piece of code, it doesn't work.
The error we get is this one (only showing the first part of the error and not the stack trace):
System.ServiceModel.Security.SecurityNegotiationException: Could not establish trust relationship for the SSL/TLS secure channel with authority '172.30.224.46'. ---> System.Net.WebException: The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel. ---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.
The new Certificate is issued by their own Certification Authority, and it has several differences in comparison with our Self-Generated one, for example the "Usage" properties are different, or for example our Certificate has a "Enhanced Usage" property and theirs don't.
The other great difference we notice in the Certificate is that theirs is part of a hierarchy of Certificates, where they have a Trusted Root Certificate, then an Intermediate Certification Authoity and the Certificate to use in the Server is under that Intermediate one.
Is a special configuration needed to support this kind of certificates that are part of a hierachy? What can you guys tell us about this? .... we need some help :S
We also made a test creating a Self-Signed Certificate and all the steps needed to set it up in their environment, and the application works.
Thanks for your help and attention,
Andrey Gonzalez
Usually you get this error when the server name stored in the certificate is different from the hostname you use on the client to refer to the server.
For example, your server certificate is issued for "yourserver.com" and you are trying to access it from the client using only "yourserver" or its IP address.
I'd like to use client certificates to verify the identity of administrative callers to my web service. Then I can issue certificates only to the people I want to call my web service and be pretty sure noone else can call it. This is in a very controlled scenario where only one or two people will get the client certificate, so distribution isn't a hard problem.
This article provides a good example of how to call a web service using a client certificate.
But how can I check details of the client certificate from within my web service? This old article talks about configuring IIS to do it, but I'd like to do it programmatically within my app. I think?
thanks for any suggestions!
The incoming Request has a ClientCertificates collection that you can interrogate -- you can check the various fields in the cert or check the actual raw byte data (perhaps against a datastore or other source) if you want to completely validate it.
Note, if you issue the certs from your own private CA, you will need to install the CA's cert on your webserver into a store that is visible to all users, otherwise IIS won't request those certs from the user (due to the nature of how the server/client interaction works.)