Android應用被抓包?防護手段需知道

語言: CN / TW / HK

theme: smartblue

為了提高網路資料傳輸的安全性,業內採用HTTPS的方式取代原來的HTTP,Android的應用開發也不例外,我們似乎只需要修改一下域名就能完成http到https的切換,無需做其他額外的操作,那麼這個HTTPS是如何實現的?是否真的就安全了?在不同的Android版本上是否有差異?今天我們就來詳細研究一下以上的問題。

Tips:本篇旨在討論HTTPS傳輸的安全性,應用本地安全不在討論範疇。

HTTPS原理

誕生背景

首先就是老生常談的問題,什麼是HTTPS,相信大家有有所瞭解,這裡簡單提一下:

由於HTTP協議(HyperText Transfer Protocol,超文字傳輸協議)中,傳輸的內容是明文的,請求一旦被劫持,內容就會完全暴露,劫持者可以對其進行竊取或篡改,因此這種資料的傳輸方式存在極大的安全隱患。

因此,在基於HTTP協議的基礎上對傳輸內容進行加密的HTTPS協議(HyperText Transfer Protocol over Secure Socket Layer)便誕生了,這樣即使傳輸的內容被劫持,由於資料是加密的,劫持者沒有對應的金鑰也很難對內容進行破解,從而提高的傳輸的安全性。

金鑰協商

既然要對傳輸的內容進行加密,那就要約定好加密的方式與金鑰管理。首先在加密方式的選擇上,有對稱加密非對稱加密兩種,這兩種方式各有有缺。

對稱加密:

加密和解密使用相同的金鑰,這種效率比較高,但是存在金鑰維護的問題。如果金鑰通過請求動態下發,會有洩漏的風險。如果金鑰存放到Client端,那麼金鑰變更時就要重新發版更新金鑰,而且如果要請求多個伺服器就要維護多個金鑰,對於伺服器端也是同理,這種金鑰的維護成本極高。

非對稱加密:

加密和解密使用不同的金鑰,即公鑰與私鑰,私鑰存放在Server端,不對外公開,公鑰是對外公開的,這樣無論是公鑰打包進Client端還是由Server端動態下發,也無需擔心洩漏的問題。但是這種加密方式效率較低。

HTTPS協議中,結合了對稱加密和非對稱加密兩種方式,取其精華,棄其糟粕,發揮了兩者各自的優勢。

假設目前Server端有一對金鑰,公鑰A和私鑰A,在Client端發起請求時,Server端下發公鑰A給Client端,Client端生成一個會話金鑰B,並使用公鑰A對會話金鑰B進行加密傳到Server端,Server端使用私鑰A進行解密得到會話金鑰B,這時Client端和Server端完成了金鑰協商工作,之後Client和和Server端互動的資料都使用會話金鑰B進行對稱加解密。在金鑰協商過程中,就算被劫持,由於劫持者沒有私鑰A,也無法獲取協商的會話金鑰B,因此保證了資料傳輸的安全性。

金鑰協商過程簡圖如下:

金鑰協商簡圖.png

CA證書

上面的過程貌似解決了資料傳輸的安全問題,但依然有一個漏洞,就是如果劫持者篡改了Server端下發給Client端的公鑰的情況。

中間人攻擊(MITM攻擊)簡圖如下:

中間人攻擊簡圖.png

為了解決Client端對Server端下發公鑰的信任問題,出現了一個被稱作CA(Certificate Authority)的機構。

CA機構同樣擁有采用非對稱加密的公鑰和私鑰,公鑰加上一些其他的資訊(組織單位、頒發時間、過期時間等)資訊被製作成一個cer/pem/crt等格式的檔案,被稱作證書,這些CA機構用來給其他組織單位簽發證書的證書叫做根證書,根證書一般都會被預裝在我們的裝置中,被無條件信任

以Android裝置為例,我們可以在設定 -> 安全 -> 更多安全設定 -> 加密與憑據 -> 信任的憑據中檢視當前裝置所有的預裝的證書。

