I'm running IIS 7.5 on Win2k8, and am trying to configure 2-way SSL. I've turned Require Client Certificate on in IIS, I've installed a valid root certificate in my local machine's trusted root store, and I've installed the server cert and configured IIS to use it.
When I first tested this configuration, I was able to connect with a valid cert, and unable to connect with an untrusted cert. So far so good. However, when I revoked a user cert, that user was still able to gain access to the website using the revoked certificate.
I read that the server may have been using a cached copy of the CRL, so I used "certutil -setreg chain\ChainCacheResyncFiletime #now" to clear the cache, reimported my CRL into the Intermediate Certificate Authority store, and tried again. This time, the server rejected ALL attempts to connect, including those with valid certs, returning 403.13 and "The revocation function was unable to check revocation because the revocation server was offline."
My setup is a little unusual because the CA server is not available to my network, so there is no OCSP and no CDP. Instead, I manually import the CRL to the server whenever a new one is issued, call it once a week. So I've enabled 'Verify Client Certificate Revocation' and 'Verify Revocation Using Cached Client Certificate Only', to try to enforce checking for revocation and to prevent the server from trying to go to an unreachable CDP and thus failing the check because the server is unreachable.
Unfortunately, it looks like the server is not using the CRL I loaded into the machine store, and is instead rejecting all users because it thinks it does not have a valid CRL and cannot request a new one.
How do I get client authentication and 2-way SSL working with revocation checking when I don't have access to a CDP?
Don't inport CRLs to store manually. Make access to CDP :)
You could do this:
Find a server in your infrastructure that has connect to the CDP and also to your server.
Then either deploy new CRLs there and change DNS (or change hosts file on your server) to point to this server whenever windows/IIS asks for new CRL.
Or make this new server a proxy (I think it called reverse proxy) delegating requests for new CRL to correct destination at CDP.
Both solutions should work. The first mentioned could be somewhat harder to implement and maintain because you would have to monitor if the script (or person) really deploying the CRLs.
Related
I'm writing a VB6 application which connects with SQL Server. To secure the connection with the database I'm using MSOLEDBSQL as provider which supports TLS 1.2. I also enabled TLS 1.2 in my machine. I verified the connection status using sys. dm_exec_connections and SQL server displays all the connections are encrypted. To double confirm I tried to use the echomirage to check the traffic and the results are surprising. The data is not encrypted and I can read all the data flow as shown in the below image. My question is
This communication is really encrypted. If not why I'm seeing different status in SQL server
I read somewhere that TCP is binary protocol. If so, why I'm seeing plain text even if this communication is not encrypted?
This isn't a TDS issue (the protocol used by SQL Server). The same thing happens with your browser when you use a debugging proxy like Fiddler and trust the proxy's certificate, or configure it to use a trusted certificate. Most likely, you trusted EchoMirage's certificate during setup or through its Settings and forgot about it.
SSL/TLS protect agains Man-In-The-Middle attacks by verifying the other party through certificates. Encryption isn't enough. Without verification a proxy between client and server could pose as the other party, set up encrypted communications with each side, decrypt the packets it receives, inspect them and then encrypt them again using the other side's keys and send them along. Without verification neither client nor server would know someone intercepted the connections.
With SSL/TLS, a connection is established only if both parties trust each other's certificates. Both sides verify the certificates by checking either whether the certificate is explicitly trusted, or if it was issued by a Certificate Authority trusted by the application. If validation fails, the connection fails as well.
Fiddler, WireShark and other similar tools decrypt traffic by acting like a proxy and establishing communications on either side using their certificate. With certificate validation enabled though, the browser (or the SQL Server client) would reject the connection. If you try to connect to a web site through HTTPS while Fiddler is in use you'd get a red warning page saying that the connection isn't safe.
To allow such connections someone would have to go and explicitly trust the tool's certificate. All tools can do this through their settings, but all OSs require privilege elevation and user confirmation before they add the certificate to their trusted list.
By default, drivers and network libraries perform validation. To allow WireShark to intercept the SQL Server connection you'd have to either explicitly disable validation with TrustServerCertificate=true;, or trust the tool's certificate, which is probably something you already did and forgotten about it.
The page Using Encryption Without Validation in SQL Server Native Client in the docs explains what happens when you don't use validation, and warns against it.
If you use Encrypt=true and leave TrustServerCertificate to its default, false, WireShark or EchoMirage won't be able to intercept, much less decrypt the traffic. In this case :
Encryption occurs only if there is a verifiable server certificate, otherwise the connection attempt fails.
This is a TDS issue (the protocol used by SQL Server), and is not caused by WireShark in any way.
TLS encryption is only used during the login process to ensure that the credentials are not passed unencrypted over the network.
After that, the remaining bulk-transfer of queries and result sets are not encrypted on the wire.
In order to enable encryption for data (and not just for the login process), you need to use the Use Encryption for Data connection string keyword in your connection string:
Use Encryption for Data=true
Use Encryption for Data
SSPROP_INIT_ENCRYPT
"Specifies whether data should be encrypted before sending it over the network. Possible values are "true" and "false". The default value is "false"."
Be aware: If you enable encryption for data, and the server doesn't have a valid certificate (i.e. the default), then you will get an error when connecting. The client will detect the server presented an invalid certificate, and stop the connection. In order to make your system reliable, you need to include Trust Server Certificate=true in your connection string:
Use Encryption for Data=true;Trust Server Certificate=true
A better alternative is to turn on the option on the server that forces encryption for data, and do not specify Use Encryption for Data or Trust Server Certificate in your connection string.
When it is the server that requires the encryption, the client will not care about the certificate presented by the server (excluding MSOLEDBSQL19, which is broken by default, and you will need to specify Trust Server Certificate=true even when it was the server who wanted the encryption in the first place.
I have encountered an issue with Windows.Web.Http.HttpClient when I have multiple connections using https with different client certificates, to the same server endpoint.
I have a setup a bit like:
Connection A: connect to https://www.myserver.com/path?querystring - with the HttpBaseProtocolFilter used to create the HttpClient instance configured for 'client certificate A'.
This all works fine.
Now I create another connection, using a new HttpClient instance to the same server (different query string), and this time the filter is configured for 'client certificate B'.
This connection seems to get through to the server, but it looks like the server is getting the wrong client certificate. I have no access to the server or its logs, but from the errors I do get I wonder if perhaps it is getting 'Client Certificate A' instead.
I note the problem goes away if I put a '.' character after the '.com' part of the server name in the second connection. This makes me suspicious that there is some caching somewhere based on server name.
This is failing on a Windows 8.1 Surface tablet. It seems to work ok on my development laptop. The app I'm building is a Windows Store App, so this may also be part of the problem.
Has anyone any knowledge of how client certificates are cached, or whether ssl/tls connections are 'local' to a HttpClient instance?
Can a Windows App Store app (C#) clear/disable/disconnect any existing ssl/tls session?
Any pointers welcome.
PS: The app I'm building is a 'monitoring' app that can connect to a server using different client certificates to access different 'accounts'. The app is intended to show an aggregated view of multiple accounts, thus the requirement to use a number of different client certificates against the same endpoint. This all works for the Android/iOS version of the app, but I cannot get a Windows version working.. (oh, and the server/account access mechanism is not under my control in any way )
I note the problem goes away if I put a '.' character after the '.com'
part of the server name in the second connection. This makes me
suspicious that there is some caching somewhere based on server name.
It seems that cache behavior of http client cause this issue...
You can try the following way to turn-off the cache.
HTTPClient every time returns the same string
or following SO post also helps you.
How to stop credential caching on Windows.Web.Http.HttpClient?
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.
I have a C# console app on a Windows Server 2003 machine that sends data (over SSL) to a web service hosted on a Windows Server 2003 R2 machine. I have the entire certificate chain installed on both the Current User and Local Computer certificate stores in MMC (Microsoft Management Console).
I can hit the web service (.asmx page) in IE and Firefox just fine. I'm assuming because it uses the Current User certificate store. However, my C# app returns the following error:
System.ServiceModel.Security.SecurityNegotiationException: Could not establish trust relationship for the SSL/TLS secure channel with
authority 'www.samplewebservice.com'. ---> 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.
It's almost like the certificate isn't stored in the right "account" or "container" in MMC. I browsed through the various service accounts and they all seem to have the cert. I know .NET runs under the "NT AUTHORITY\Network Service" account but "Network Service" isn't listed under the Service Accounts in MMC. I checked the following service accounts and they all had the correct certificates (I never copied them so I'm assuming it's because they're in the Local Computer account):
Computer Browser
Network Connections
Network Manager
I'm completely stumped. It's like .NET doesn't have access to the certificates. I wish I could use a keystore similar to Java. Has anyone ever came across this?
I had a similar issue. I got around by deleting the certificates, reinstalling them and restarting both PC and IIS. Also make sure your certificatess haven't expired and are trusted in the machine's store.
Somewhere early in your processing pipeline:
ServicePointManager.ServerCertificateValidationCallback = (a,b,c,d) => true;
This is to ensure that all certificates are accepted.
Of course as John points out, such general callback could possibly be dangerous so please fine tune it so that on one hand it solves your issue and on the other hand it doesn't introduce any security issues.
I hope John is satisfied now. I should have been more talkative, and so should he :)
I am trying to access a WCF web service, that is using two way SSL encryption. When I try to call the service I get a
System.ServiceModel.Security.SecurityNegotiationException: Could not establish secure channel for SSL/TLS with authority 'XXX.xx'. ---> System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel.
I have tried activating wire shark, to see what is sent to and from the server: I see a client hello and a server hello. But there is no client response to the server hello. I was expecting a
"Certificate. Client key exchange. Change cipher. Encrypted handshake Message"
package, but none is sent. I'm thinking it is a problem with the certificate sent by the server, that somehow my client server does not trusy it.
Here is what I have already tried:
I have created the certificate, through the proper authority, though I could have made a mistake in the certificate request without knowing it.
I have added the two root certificates to: trusted root certificates, trusted publishers and trusted people. I have also added the client certificate to trusted people. My colleague has succeded in establishing connection on a win 2008 server (i'm using a 2003, because it is necessary for some odd reason - don't ask). I can't see any differences in our approach, so i'm a bit lost.
Any help would be greatly appreciated.
I resolved this issue:
It turn out that the app-pool did not have read permission on the private key of the certificate. We changed the app-pool to local system (I believe) and it resolved the problem.