Android安全開發(fā)之安全使用HTTPS(轉(zhuǎn))

轉(zhuǎn)自: https://www.cnblogs.com/alisecurity/p/5939336.html

1、HTTPS簡介

阿里聚安全的應(yīng)用漏洞掃描器中有證書弱校驗(yàn)、主機(jī)名弱校驗(yàn)、webview未校驗(yàn)證書的檢測項(xiàng),這些檢測項(xiàng)是針對APP采用HTTPS通信時容易出現(xiàn)風(fēng)險的地方而設(shè)。接下來介紹一下安全使用HTTPS的相關(guān)內(nèi)容。

1.1 為何需要HTTPS

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

image

上圖是在我的住處,用WiFi打開某APP,頁面底部出現(xiàn)了一個拆紅包的廣告,點(diǎn)開以后是一個安裝APP的頁面,如果我用聯(lián)通的4G網(wǎng)絡(luò)打開,就不會出現(xiàn)這種情況,說明小區(qū)運(yùn)營商劫持了HTTP通信,往APP的通信中加入了自己的推廣內(nèi)容,還有一些低俗的推廣廣告,這很影響用戶體驗(yàn)。一些別有用心的人通過搭建公共WiFi,進(jìn)行流量劫持、嗅探,可以獲得通過HTTP傳輸?shù)拿舾行畔ⅰ?/p>

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

1.2 HTTPS通信原理

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

image

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

image

HPPTS握手協(xié)議有很豐富的內(nèi)容,建議讀者使用wireshark抓包進(jìn)行分析,由于篇幅所限,這里不再進(jìn)一步深入。

2、如何使用HTTPS

2.1 數(shù)字證書、CA與HTTPS

信息安全的基礎(chǔ)依賴密碼學(xué),密碼學(xué)涉及算法和密鑰,算法一般是公開的,而密鑰需要得到妥善的保護(hù),密鑰如何產(chǎn)生、分配、使用和回收,這涉及公鑰基礎(chǔ)設(shè)施。

公鑰基礎(chǔ)設(shè)施(PKI)是一組由硬件、軟件、參與者、管理政策與流程組成的基礎(chǔ)架構(gòu),其目的在于創(chuàng)造、管理、分配、使用、存儲以及撤銷數(shù)字證書。公鑰存儲在數(shù)字證書中,標(biāo)準(zhǔn)的數(shù)字證書一般由可信數(shù)字證書認(rèn)證機(jī)構(gòu)(CA,根證書頒發(fā)機(jī)構(gòu))簽發(fā),此證書將用戶的身份跟公鑰鏈接在一起。CA必須保證其簽發(fā)的每個證書的用戶身份是唯一的。

鏈接關(guān)系(證書鏈)通過注冊和發(fā)布過程創(chuàng)建,取決于擔(dān)保級別,鏈接關(guān)系可能由CA的各種軟件或在人為監(jiān)督下完成。PKI的確定鏈接關(guān)系的這一角色稱為注冊管理中心(RA,也稱中級證書頒發(fā)機(jī)構(gòu)或者中間機(jī)構(gòu))。RA確保公鑰和個人身份鏈接,可以防抵賴。如果沒有RA,CA的Root 證書遭到破壞或者泄露,由此CA頒發(fā)的其他證書就全部失去了安全性,所以現(xiàn)在主流的商業(yè)數(shù)字證書機(jī)構(gòu)CA一般都是提供三級證書,Root 證書簽發(fā)中級RA證書,由RA證書簽發(fā)用戶使用的證書。

X509證書鏈,左邊的是CA根證書,中間的是RA中間機(jī)構(gòu),右邊的是用戶:

image

www.google.com.hk 網(wǎng)站的證書鏈如下,CA證書機(jī)構(gòu)是 GeoTrust Global CA,RA機(jī)構(gòu)是 Google Internet Authority G2,網(wǎng)站的證書為 *.google.com.hk

image

HTTPS通信所用到的證書由CA提供,需要在服務(wù)器中進(jìn)行相應(yīng)的設(shè)置才能生效。另外在我們的客戶端設(shè)備中,只要訪問的HTTPS的網(wǎng)站所用的證書是可信CA根證書簽發(fā)的,如果這些CA又在瀏覽器或者操作系統(tǒng)的根信任列表中,就可以直接訪問,而如12306.cn網(wǎng)站,它的證書是非可信CA提供的,是自己簽發(fā)的,所以在用谷歌瀏覽器打開時,會提示“您的連接不是私密連接”,證書是非可信CA頒發(fā)的:

image

所以在12306.cn的網(wǎng)站首頁會提示為了我們的購票順利,請下載安裝它的根證書,操作系統(tǒng)安裝后,就不會再有上圖的提示了。

2.2 自有數(shù)字證書的生成

