Android安全开发之安全使用HTTPS

Android安全开发之安全使用HTTPS

一、HTTPS简介

阿里聚安全的应用漏洞扫描器中有证书弱校验、主机名弱校验、webview未校验证书的检测项,这些检测项是针对APP采用HTTPS通讯时容易出现风险的地方而设。接下来介绍一下安全使用HTTPS的相关内容。html

1.1 为什么须要HTTPS

HTTP协议是没有加密的明文传输协议,若是APP采用HTTP传输数据,则会泄露传输内容,可能被中间人劫持,修改传输的内容。以下图所示就是典型的APP HTTP通讯被运营商劫持修改,插入广告:java

上图是在个人住处,用WiFi打开某APP,页面底部出现了一个拆红包的广告,点开之后是一个安装APP的页面,若是我用联通的4G网络打开,就不会出现这种状况,说明小区运营商劫持了HTTP通讯,往APP的通讯中加入了本身的推广内容,还有一些低俗的推广广告,这很影响用户体验。一些别有用心的人经过搭建公共WiFi,进行流量劫持、嗅探,能够得到经过HTTP传输的敏感信息。python

为了保护用户的信息安全、保护本身的商业利益,减小攻击面,咱们须要保障通讯信道的安全,采用开发方便的HTTPS是比较好的方式,比用私有协议要好,省时省力。可是若是HTTPS使用不当,就很难起到应有的保护效果。乌云上有不少Android HTTPS使用不当致使产生风险的例子,如 wooyun-2010-07935八、wooyun-2010-08196六、wooyun-2010-080117,有兴趣的话能够去找找看看。android

1.2 HTTPS通讯原理

HTTPS是HTTP over SSL/TLS,HTTP是应用层协议,TCP是传输层协议,在应用层和传输层之间,增长了一个安全套接层SSL/TLS:ios

SSL/TLS层负责客户端和服务器之间的加解密算法协商、密钥交换、通讯链接的创建,安全链接的创建过程以下所示:git

HPPTS握手协议有很丰富的内容,建议读者使用wireshark抓包进行分析,因为篇幅所限,这里再也不进一步深刻。github

二、如何使用HTTPS

2.1 数字证书、CA与HTTPS

信息安全的基础依赖密码学,密码学涉及算法和密钥,算法通常是公开的,而密钥须要获得妥善的保护,密钥如何产生、分配、使用和回收,这涉及公钥基础设施。web

公钥基础设施(PKI)是一组由硬件、软件、参与者、管理政策与流程组成的基础架构,其目的在于创造、管理、分配、使用、存储以及撤销数字证书。公钥存储在数字证书中,标准的数字证书通常由可信数字证书认证机构(CA,根证书颁发机构)签发,此证书将用户的身份跟公钥连接在一块儿。CA必须保证其签发的每一个证书的用户身份是惟一的。算法

连接关系(证书链)经过注册和发布过程建立,取决于担保级别,连接关系可能由CA的各类软件或在人为监督下完成。PKI的肯定连接关系的这一角色称为注册管理中心(RA,也称中级证书颁发机构或者中间机构)。RA确保公钥和我的身份连接,能够防抵赖。若是没有RA,CA的Root 证书遭到破坏或者泄露,由此CA颁发的其余证书就所有失去了安全性,因此如今主流的商业数字证书机构CA通常都是提供三级证书,Root 证书签发中级RA证书,由RA证书签发用户使用的证书。浏览器

X509证书链,左边的是CA根证书,中间的是RA中间机构,右边的是用户:

www.google.com.hk 网站的证书链以下,CA证书机构是 GeoTrust Global CA,RA机构是 Google Internet Authority G2,网站的证书为 *.google.com.hk:

HTTPS通讯所用到的证书由CA提供,须要在服务器中进行相应的设置才能生效。另外在咱们的客户端设备中,只要访问的HTTPS的网站所用的证书是可信CA根证书签发的,若是这些CA又在浏览器或者操做系统的根信任列表中,就能够直接访问,而如12306.cn网站,它的证书是非可信CA提供的,是本身签发的,因此在用谷歌浏览器打开时,会提示“您的链接不是私密链接”,证书是非可信CA颁发的:

因此在12306.cn的网站首页会提示为了咱们的购票顺利,请下载安装它的根证书,操做系统安装后,就不会再有上图的提示了。

2.2 自有数字证书的生成

