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:git

SSL/TLS層負責客戶端和服務器之間的加解密算法協商、密鑰交換、通訊鏈接的創建,安全鏈接的創建過程以下所示:github

HPPTS握手協議有很豐富的內容,建議讀者使用wireshark抓包進行分析,因爲篇幅所限,這裏再也不進一步深刻。web

二、如何使用HTTPS

2.1 數字證書、CA與HTTPS

信息安全的基礎依賴密碼學,密碼學涉及算法和密鑰,算法通常是公開的,而密鑰須要獲得妥善的保護,密鑰如何產生、分配、使用和回收,這涉及公鑰基礎設施。算法

公鑰基礎設施(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/su...

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

[3] http://www.barretlee.com/blog...

[4] Security with HTTPS and SSL,https://developer.android.com...

[5] 竊聽風暴:Android平臺https嗅探劫持漏洞,http://www.freebuf.com/articl...

[6] Android HTTPS中間人劫持漏洞淺析,https://jaq.alibaba.com/blog....

[7] 淺析HTTPS中間人攻擊與證書校驗,http://www.evil0x.com/posts/2...

[8] https://github.com/menjoo/And...

[9] https://github.com/square/okh...

[10] https://github.com/square/okh...

五、Android安全開發系列

目錄

Android安全開發之通用簽名風險

Android安全開發之ZIP文件目錄遍歷

Android安全開發之Provider組件安全

Android安全開發之淺談密鑰硬編碼

Android安全開發之淺談網頁打開APP

Android應用安全開發之淺談加密算法的坑

做者:伊樵@阿里聚安全,更多Android、iOS安全技術文章,請訪問阿里聚安全博客

相關文章
相關標籤/搜索