HTTPS網(wǎng)站所用的證書可向可信CA機(jī)構(gòu)申請,不過這一類基本上都是商業(yè)機(jī)構(gòu),申請證書需要繳費(fèi),一般是按年繳費(fèi),費(fèi)用因?yàn)镃A機(jī)構(gòu)的不同而不同。如果只是APP與后臺服務(wù)器進(jìn)行HTTPS通信,可以使用openssl工具生成自簽發(fā)的數(shù)字證書,可以節(jié)約費(fèi)用,不過得妥善保護(hù)好證書私鑰,不能泄露或者丟失。HTTPS通信所用的數(shù)字證書格式為X.509。

自簽發(fā)數(shù)字證書步驟如下:

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 生成服務(wù)端證書

先生成服務(wù)器私鑰文件server_private.key:
openssl genrsa -out server_private.key 1024

根據(jù)服務(wù)器私鑰生成服務(wù)器公鑰文件server_public.pem:
openssl rsa -in server_private.key -pubout -out server_public.pem

服務(wù)器端需要向CA機(jī)構(gòu)申請簽名證書,在申請簽名證書之前依然是創(chuàng)建自己的證書簽名請求文件server.csr:
openssl req -new -key server_prviate.key -out server.csr

image

對于用于HTTPS的CSR,Common Name必須和網(wǎng)站域名一致,以便之后進(jìn)行Host Name校驗(yàn)。

服務(wù)器端用server.csr文件向CA申請證書,簽名過程需要CA的公鑰證書和私鑰參與,最終頒發(fā)一個帶有CA簽名的服務(wù)器端證書server.crt:
openssl x509 -req -CA ca_public.crt -CAkey ca_private.key -CAcreateserial -in server.csr -out server.crt

如果服務(wù)器端還想校驗(yàn)客戶端的證書,可以按生成服務(wù)器端證書的形式來生成客戶端證書。

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

用web.py搭建一個簡單的服務(wù)器測試生成的server.crt,文件webpytest.py為:

image

在本地運(yùn)行web服務(wù)器程序:
python webpytest.py 1234

在safari瀏覽器中輸入 https://0.0.0.0:1234 ,提示此證書無效(主機(jī)名不相符),因?yàn)樵谏煞?wù)器端證書簽名請求文件server.csr時,在Common Name中輸入的是localhost,與0.0.0.0不符:

image

在safari瀏覽器中輸入 https://localhost:1234 ,不再提示主機(jī)名不相符了,而是提示此證書是由未知頒發(fā)機(jī)構(gòu)簽名的,因?yàn)槭撬接蠧A簽發(fā)的證書,私有CA不在瀏覽器或者操作系統(tǒng)的的根信任列表中:

image

還可用以下命令查看網(wǎng)站證書信息:
openssl s_client -connect localhost:1234

服務(wù)器端搭建成功,接下來講Android客戶端怎么和服務(wù)端進(jìn)行HTTPS通信。

2.3 使用HttpsURLConnection進(jìn)行HTTPS通信

Android官網(wǎng)給出了使用HttpsURLConnection API訪問HTTPS的網(wǎng)站示例:

image

此方法的特點(diǎn):

  • 由Android系統(tǒng)校驗(yàn)服務(wù)端數(shù)字證書的合法性,用可信CA簽發(fā)的數(shù)字證書的網(wǎng)站才可以正常訪問,私有CA簽發(fā)的數(shù)字證書的網(wǎng)站無法訪問。

  • 不能抵御在用戶設(shè)備上安裝證書(將中間人服務(wù)器的證書放到設(shè)備的信任列表中)進(jìn)行中間人攻擊,做此類攻擊的一般是為了分析應(yīng)用和服務(wù)器的交互協(xié)議,找應(yīng)用和服務(wù)器的其他漏洞。

  • 如果網(wǎng)站沒有啟用SSL site wide(use HTTPS only)或HSTS(HTTP Strict Transport Security)則無法抵御SSL Strip(HTTPS降級為HTTP)攻擊,局域網(wǎng)攻擊,如針對免費(fèi)WiFi。

如果要使用私有CA簽發(fā)的證書,必須重寫校驗(yàn)證書鏈TrustManager中的方法,否則的話會出現(xiàn)javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found。但是在重寫TrustManger中的checkServerTrusted()很多開發(fā)者什么也沒有做,會導(dǎo)致證書弱校驗(yàn)(沒有真正校驗(yàn)證書)。

如下是錯誤的寫法:

image

正確的寫法是真正實(shí)現(xiàn)TrustManger的checkServerTrusted(),對服務(wù)器證書域名進(jìn)行強(qiáng)校驗(yàn)或者真正實(shí)現(xiàn)HostnameVerifier的verify()方法。

真正實(shí)現(xiàn)TrustManger的checkServerTrusted()代碼如下:

image

其中serverCert是APP中預(yù)埋的服務(wù)器端公鑰證書,如果是以文件形式,其獲取為如下形式:

image

對服務(wù)器證書域名進(jìn)行強(qiáng)校驗(yàn):

image