HTTPS网站所用的证书可向可信CA机构申请,不过这一类基本上都是商业机构,申请证书须要缴费,通常是按年缴费,费用由于CA机构的不一样而不一样。若是只是APP与后台服务器进行HTTPS通讯,可使用openssl工具生成自签发的数字证书,能够节约费用,不过得妥善保护好证书私钥,不能泄露或者丢失。HTTPS通讯所用的数字证书格式为X.509。

自签发数字证书步骤以下:

Step1 生成本身的CA根证书

生成CA私钥文件ca.key:
openssl genrsa -out ca.key 1024

生成X.509证书签名请求文件ca.csr:
openssl req -new -key ca_private.key -out ca.csr

在生成ca.csr的过程当中,会让输入一些组织信息等。

生成X.509格式的CA根证书ca_public.crt(公钥证书):
openssl x509 -req -in ca.csr -signkey ca_private.key -out ca_public.crt

Step2 生成服务端证书

先生成服务器私钥文件server_private.key:
openssl genrsa -out server_private.key 1024

根据服务器私钥生成服务器公钥文件server_public.pem:
openssl rsa -in server_private.key -pubout -out server_public.pem

服务器端须要向CA机构申请签名证书,在申请签名证书以前依然是建立本身的证书签名请求文件server.csr:
openssl req -new -key server_prviate.key -out server.csr

对于用于HTTPS的CSR,Common Name必须和网站域名一致,以便以后进行Host Name校验。

服务器端用server.csr文件向CA申请证书,签名过程须要CA的公钥证书和私钥参与,最终颁发一个带有CA签名的服务器端证书server.crt:
openssl x509 -req -CA ca_public.crt -CAkey ca_private.key -CAcreateserial -in server.csr -out server.crt

若是服务器端还想校验客户端的证书,能够按生成服务器端证书的形式来生成客户端证书。

使用openssl查看证书信息:
openssl x509 -in server.crt -text -noout

用web.py搭建一个简单的服务器测试生成的server.crt,文件webpytest.py为:

在本地运行web服务器程序:
python webpytest.py 1234

在safari浏览器中输入 https://0.0.0.0:1234 ,提示此证书无效(主机名不相符),由于在生成服务器端证书签名请求文件server.csr时,在Common Name中输入的是localhost,与0.0.0.0不符:

在safari浏览器中输入 https://localhost:1234 ,再也不提示主机名不相符了,而是提示此证书是由未知颁发机构签名的,由于是私有CA签发的证书,私有CA不在浏览器或者操做系统的的根信任列表中:

还可用如下命令查看网站证书信息:
openssl s_client -connect localhost:1234

服务器端搭建成功,接下来说Android客户端怎么和服务端进行HTTPS通讯。

2.3 使用HttpsURLConnection进行HTTPS通讯

Android官网给出了使用HttpsURLConnection API访问HTTPS的网站示例:

此方法的特色:

  • 由Android系统校验服务端数字证书的合法性,用可信CA签发的数字证书的网站才能够正常访问,私有CA签发的数字证书的网站没法访问。

  • 不能抵御在用户设备上安装证书(将中间人服务器的证书放到设备的信任列表中)进行中间人攻击,作此类攻击的通常是为了分析应用和服务器的交互协议,找应用和服务器的其余漏洞。

  • 若是网站没有启用SSL site wide(use HTTPS only)或HSTS(HTTP Strict Transport Security)则没法抵御SSL Strip(HTTPS降级为HTTP)攻击,局域网攻击,如针对免费WiFi。

若是要使用私有CA签发的证书,必须重写校验证书链TrustManager中的方法,不然的话会出现javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found。可是在重写TrustManger中的checkServerTrusted()不少开发者什么也没有作,会致使证书弱校验(没有真正校验证书)。

以下是错误的写法:

正确的写法是真正实现TrustManger的checkServerTrusted(),对服务器证书域名进行强校验或者真正实现HostnameVerifier的verify()方法。

真正实现TrustManger的checkServerTrusted()代码以下:

其中serverCert是APP中预埋的服务器端公钥证书,若是是以文件形式,其获取为以下形式:

对服务器证书域名进行强校验:

真正实现HostnameVerifier的verify()方法:

另一种写法证书锁定,直接用预埋的证书来生成TrustManger,过程以下:

参数certStream是证书文件的InputSteam流:

