天天看點

關于Android的https通訊安全

前段時間,同僚拿着一個代碼安全掃描出來的 bug 過來咨詢,我一看原來是個 https

通信時數字證書校驗的漏洞,一想就明白了大概;其實這種問題早兩年就有大規模的暴露,各大廠商app

也紛紛中招,想不到過了這麼久天貓用戶端裡還留有這種坑;然後仔細研究了漏洞所在的代碼片段,原來所屬的是新浪微網誌分享 sdk 内部的,因為這個 sdk

是源碼引用的,一直沒有更新,年久失修,是以也就被掃描出來了。是以給出的解決方案是:

先擷取最新的 sdk,看其内部是否已解決,已解決的話更新 sdk 版本即可;

第1步行不通,那就自己寫校驗邏輯,貓客全局通信基本已經使用 https 通信,參考着再寫一遍校驗邏輯也不是問題;

後來查了一下網上資訊,早在2014年10月份,烏雲

平台裡就已經暴露過天貓這個漏洞,想必當時一定是忙于雙十一忽略了這個問題。

雖然這個問題通過更新 sdk

解決了,但是這個問題純粹是由于開發者本身疏忽造成的;特别是對于初級開發人員來說,可能為了解決異常,屏蔽了校驗邏輯;是以我還是抽空再 review

了一下這個漏洞,整理相關資訊。

對于數字證書相關概念、android 裡 https 通信代碼就不再複述了,直接講問題。缺少相應的安全校驗很容易導緻中間人攻擊,而漏洞的形式主要有以下3種:

在使用httpsurlconnection發起 https 請求的時候,提供了一個自定義的x509trustmanager,未實作安全校驗邏輯,下面片段就是當時新浪微網誌 sdk 内部的代碼片段。如果不提供自定義的x509trustmanager,代碼運作起來可能會報異常(原因下文解釋),初學者就很容易在不明真相的情況下提供了一個自定義的x509trustmanager,卻忘記正确地實作相應的方法。本文重點介紹這種場景的處理方式。

在握手期間,如果 url 的主機名和伺服器的辨別主機名不比對,則驗證機制可以回調此接口的實作程式來确定是否應該允許此連接配接。如果回調内實作不恰當,預設接受所有域名,則有安全風險。代碼示例。

分而治之,針對不同的漏洞點分别描述,這裡就講的修複方案主要是針對非浏覽器app,非浏覽器 app 的服務端通信對象比較固定,一般都是自家伺服器,可以做很多特定場景的定制化校驗。如果是浏覽器 app,校驗政策就有更通用一些。

自定義x509trustmanager。前面說到,當發起 https 請求時,可能抛起一個異常,以下面這段代碼為例(來自官方文檔):

它會抛出一個sslhandshakeexception的異常。

android 手機有一套共享證書的機制,如果目标 url 伺服器下發的證書不在已信任的證書清單裡,或者該證書是自簽名的,不是由權威機構頒發,那麼會出異常。對于我們這種非浏覽器 app 來說,如果提示使用者去下載下傳安裝證書,可能會顯得比較詭異。幸好還可以通過自定義的驗證機制讓證書通過驗證。驗證的思路有兩種:

不論是權威機構頒發的證書還是自簽名的,打包一份到 app 内部,比如存放在 asset 裡。通過這份内置的證書初始化一個keystore,然後用這個keystore去引導生成的trustmanager來提供驗證,具體代碼如下:

這樣就可以得到正确的輸出内容:

同方案1,打包一份到證書到 app 内部,但不通過keystore去引導生成的trustmanager,而是幹脆直接自定義一個trustmanager,自己實作校驗邏輯;校驗邏輯主要包括:

•伺服器證書是否過期

•證書簽名是否合法

•自定義hostnameverifier,簡單的話就是根據域名進行字元串比對校驗;業務複雜的話,還可以結合配置中心、白名單、黑名單、正則比對等多級别動态校驗;總體來說邏輯還是比較簡單的,反正隻要正确地實作那個方法。

•主機名驗證政策改成嚴格模式

文/尹star(簡書作者)

原文連結:http://www.jianshu.com/p/7c1bc2daef8d

著作權歸作者所有,轉載請聯系作者獲得授權,并标注“簡書作者”。

繼續閱讀