真正實(shí)現(xiàn)HostnameVerifier的verify()方法:

image

另外一種寫法證書鎖定,直接用預(yù)埋的證書來生成TrustManger,過程如下:

image

參數(shù)certStream是證書文件的InputSteam流:

image

另外可以用以下命令查看服務(wù)器證書的公鑰:

keytool -printcert -rfc -file uwca.crt

直接復(fù)制粘貼可以將公鑰信息硬編碼在代碼中:

image

可以用以下形式獲取此公鑰對應(yīng)的X.509證書:

image

2.4 使用OKHttp3.0進(jìn)行HTTPS通信

除了使用Android系統(tǒng)提供的HttpsURLconnection進(jìn)行https通信,還有其他的第三方庫可以使用,以O(shè)Khttp3.0為例,先看未校驗(yàn)服務(wù)器端證書鏈、未校驗(yàn)服務(wù)端證書域名的錯誤寫法:

image

這些錯誤的發(fā)生其實(shí)和HttpsURLConnection的其實(shí)相同,都涉及SSLContext和HostnameVerifier,聚安全應(yīng)用掃描器都能掃出來這些潛在風(fēng)險點(diǎn),解決辦法也和2.3 節(jié)相同使用HttpsURLConnection都是真正實(shí)現(xiàn)TrustManager和HostnameVerifier中的方法。

2.5 Webview的HTTPS安全

目前很多應(yīng)用都用webview加載H5頁面,如果服務(wù)端采用的是可信CA頒發(fā)的證書,在 webView.setWebViewClient(webviewClient) 時重載 WebViewClient的onReceivedSslError() ,如果出現(xiàn)證書錯誤,直接調(diào)用handler.proceed()會忽略錯誤繼續(xù)加載證書有問題的頁面,如果調(diào)用handler.cancel()可以終止加載證書有問題的頁面,證書出現(xiàn)問題了,可以提示用戶風(fēng)險,讓用戶選擇加載與否,如果是需要安全級別比較高,可以直接終止頁面加載,提示用戶網(wǎng)絡(luò)環(huán)境有風(fēng)險:

image

不建議直接用handler.proceed(),聚安全的應(yīng)用安全掃描器會掃出來直接調(diào)用handler.proceed()的情況。

如果webview加載https需要強(qiáng)校驗(yàn)服務(wù)端證書,可以在 onPageStarted() 中用 HttpsURLConnection 強(qiáng)校驗(yàn)證書的方式來校驗(yàn)服務(wù)端證書,如果校驗(yàn)不通過停止加載網(wǎng)頁。當(dāng)然這樣會拖慢網(wǎng)頁的加載速度,需要進(jìn)一步優(yōu)化,具體優(yōu)化的辦法不在本次討論范圍,這里也不詳細(xì)講解了。

3、阿里聚安全對開發(fā)者建議

阿里聚安全的漏洞掃描器發(fā)現(xiàn),很多APP都存在HTTPS使用不當(dāng)?shù)娘L(fēng)險。正確使用HTTPS能有效抵御在用戶設(shè)備上安裝證書進(jìn)行中間人攻擊和SSL Strip攻擊。

但是上述方法都需要在客戶端中預(yù)埋證書文件,或者將證書硬編碼寫在代碼中,如果服務(wù)器端證書到期或者因?yàn)樾孤兜绕渌蛐枰鼡Q證書,也就必須強(qiáng)制用戶進(jìn)行客戶端升級,體驗(yàn)效果不好。阿里聚安全推出了一個能完美解決這個問題的安全組件。APP開發(fā)者只需要將公鑰放在安全組件中,安全組件的動態(tài)密鑰功能可以實(shí)現(xiàn)公鑰的動態(tài)升級。

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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本文摘自 騰訊bugly 的文章《全站 HTTPS 來了》,內(nèi)容有修改。 大家在使用百度、谷歌或淘寶的時候,是否注...
    bnotes閱讀 3,868評論 1 9
  • CA和證書安全協(xié)議(SSL/TLS)OpenSSH 一、CA和證書 (一) PKI(Public Key Infr...
    哈嘍別樣閱讀 1,517評論 0 0
  • 超文本傳輸安全協(xié)議(HTTPS,常稱為 HTTP over TLS/SSL)是一種通過計算機(jī)網(wǎng)絡(luò)進(jìn)行安全通信的傳輸...
    MarchCd閱讀 7,333評論 1 22
  • 一、青云 1.青云推出『預(yù)留實(shí)例』—是針對用戶長期、穩(wěn)定的 IT 需求,全新推出的主機(jī)(實(shí)例)使用和計費(fèi)方式。 通...
    Captain7閱讀 184評論 0 0
  • 總算過了一個不那么荒廢的周六,看視頻復(fù)習(xí)了不少Java知識,前些日子看的很多東西有的已經(jīng)開始模糊,重新看了一些知識...
    Hyleon閱讀 308評論 0 0

友情鏈接更多精彩內(nèi)容