如何在Windows商店应用中防止HTTPS通讯被中间人攻击解密?

背景

几个月前,我们这里接到一份消息,有个人评论一家业内著名的Windows Store开发者使用明文传递用户账号信息。这是一个很震惊的问题,我们无法想象这样一家著名的开发公司也会犯如此低级的错误。我们的生活早已离不开这家公司开发的软件,当然也离不开Windows 8。

在紧急的研究之后,我们发现,事实并非如此,实际上,这个App是使用加密的HTTPS信道去传输信息的。而评论这条消息的人正是使用了一种类似于中间人攻击的方法,在本地破解了HTTPS的传输,并读取到了内容。

而这个工具也是我们经常使用的用作HTTP分析的工具——Fiddler。不过,这个工具仅仅只能作为本地的代理去分析从本地或到达本地的流量。虽然我们没有办法去获取到加密过的HTTPS流量,但是我们可以使用这个工具去解密本机发出的HTTPS流量,无论我们是用什么样子的浏览器。

具体细节,可以参考Fiddler官方的一篇文章,https://fiddler2.com/Fiddler/help/httpsdecryption.asp,这篇文章描述了如果使用中间人攻击的方法,采用一张伪造的HTTPS证书来分析HTTPS流量。

其实,回到最初的问题,这个评论人提到的问题是可以在此App的不同平台版本下重现的,当然,也可以在其他软件中重现。而这位“怀有恶意的”评论人并没有提及这些事实,仅仅针对于Windows 8 Store版本。也使得我们不得不怀疑,这位评论人究竟出于什么样的原因编造了这样的事情。

虽然我们知道了事情的经过,也虽然我们这里并没有做错什么,可是我们是不是还能做点什么,避免此类事情的再次发生呢?

研究:

作为一名MSFT的工程师,我们还是把重点放在了技术上面。通过技术去减少此类不实评论。实际中,我们没有办法阻止中间人获取到流量信息,但是我们可以探测到他们。现在我们最大的困难是,在桌面时代,我们有着很多可用的API,可是在Windows RT时代,可用的资源就变少了。

最初,我们想在Windows RT上找到一种可以远程颁发证书的方法,像是在传统的.NET平台中做得一样,RemoteCertificateValidationCallback。不幸的是,直到最后,我们也没有办法在API层面上找到可以去验证SSL证书的方法。

不过,在配置层面呢?

解决方法:

之所以Fiddler可以去解密HTTPS流量,是在于,Fiddler把自己的证书放到了Windows的根信任证书里,而我们的Windows Store App又继承信任了Windows根信任证书。

如果我们把所有的信任证书都拿掉,仅仅保留一份我们自己的证书,事情就可以解决了。灵感来源于此,SSL server authentication using application specific trusted roots

你可以编写 Windows 应用商店应用,该应用使用自己的信任密钥,而不是从系统信任中继承。在安装你的应用之后,你可以使用清单来指定根证书也安装在专用存储中,而且该应用可以使用根证书与 Web 服务器建立安全的 HTTPS 连接。根不必通过 Microsoft 根程序进行信任。根仅受你的应用的信任,而且不会影响对系统上其他应用的信任。

还有,Setting the certificates extension

证书扩展使你能够随应用安装证书、指定是否从系统信任继承,以及设置证书选择标准。

事情变得简单了,我们仅仅需要让我们自己的App信任唯一的由我们自己颁发的证书就可以了。请看下面App Manifest文件的截图,在Solution Explorer里,仅仅需要把证书文件部分设置为“build action = content, copy if newer”:

clip_image001

 

哪里获得我们需要的证书:

在我们测试中,我仅仅用到了自签名的cer证书。但是,我们怎么能得到一张在生产环境中使用的证书呢?其实,很简单,去问问看你的网站管理员!不过,如果他不是很和蔼可亲怎么办?其实我们也可以自己从浏览器中提取。

在IE中,当我们打开一个启用HTTPS的网站的时候,我们可以在地址栏前看到一把小锁。点一下这把锁,我们就可以看到一个证书,

clip_image001[6]

点击”查看证书“,弹出一个证书对话框,在这里,我们能看到证书的Common Name。有些证书使用了通配符,像是*.domainname.com。如果这个证书的Common Name正是我们Windows Store App中所要通信的地址的话,这个证书我们就可以拿来直接用。

clip_image002

最后的测试,为了验证我们的设想:

1. 首先,要先配置好Fiddler:

a. 参考https://www.fiddler2.com/fiddler/help/httpsdecryption.asp,配置HTTPS解密部分;

b. 参考https://blogs.msdn.com/b/fiddler/archive/2011/12/10/fiddler-windows-8-apps-enable-loopback-network-isolation-exemption.aspx,配置Windows Store App的监控部分。

2. 写一段简单的测试代码。仅仅做一个简单的对我们自己的合作伙伴社区的HTTP请求,用到HttpWebRequest 或者 HttpClient.

    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. 用以下案例测试:

把上一步得到的证书放到我们的工程文件里,把它设置为独占,编译并运行:

  • 关闭Fiddler,HTTPS请求发送成功;
  • 打开Fiddler,HTTPS请求发送失败,跳HttpRequestException错误”The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.“ 这说明,如果有中间人伪造了证书去尝试解密HTTPS通信的话,Store App会报错。

不选”Exclusive Trust“,把证书从App Manifest > capability标签中移除:

  • 关闭Fiddler,HTTPS请求发送成功;
  • 打开Fiddler,这时候Fiddler可以获取到HTTPS流量。Fiddler作为一个中间人角色,已经把伪造的证书放到了我们系统中去了。

就这样,结束了。祝大家晚安。

English Version: https://blogs.msdn.com/b/lighthouse/archive/2013/10/17/how-to-protect-your-https-communication-from-man-in-the-middle-s-decryption-in-windows-store-app.aspx