另外能够用如下命令查看服务器证书的公钥:

keytool -printcert -rfc -file uwca.crt

直接复制粘贴能够将公钥信息硬编码在代码中:

能够用如下形式获取此公钥对应的X.509证书:

2.4 使用OKHttp3.0进行HTTPS通讯

除了使用Android系统提供的HttpsURLconnection进行https通讯,还有其余的第三方库可使用,以OKhttp3.0为例,先看未校验服务器端证书链、未校验服务端证书域名的错误写法:

这些错误的发生其实和HttpsURLConnection的其实相同,都涉及SSLContext和HostnameVerifier,聚安全应用扫描器都能扫出来这些潜在风险点,解决办法也和2.3 节相同使用HttpsURLConnection都是真正实现TrustManager和HostnameVerifier中的方法。

2.5 Webview的HTTPS安全

目前不少应用都用webview加载H5页面,若是服务端采用的是可信CA颁发的证书,在 webView.setWebViewClient(webviewClient) 时重载 WebViewClient的onReceivedSslError() ,若是出现证书错误,直接调用handler.proceed()会忽略错误继续加载证书有问题的页面,若是调用handler.cancel()能够终止加载证书有问题的页面,证书出现问题了,能够提示用户风险,让用户选择加载与否,若是是须要安全级别比较高,能够直接终止页面加载,提示用户网络环境有风险:

不建议直接用handler.proceed(),聚安全的应用安全扫描器会扫出来直接调用handler.proceed()的状况。

若是webview加载https须要强校验服务端证书,能够在 onPageStarted() 中用 HttpsURLConnection 强校验证书的方式来校验服务端证书,若是校验不经过中止加载网页。固然这样会拖慢网页的加载速度,须要进一步优化,具体优化的办法不在本次讨论范围,这里也不详细讲解了。

三、阿里聚安全对开发者建议

阿里聚安全的漏洞扫描器发现,不少APP都存在HTTPS使用不当的风险。正确使用HTTPS能有效抵御在用户设备上安装证书进行中间人攻击和SSL Strip攻击。

可是上述方法都须要在客户端中预埋证书文件,或者将证书硬编码写在代码中,若是服务器端证书到期或者由于泄露等其余缘由须要更换证书,也就必须强制用户进行客户端升级,体验效果很差。阿里聚安全推出了一个能完美解决这个问题的安全组件。APP开发者只须要将公钥放在安全组件中,安全组件的动态密钥功能能够实现公钥的动态升级。

另外正确使用HTTPS并不是彻底可以防住客户端的Hook分析修改,要想保证通讯安全,也须要依靠其余方法,好比重要信息在交给HTTPS传输以前进行加密,另外实现客户端请求的签名处理,保证客户端与服务端通讯请求不被伪造。目前阿里聚安全的安全组件已经具有以上全部功能,此外还有安全存储、模拟器检测,人机识别等功能。安全组件还具备实时更新客户端模块的功能,保证攻防对抗强度。

四、参考

[1] Survival guides - TLS/SSL and SSL (X.509) Certificates,http://www.zytrax.com/tech/survival/ssl.html

[2] Public key infrastructure,https://en.wikipedia.org/wiki/Public_key_infrastructure

[3] http://www.barretlee.com/blog/2015/10/05/how-to-build-a-https-server/

[4] Security with HTTPS and SSL,https://developer.android.com/training/articles/security-ssl.html

[5] 窃听风暴:Android平台https嗅探劫持漏洞,http://www.freebuf.com/articles/terminal/26840.html

[6] Android HTTPS中间人劫持漏洞浅析,https://jaq.alibaba.com/blog.htm?id=60

[7] 浅析HTTPS中间人攻击与证书校验,http://www.evil0x.com/posts/26569.html

[8] https://github.com/menjoo/Android-SSL-Pinning-WebViews

[9] https://github.com/square/okhttp/wiki/HTTPS

[10] https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/CustomTrust.java

五、Android安全开发系列

目录

Android安全开发之通用签名风险

Android安全开发之ZIP文件目录遍历

Android安全开发之Provider组件安全

Android安全开发之浅谈密钥硬编码

Android安全开发之浅谈网页打开APP

Android应用安全开发之浅谈加密算法的坑

做者:伊樵@阿里聚安全,更多Android、iOS安全技术文章,请访问阿里聚安全博客

相关文章
相关标签/搜索