美文网首页
Android App 安全的HTTPS 通信

Android App 安全的HTTPS 通信

作者: jacky123 | 来源:发表于2016-07-25 11:29 被阅读443次

http 与 https

https 跟 http 的最大区别在于 https 多加了一个保障通讯安全的层.


  • https协议需要到ca申请证书,一般免费证书很少,需要交费.
  • http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议。
  • http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
  • http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

SSL 证书

Transport Layer Security
Secure Sockets Layer 其实它就包含俩部分:

  1. 一个身份标识, 一个用来识别身份的东西, 有点类似警察叔叔通过护照或驾照查你的身份;
  1. 一个公共密钥, 这个用来给数据加密, 而且只有证书的持有者才能解密.
    SSL 证书就俩个功能, 身份验证跟保障通讯过程中的数据安全.

另外还有一点很重要. 那就是一个证书可以给另外一个证书“签字”. 用 layman 的话说就是 Bob 用他自己的证书在别的证书上盖上 “同意” 两个红红的大字. 如果你信任 Bob (当然还有他的证书), 那么你也可以信任由他签发的证书. 在这个例子中, Bob 摇身一变, 成了证书颁发机构(Certificate Authority). 现在主流的浏览器都自带一大堆受信任证书颁发机构(trusted Certificate Authorities)(比如:Thawte, Verisign等).

浏览器是怎么使用证书的

笼统的讲, 当你打开下列连接的时候 “https://www.yoursite.com” :

  1. 服务器会给浏览器发一个证书.
  1. 浏览器会对比证书中的“common name”(有时也叫 “subject”) 跟服务器的域名是否一样. 例如, 一个从“www.yoursite.com” 网站发过来的证书就应该有一个内容是 “www.yoursite.com” 的 common name, 否则浏览器就会提示该证书有问题.
  2. 浏览器验证证书真伪, 有点像门卫通过证件上的全息图辨别你的证件是不是真的. 既然在现实生活中有人伪造别人的身份. 那么在网络世界也就有人造假, 比如用你的域名“www.yoursite.com” 来伪造一个安全证书. 浏览器在验证的时候, 会检查这个证书是否是它信任机构颁发的, 如果不是, 那么浏览器就会提示这个证书可能有问题. 当然, 用户可以选择无视警告, 继续使用.
  3. 一旦证书通过验证 (或是用户无视警告, 继续使用有问题的证书), 浏览器就开始利用证书中的公开密钥加密数据并传给服务器.

TLS (SSL)中的加密

一旦服务器发过来的证书通过验证, 客户端就会利用证书中包含的公共密钥加密某个指定的共享密钥, 然后发给服务器. 这个加密过的共享密钥只能用服务器的私有密钥才能解密(非对称加密), 别人无法解密出其中的内容. 服务器把解密出来的共享密钥保存起来, 供本次连接会话专用. 从现在开始, 服务器跟客户端之间的所有通讯信息都用这个共享密钥加密解密(对称加密).


漏洞描述

对于数字证书相关概念、Android 里 https 通信代码就不再复述了,直接讲问题。缺少相应的安全校验很容易导致中间人攻击,而漏洞的形式主要有以下3种:

  1. 自定义X509TrustManager。在使用HttpsURLConnection发起 HTTPS 请求的时候,提供了一个自定义的X509TrustManager,未实现安全校验逻辑,下面片段就是常见的容易犯错的代码片段。如果不提供自定义的X509TrustManager,代码运行起来可能会报异常(原因下文解释),初学者就很容易在不明真相的情况下提供了一个自定义的X509TrustManager,却忘记正确地实现相应的方法。本文重点介绍这种场景的处理方式。
TrustManager tm = new X509TrustManager() {
    public void checkClientTrusted(X509Certificate[] chain, String authType)
            throws CertificateException {
              //do nothing,接受任意客户端证书
    }

    public void checkServerTrusted(X509Certificate[] chain, String authType)
            throws CertificateException {
              //do nothing,接受任意服务端证书
    }

    public X509Certificate[] getAcceptedIssuers() {
        return null;
    }
};
sslContext.init(null, new TrustManager[] { tm }, null);
  1. 自定义了HostnameVerifier。在握手期间,如果 URL 的主机名和服务器的标识主机名不匹配,则验证机制可以回调此接口的实现程序来确定是否应该允许此连接。如果回调内实现不恰当,默认接受所有域名,则有安全风险。代码示例。
HostnameVerifier hnv = new HostnameVerifier() {
    @Override
    public boolean verify(String hostname, SSLSession session) {
     // Always return true,接受任意域名服务器
     return true;
    }
};
HttpsURLConnection.setDefaultHostnameVerifier(hnv);
  1. 信任所有主机名。
SSLSocketFactory sf = new MySSLSocketFactory(trustStore);
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

参考资料

相关文章

网友评论

      本文标题:Android App 安全的HTTPS 通信

      本文链接:https://www.haomeiwen.com/subject/gdugjttx.html