裝置預裝的證書.jpeg

如果Server端部署的證書是正規CA機構簽發的證書(CA機構一般不會直接用根證書為企業簽發域名證書,而是使用根證書生成的中間證書,一般情況下證書鏈是三級,根證書-中間證書-企業證書),那麼我們在進行HTTPS請求的時候,不需要做其他額外操作,Client端獲取到Server端下發的證書會自動與系統預裝的證書進行校驗,以確認證書是否被篡改。

如果Server端的證書是自籤的,則需要在Client端自行處理證書校驗規則,否則無法正常完成HTTPS請求。

這也是為什麼,我們在Android開發網路請求時,無需做額外操作便能絲滑切換到HTTPS,但是這樣真的就能保證網路請求的安全性了嗎?

真的安全了嗎?

經過上面的介紹我們可以瞭解到,如果Client端(手機、瀏覽器)中預裝了大量正規CA機構的根證書,Server端如果是正規CA簽發的證書,理論上是解決了HTTPS通訊中雙端的信任問題,但是還存在一個問題,就是這些Client端一般都會支援使用者自行安裝證書,這將會給Android端的網路安全帶來哪些風險?接下來我們就繼續來聊聊。

由於Android版本更新迭代較快,且不同版本之前差異較大,因此分析這個問題的時候一定要基於一個特定的系統版本,區別分析。Android 5.0(21)之前的版本太過古老,這裡就不再進行分析,直接分析5.0之後的版本。

在一個只採用預設配置的的測試專案中進行HTTPS請求的抓包測試,發現在5.0(包括)到7.0(不包括)之間的版本,可以通過中間人或VPN的方式進行抓包,而7.0及以上版本則無法正常抓包,抓包情況如下

7.0以下手機代理抓包情況:

Android7.0以下.jpeg

7.0及以上手機代理抓包情況:

之所以7.0是個分水嶺,是因為在Android7.0之前,系統除了對系統內建CA證書無條件信任外,對使用者手動安裝的CA證書也無條件信任了。

雖然說7.0及以上的裝置不再信用使用者自行新增的CA證書,安全性比之前的高很多,但是無門卻無法阻止那些抓包的人使用7.0之下的手機,除非提高應用的最小支援版本,但這樣就意味著要放棄一些使用者,顯然也不適用於所有情況。

那麼如何在保證低版本相容性的同時兼顧安全性呢,我們接下來繼續探討。

如何更安全

除了系統預設的安全校驗之外,我們也可以通過如下手段來提高請求的安全性,讓抓包變得更加困難。

禁用代理

該方式適用於所有Android版本。

在網路請求時,通過呼叫系統API獲取當前網路是否設定了代理,如果設定了就終止請求,達到保護資料安全的目的。因為通過中間人的方式進行抓包,需要把網路請求轉發到中間人的代理伺服器,如果禁止了代理相當於從源頭解決了問題。

優勢:設定簡單,系統API簡單呼叫即可獲取代理狀態。

劣勢:

  1. 會錯殺一些因為其他場景而使用代理的使用者,導致這樣的使用者無法正常使用

  2. 通過開啟VPN在VPN上設定代理轉發到中間人伺服器的方式繞過

由於設定禁用代理的方式很容易被繞過且有可能影響正常開啟VPN使用者的使用,因此不推薦使用該方式。

資料加密

該方式適用於所有Android版本。

對請求傳輸的資料進行加密,然後再通過HTTPS協議傳輸。HTTPS本身在傳輸過程中會生成一個會話金鑰,但是這個金鑰可以被抓包獲取,如果對傳輸的資料進行一次加密後再傳輸,即使被抓包也沒法解析出真實的資料。

優勢:安全性較高,只要金鑰沒有洩漏,資料被破獲的風險較低

劣勢:

  1. 修改同時修改Client端和Server端程式碼,增加加解密邏輯

  2. 加解密操作影響效率且有金鑰維護的成本

在對資料安全性要求比較高的介面上,可以採用這種方式對傳輸內容進行增強保護。

證書單向認證

該方式適用於所有Android版本。

在預設情況下,HTTPS在握手時,Server端下證書等資訊到Client端,Client端校驗該證書是否為正規CA機構簽發,如果是則通過校驗。這裡我們可以自定義校驗規則,可以下載Server端的證書到打包到APK中,在請求時進行證書校驗。

https單向認證.png

優勢:安全性高。

劣勢:證書容易過期,當前企業證書有效期只有1年,需要每年進行續簽,Client需要維護證書更新的問題。

證書雙向認證

該方式適用於所有Android版本。

在單向認證中,Client端會驗證Server端是否安全,但是Server端並沒有對Client進行校驗,這裡可以讓Server端對Client也進行一次認證。這種認證需要在單向認證的基礎上再額外建立一套證書B,存放在Client端,並在Client端完成對Server端的校驗後,把Client端的公鑰證書傳送到Server端,由Server端進行校驗,校驗通過後開始金鑰協商等後續步驟。

https雙向認證.png

優勢:安全性非常高!

劣勢: 1. Server端要存放Client端公鑰證書,如果一個Server對應多個Client則需要維護多套

  1. 增加了校驗成本,會降低相應速度

網路安全配置檔案

該方案為google官方推薦的方案,也是一種證書的單向校驗,不過在Android7.0及更高版本上,配置簡單,只需要再清單檔案的application節點下增加一個networkSecurityConfig項,並指向一個按固定的格式建立一個xml檔案,即可完成網路安全的校驗,體驗相當絲滑,唯一美中不足的是該配置不支援7.0以下的版本。

在7.0及以上版本中,在xml資料夾下建立名為network_security_config_wanandroid的網路安全配置檔案:

網路安全檔案配置.jpeg

該檔案只需要在清單檔案application節點的networkSecurityConfig中引用該檔案即可,如此就完成了對wanandroid.com域名及其所有次級域名的證書單向認證。

在7.0以下版本中:

由於networkSecurityConfig是7.0版本新增的,因此在所有7.0以下的裝置上無法生效,所以針對7.0以下的裝置只能通過程式碼進行認證。推薦使用OkHttp:

okHttp進行證書校驗.png

需要注意的是,在通過程式碼配置指定域名的證書校驗時,根域名和次級域名需要分別進行配置。

優勢:安全性較高,程式碼改動少。

劣勢:本質還是證書的單向認證。

選擇要校驗的證書

如果說採取了google推薦的方式進行安全校驗,那校驗證書鏈中的哪個證書比較合適呢?

理論上來說,當然是校驗企業自己的證書最好,即證書鏈的第三層企業證書

image.png

但是該層證書的有效期比較短,一般每年都要進行重籤,重籤之後證書的Sha256就會發生變化,這時候就要及時更新Client端中資訊,否則就無法正常完成校驗。

為了規避證書頻繁過期的問題,我們可以直接對根證書進行校驗,一般來說,根證書的有效期是比較長的:

image.png

這樣就不用擔心證書頻繁過期的問題了,但是如果再企業證書續簽的時候更換了CA機構,那就必須要更新Client端中的根證書資訊了,不過這就是另外的一個問題了。

只校驗根證書會不會存在風險?

幾乎不會,因為正規的CA機構在給一個企業頒發證書的時候,會有稽核機制的,一般不會出現錯誤辦法的狀況,但在歷史上確實出現過CA機構被騙,將證書頒發給了相應域名之外的人。下面截圖來自Google官網:

列入黑名單.png

不過這是非常小概率的事件了,因此校驗域名+根證書摘要算是即安全又避免了證書頻繁過期的問題,再加上google官方的推薦,算的上是最佳解決方案了。

這篇文章就介紹到這裡,感謝觀看~~

上號.jpg