How to protect your HTTPS communication from Man-In-the-Middle's decryption in Windows Store App
[Update Feb.24 2014]
There might be a mechanism change of the certification trust logic recently. Check out our second post for the topic https://blogs.msdn.com/b/lighthouse/archive/2014/02/24/part-ii-how-to-protect-your-https-communication-from-man-in-the-middle-s-decryption-in-windows-store-app-about-which-certificate-should-be-included-for-exclusive-trust.aspx before going further.
Background:
Months ago we got a report that a bad guy was accusing one Windows Store app provider of transferring the user credential in plain text, which was quite a big news because we've trusted the app provider, our life has been relying on it for more than 10 years and our Windows Runtime/ Windows 8 platform for more than one year:)
We definitely did not believe that the app could make such regretful and basic mistake. After a quick research, the real thing was that, every single web traffic from their apps is using HTTPS channel with SSL encryption. The accuser was using a special tool acting like a Man-in-the-middle attack to hack the https traffic and read out the credentials.
The tool is a widely used http debugging tool named ‘Fiddler’. However, it could just act a local proxy that monitors the traffic sent from local machine, i.e. I will never be able to capture your encrypted https traffic, but I could only use this tool to decrypt my own https traffic. Whatever HTTPS site we visit from any browser, we can use this tool view the crypted traffice from our local machine easily.
Read Decrypting HTTPS –protected traffic function to get know how fiddler performs the ‘Man-in-the-middle attack’ that generates a fake HTTPS certificate to the client and enables us to debug https traffic.
Actually the problem can also reproduce on the same apps on other platform, and other parties’ apps using HTTPS. The accuser has never mentioned those facts but just blame on this app on windows 8. The accuser had never mentioned what he did with the tool but just blamed and commented in the app's store page. So it turned out that it was just a fabricated trap for some dirty reason.
It seems that we've known the reason, and we did nothing wrong, but is there anything further we can do to protect the https communication even from the bad man in the middle?
Research:
Our MSFT engineers focused on the technical side to find out possible workaround to prevent the accusation. In fact, we are not able to prevent the traffic from being captured by the “man in the middle”, but technically we can detect if there is a “man in the middle”. What is challenging us is that, we got APIs working on traditional desktop app, but so far we don’t have equivalent implementation on WinRT for Windows 8 Store app.
Initially we were seeking for a way in WinRT to certify the remote SSL certificate, like what RemoteCertificateValidationCallback does on traditional .Net platform. Unfortunately till end we had not found any equivalent API level support that can help verifying remote SSL certificated in Windows Store App.
How about a solution on the configuration level?
Solution:
The reason why the Fiddler can decrypt the HTTPS traffic is because that it puts a Fiddler's own certificate in our Windows's trust root, and by default Our Windows Store app inherits our Windows's trust root.
If we can cut off the trust chain and just make an exclusive trust, we can get things done. Referring to this article SSL server authentication using application specific trusted roots -
You can write a Windows Store app that uses its own trust anchor rather than inheriting from system trust. When your app is installed, you can use the manifest to specify that the root certificate also be installed in a private store, and the app can use the root certificate to establish a secure HTTPS connection to the web server. The root need not be trusted through the Microsoft root program. The root is trusted only for your app and does not affect trust for other applications on the system.
And Setting the certificates extension -
The Certificates extension enables you to install certificates with the application, specify whether to inherit from system trust, and set certificate selection criteria.
So the solution is to make our app exclusively trust the public key certificate that applies to HTTPS destination domain in the application level. Checkout the screen shot in app manifest file. In the Solution Explorer windows of your VS project, just set the cer file to "build action = content, copy if newer":
How to get the Certificate that we need to exclusively trust
In this test case, the .cer file in my example was just from a self-generated certificate. How can we get the really one we needed for the production scenario? Go ahead to ask your website admin! However, If the admin is not friendly enough, we can do it by ourselves via IE or any other mainstream browser -
In IE, when we navigate to a web page that enables SSL, we can see a lock icon in the address bar. Click the lock, we can then view the certificate-
Click the View Certificates button to get to the certificate dialog, we can see Common name that the certificate issues. Some SSL certificates use the Common Name with wildcard, like *.domainname.com. If the CN also applies to the HTTPS Uri that we need to talk with in our Windows Store App, put it into our Store app's manifest configuration.
Make a test case to reproduce the problem and verify the solution
1. Config fiddler:
a. https://www.fiddler2.com/fiddler/help/httpsdecryption.asp to enable decryption https traffice
b. https://blogs.msdn.com/b/fiddler/archive/2011/12/10/fiddler-windows-8-apps-enable-loopback-network-isolation-exemption.aspx to enable monitor Win store apps.
2. Build a Windows Store app sample. Let's make a simple HTTPS call by HttpWebRequest or HttpClient to our partner portal https://mspartner.microsoft.com/en/us/Pages/index.aspx
1: HttpClientHandler msgHandler = new HttpClientHandler ();
2:
3: using (HttpClient httpClient = new System.Net.Http.HttpClient(msgHandler, true))
4:
5: {
6:
7: try
8:
9: {
10:
11: var response = await httpClient.PostAsync(HTTPSURL, new StringContent(DateTime.Now.ToString()));
12:
13: var responseStr = await response.Content.ReadAsStringAsync();
14:
15: }
16:
17: catch (Exception ex)
18:
19: {
20:
21: }
22:
23: }
3. Try the following test cases:
Follow my previous steps to get the Certificate, put it in the app project, make it as exclusive trust, build and run the app:
-
- Close Fiddler. The https call is sent successfully.
- Open Fiddler. The https call is expected to be failed with HttpRequestException {"The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel."} , which means that if there is a man-in-the-middle attempts to insert fake cert and decrypt the https traffic, our store app will throws the exception and protect your data.
Remove the certificates in app manifest > capability tab, uncheck the “Exclusive Trust”.
-
- Close Fiddler. The https call should be sent as normal.
- Open Fiddler. The fiddler should be able to capture the HTTPS traffic if we configured it properly. Fiddler is acting a man-in-the-middle role and has already put a fake cert into your OS’s cert store.
That's all.
-Ranger
Comments
- Anonymous
October 17, 2013
That was a great case study read after a long time. I learnt new stuff and that makes me a lot happy. Thank You