今天主要跟大家介紹一下Android的抓包和防止抓包
介紹兩款抓包工具,Profiter和Charles。
工具環境:
Android Studio 4.2.2
手機Google Pixel 3XL Android 11
使用Profiler 工具抓包
將自己的手機連接到電腦上,然後打開Android Studio 的Profiler
Android Studio 白狐及以下版本的NetWork Inspector 在 Profler 中,大黃蜂版本的NetWork Inspector 在 App Inspection中。
然後app 訪問網絡會有這樣提示:
我們選中波動 ,可以看到請求的信息:
然後我們點擊接口信息之後,可以看到請求的詳細信息:
這樣我們就可以通過AndroidStudio的Profiler 輕鬆地抓取我們App 的網絡信息了。
使用Charles 工具抓包
1.安裝證書
首先下載Charles ,打開之後點擊Help->SSL Proxying -> Install Charles Root Certificate 安裝根證書
然後雙擊證書,進行信任
電腦端這就配置完了, 接下來配置 客户端
方式1:
手機端通過瀏覽器下載證書。
手機端 對連接wifi 進行代理設置,設置手動代理,將charles 提示的代理地址 設置好,然後charles 就會有一個提示:
然後我們同意就好了。
然後瀏覽器輸入chls.pro/ssl 進行下載證書,下載完成進行安裝即可;不過有時候這種方式無法安裝,可以通過方式2進行安裝。
方式2:
通過Help->SSL Proxying -> Save Charles Root Certificate 將證書保存在電腦上
然後上傳到手機端,點擊設置-安全-加密與憑證-安裝證書-CA證書,選擇我們剛剛的證書進行安裝即可。
至此,安裝證書的步驟我們就完成了。
2.抓包
此時,當我們進行網絡訪問 的時候,可以在charles上面看到我們訪問的數據了
我們可以通過左下角的Filter 進行地址過濾,找到我們想看的網絡數據。
防止抓包
前面講到,默認的 Android Https 配置下,只要使用 Android7.0 以下的手機、或者找個 Root 設備安裝把用户證書(比如charles證書)想辦法搞進系統證書那部分,就可以抓包了。這對於黑產來説也忒忒忒簡單了。那麼怎麼防止呢?
答案是配置你信任的網站證書或者配置信任的認證鏈。
**1.Android 官方配置信息證書
(聲明:這種方法只能防篡改設備的根證書,防不了使用 Android7.0 以下的手機。)**
比如你可以像這樣把你信任的網站的證書給搞下來
步驟①:點擊域名旁邊鎖的圖標,彈出框裏面點「證書」
mac系統,對着證書那個圖標拖動到某個文件夾裏。這樣你就能得到一個HTTPS的裏面的SSL裏面的非對稱加密算法的公鑰。
步驟②:放進 res/raw 文件夾裏,在network_security_config.xml 裏寫上相關配置
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<!-- 這個是全局的基礎的配置 -->
<base-config>
<trust-anchors>
<!-- 如果整個base-config都不寫,就等於是<certificates src="system" /> -->
<!-- 這裏寫全局基礎配置,只信任下面某幾個證書 -->
<certificates src="@raw/zhihu" />
<certificates src="@raw/baidu" />
</trust-anchors>
</base-config>
<!-- 如果只對某些涉及數據安全的私密域名進行保護,可以針對某個域名,只信任某幾個證書 -->
<domain-config>
<domain includeSubdomains="true">zhihu.com</domain>
<trust-anchors>
<certificates src="@raw/zhihu" />
<certificates src="@raw/tencent" />
</trust-anchors>
</domain-config>
<debug-overrides>
<trust-anchors>
<certificates src="user" />
</trust-anchors>
</debug-overrides>
</network-security-config>
以上就是 Android 官方推薦的做法。
——————————————— 分割線 ———————————————
**2. OkHttp 配置信任認證鏈
(聲明:這種方法是全方面防禦,在 Android7.0 以下設備也能起作用)**
步驟①:寫一個 CertificatePinner 的配置
其中的 add方法兩個參數。第一個參數是網址的域名host,第二個是sha256的證書。證書我們目前不清楚,先輸入這麼一段字符串。使用這麼一段錯誤的配置運行後將會報錯,然後在日誌裏得到正確的配置信息。
注意第一個參數不要包含協議,也不要省略部分域名,錯誤示例 「https://news-at.zhihu.com」、「zhihu.com」。
第二個參數是個假證書識別串,但是有效的,我測試時候亂輸入了一串「sha256/wrong」沒有觸發到搜想要的結果。
public class ZhihuHttp {
public static final String ZHIHU_BASE_URL = "https://news-at.zhihu.com/api/";
private static final ZhihuHttp zhihuHttp = new ZhihuHttp();
private OkHttpClient okHttpClient;
private ZhihuHttp() {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.connectTimeout(10, TimeUnit.SECONDS);
// 只信任網站對應的證書
CertificatePinner certificatePinner = new CertificatePinner.Builder()
.add("news-at.zhihu.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
.build();
builder.certificatePinner(certificatePinner);
okHttpClient = builder.build();
}
public static ZhihuHttp getZhihuHttp() {
return zhihuHttp;
}
public void getDailiesWithCallback() {
Request request = new Request.Builder()
.url(ZHIHU_BASE_URL + "4/news/latest")
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
Log.e("YAO", "ZhihuHttp.java - onFailure() ----- e:" + e.toString());
e.printStackTrace();
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
Log.e("YAO", "ZhihuHttp.java - onResponse() ----- :" + response.toString());
}
});
}
}
步驟②:執行代碼後報錯。搜索關鍵字,我們能得到這麼一串報錯
Subscriber onError() : javax.net.ssl.SSLPeerUnverifiedException: Certificate pinning failure!
Peer certificate chain:
sha256/f5fNYvDJUKFsO51UowKkyKAlWXZXpaGK6Bah4yX9zmI=: CN=*.zhihu.com,OU=IT,O=智者四海(北京)技術有限公司,L=北京市,C=CN
sha256/zUIraRNo+4JoAYA7ROeWjARtIoN4rIEbCpfCRQT6N6A=: CN=GeoTrust RSA CA 2018,OU=www.digicert.com,O=DigiCert Inc,C=US
sha256/r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E=: CN=DigiCert Global Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US
Pinned certificates for news-at.zhihu.com:
sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
這報錯的意思是。現在訪問這個鏈接的認證鏈是 Peer certificate chain 下面的3個sha256。
「sha256/f5fNYvDJUKFsO51UowKkyKAlWXZXpaGK6Bah4yX9zmI=」
「sha256/zUIraRNo+4JoAYA7ROeWjARtIoN4rIEbCpfCRQT6N6A=」
「sha256/r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E=」
鏈的含義是,第一個sha256對應的證書由第二個sha256對應的證書認證,第二個sha256對應的證書又第三個sha256對應的證書認證。
在代碼裏配置的用於「news-at.zhihu.com」域名的認證 sha256 期望是
「sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=」
因為兩者對應不上,所以請求失敗。然而通過這個方法,我們得到正確的sha256,下面就拿這幾個正確的sha256來配置。
步驟③:配置正確 sha256
CertificatePinner certificatePinner = new CertificatePinner.Builder()
//正常請求下的證書驗證鏈路
.add("news-at.zhihu.com", "sha256/f5fNYvDJUKFsO51UowKkyKAlWXZXpaGK6Bah4yX9zmI=")//CN=*.zhihu.com,OU=IT,O=智者四海(北京)技術有限公司,L=北京市,C=CN
.add("news-at.zhihu.com", "sha256/zUIraRNo+4JoAYA7ROeWjARtIoN4rIEbCpfCRQT6N6A=")//CN=GeoTrust RSA CA 2018,OU=www.digicert.com,O=DigiCert Inc,C=US
.add("news-at.zhihu.com", "sha256/r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E=")//CN=DigiCert Global Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US
.build();
配置後,這個域名的請求就不能被抓包了。因為開啓抓包後,根證書是 charles 的公鑰,跟期望的 sha256 匹配不上。
一個很重要的點是,其實我們可以不用把3個 sha256 都加上。匹配邏輯是任意一個 sha256 匹配上請求就可以通過了。所以其實可以這麼寫。
CertificatePinner certificatePinner = new CertificatePinner.Builder()
//正常請求下的證書驗證鏈路
.add("news-at.zhihu.com", "sha256/f5fNYvDJUKFsO51UowKkyKAlWXZXpaGK6Bah4yX9zmI=")//CN=*.zhihu.com,OU=IT,O=智者四海(北京)技術有限公司,L=北京市,C=CN
.build();
域名hostname 支持通配符,可以參考OkHttp CertificatePinner部分
驗證結果
按照 OkHttp 官方指導配置完後,使用 charles 抓包看看還能不能在 Android 7.0 以下系統抓到包。
驗證結果,不能抓包,會出現一個報錯:
Subscriber onError() : javax.net.ssl.SSLPeerUnverifiedException: Certificate pinning failure!
Peer certificate chain:
sha256/dVUJFtUhQtJki5t0/j+hMYzTgtVkETqjsogUuyquPPo=: CN=*.zhihu.com,OU=IT,O=智者四海(北京)技術有限公司,L=北京市,C=CN
sha256/54ZQa+M6vq6DhdR7DLkc1X6fWmVEZ6wLZaaYwoR4Uvw=: C=NZ,ST=Auckland,L=Auckland,O=XK72 Ltd,OU=https://charlesproxy.com/ssl,CN=Charles Proxy CA (2 十月 2017\, YaodeMacBook-Pro.local)
Pinned certificates for news-at.zhihu.com:
sha256/f5fNYvDJUKFsO51UowKkyKAlWXZXpaGK6Bah4yX9zmI=
sha256/zUIraRNo+4JoAYA7ROeWjARtIoN4rIEbCpfCRQT6N6A=
sha256/r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E=
可以看到現在訪問這個鏈接的認證鏈是 Peer certificate chain 下面的兩個sha256。
「sha256/dVUJFtUhQtJki5t0/j+hMYzTgtVkETqjsogUuyquPPo=」
「sha256/54ZQa+M6vq6DhdR7DLkc1X6fWmVEZ6wLZaaYwoR4Uvw=」
報錯的信息裏,第二個 sha256 冒號後面,顯示這串字符來自我的 charles 公鑰。
對比 未使用 和 使用 抓包的報錯信息,發現第一個 sha256 都是來自於知乎的公鑰,但兩個的 sha256 是不一樣的。
//未開啓抓包
sha256/f5fNYvDJUKFsO51UowKkyKAlWXZXpaGK6Bah4yX9zmI=: CN=*.zhihu.com,OU=IT,O=智者四海(北京)技術有限公司,L=北京市,C=CN
//開啓抓包
sha256/dVUJFtUhQtJki5t0/j+hMYzTgtVkETqjsogUuyquPPo=: CN=*.zhihu.com,OU=IT,O=智者四海(北京)技術有限公司,L=北京市,C=CN
一開始我一直以為這一串東西是SSL公鑰進行一次hash算法得到的字符串。後面觀察後發現不是。
這是兩個公鑰在不同 「中間證書認證」-「中間證書認證」……「根證書認證」這種認證體系下的一個hash串。
所以如果開啓抓包,那麼他對應的根證書是 charles 的公鑰,得出的第一個來自知乎證書的 sha256 就會有所不同。
warning: 配置信任某個具體證書一定要與服務器開發或運維溝通好,因為如果服務器進行了證書替換而App沒有更新到最新證書,App的請求將會失效。如果開啓的是全部域名的證書配置,意味着你連應用內升級或者熱更新都用不了,絕對是重大事故。
還有什麼騷操作
上面講到我們配置到工程代碼裏的是 網站的公鑰(任何人都可以隨意下載)
根據HTTPS的原理,公鑰和私鑰的原理,其實完全可以在代碼裏配置上開發者的 charles 公鑰(只針對某台具體的筆記本,charles 為它生成的一對公鑰私鑰)。因為沒人能根據公鑰能破解出對應的私鑰。
所以如果在在 app 裏配上我們某部電腦 charles 公鑰,以後就可以用那個電腦抓正式環境正式域名的請求了。比如工程加上公司的公用開發機的 charles 公鑰,或者核心App測試大佬的 charles 公鑰。
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<!-- 這個是全局的基礎的配置 -->
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<!-- 如果整個base-config都不寫,就等於是<certificates src="system" /> -->
<!-- 這裏寫全局基礎配置,只信任下面某幾個證書 -->
<certificates src="@raw/zhihu" />
<certificates src="@raw/yao_charles" />
</trust-anchors>
</base-config>
<debug-overrides>
<trust-anchors>
<certificates src="user" />
</trust-anchors>
</debug-overrides>
</network-security-config>
使用OkHttp的配置的方法,這麼寫:
// 只信任網站對應的證書
CertificatePinner certificatePinner = new CertificatePinner.Builder()
//正常請求下的證書驗證鏈路
.add("news-at.zhihu.com", "sha256/f5fNYvDJUKFsO51UowKkyKAlWXZXpaGK6Bah4yX9zmI=")//CN=*.zhihu.com,OU=IT,O=智者四海(北京)技術有限公司,L=北京市,C=CN
.add("news-at.zhihu.com", "sha256/zUIraRNo+4JoAYA7ROeWjARtIoN4rIEbCpfCRQT6N6A=")//CN=GeoTrust RSA CA 2018,OU=www.digicert.com,O=DigiCert Inc,C=US
.add("news-at.zhihu.com", "sha256/r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E=")//CN=DigiCert Global Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US
//charles 抓包下的配置
.add("news-at.zhihu.com", "sha256/dVUJFtUhQtJki5t0/j+hMYzTgtVkETqjsogUuyquPPo=")//CN=*.zhihu.com,OU=IT,O=智者四海(北京)技術有限公司,L=北京市,C=CN
.add("news-at.zhihu.com", "sha256/54ZQa+M6vq6DhdR7DLkc1X6fWmVEZ6wLZaaYwoR4Uvw=")//C=NZ,ST=Auckland,L=Auckland,O=XK72 Ltd,OU=https://charlesproxy.com/ssl,CN=Charles Proxy CA (2 十月 2017\, YaodeMacBook-Pro.local)
.build();