Android安全開發之安全使用HTTPS


Android安全開發之安全使用HTTPS

1、HTTPS簡介

阿里聚安全的應用漏洞掃描器中有證書弱校驗、主機名弱校驗、webview未校驗證書的檢測項,這些檢測項是針對APP采用HTTPS通信時容易出現風險的地方而設。接下來介紹一下安全使用HTTPS的相關內容。

1.1 為何需要HTTPS

HTTP協議是沒有加密的明文傳輸協議,如果APP采用HTTP傳輸數據,則會泄露傳輸內容,可能被中間人劫持,修改傳輸的內容。如下圖所示就是典型的APP HTTP通信被運營商劫持修改,插入廣告:

上圖是在我的住處,用WiFi打開某APP,頁面底部出現了一個拆紅包的廣告,點開以后是一個安裝APP的頁面,如果我用聯通的4G網絡打開,就不會出現這種情況,說明小區運營商劫持了HTTP通信,往APP的通信中加入了自己的推廣內容,還有一些低俗的推廣廣告,這很影響用戶體驗。一些別有用心的人通過搭建公共WiFi,進行流量劫持、嗅探,可以獲得通過HTTP傳輸的敏感信息。

為了保護用戶的信息安全、保護自己的商業利益,減少攻擊面,我們需要保障通信信道的安全,采用開發方便的HTTPS是比較好的方式,比用私有協議要好,省時省力。但是如果HTTPS使用不當,就很難起到應有的保護效果。烏雲上有很多Android HTTPS使用不當導致產生風險的例子,如 wooyun-2010-079358、wooyun-2010-081966、wooyun-2010-080117,有興趣的話可以去找找看看。

1.2 HTTPS通信原理

HTTPS是HTTP over SSL/TLS,HTTP是應用層協議,TCP是傳輸層協議,在應用層和傳輸層之間,增加了一個安全套接層SSL/TLS:

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

HPPTS握手協議有很豐富的內容,建議讀者使用wireshark抓包進行分析,由於篇幅所限,這里不再進一步深入。

2、如何使用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 強校驗證書的方式來校驗服務端證書,如果校驗不通過停止加載網頁。當然這樣會拖慢網頁的加載速度,需要進一步優化,具體優化的辦法不在本次討論范圍,這里也不詳細講解了。

3、阿里聚安全對開發者建議

阿里聚安全的漏洞掃描器發現,很多APP都存在HTTPS使用不當的風險。正確使用HTTPS能有效抵御在用戶設備上安裝證書進行中間人攻擊和SSL Strip攻擊。

但是上述方法都需要在客戶端中預埋證書文件,或者將證書硬編碼寫在代碼中,如果服務器端證書到期或者因為泄露等其他原因需要更換證書,也就必須強制用戶進行客戶端升級,體驗效果不好。阿里聚安全推出了一個能完美解決這個問題的安全組件。APP開發者只需要將公鑰放在安全組件中,安全組件的動態密鑰功能可以實現公鑰的動態升級。

另外正確使用HTTPS並非完全能夠防住客戶端的Hook分析修改,要想保證通信安全,也需要依靠其他方法,比如重要信息在交給HTTPS傳輸之前進行加密,另外實現客戶端請求的簽名處理,保證客戶端與服務端通信請求不被偽造。目前阿里聚安全的安全組件已經具備以上所有功能,此外還有安全存儲、模擬器檢測,人機識別等功能。安全組件還具有實時更新客戶端模塊的功能,保證攻防對抗強度。

4、參考

[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

5、Android安全開發系列

目錄

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

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

Android安全開發之Provider組件安全

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

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

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

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM