繞過安卓SSL驗證證書的四種方式
在此之前,移動端應用程式會直接忽略掉所有的SSL錯誤,並允許攻擊者攔截和修改自己的通訊流量。但是現在,很多熱門應用程式至少會檢查證書鏈是否是一個有效可信任的證書機構(CA)頒發的。
作為一名滲透測試人員來說,我們常常需要讓目標應用程式信任我們的證書是有效的,這樣我們就可以進行中間人攻擊(MITM)並修改其流量了。在這篇文章中,我們將給大家介紹四種繞過Android SSL驗證的方式。
SSL MitM
為什麼我們要特別關注移動端應用程式的SSL MitM安全情況呢?為了觀察或對移動端應用程式的Web服務呼叫情況,我們需要使用類似BurpSuite或ZAP這樣的攔截代理。當我們利用代理攔截下SSL流量之後,客戶端的SSL連結將會中斷。預設情況下,類似Burp這種工具所生成的自簽名證書將失效,如果證書不被信任,那麼移動端App將會中斷連線。接下來,我們所要介紹的技術將能夠讓移動端應用程式信任我們的攔截代理所提供的證書。
技術#1-向用戶證書中新增自定義CA
避免SSL錯誤的最好方法就是設定一個有效可信任的證書。這種方法相對比較簡單,如果你可以向裝置安裝一個新的可信任CA證書,並且作業系統信任你的CA,那麼它就會信任由你CA簽名的證書。
Android有兩個內建的證書儲存(即System Store和User Store),它們會對作業系統信任的CA進行跟蹤。其中System Store用於儲存預裝的CA,User Store儲存使用者安裝的CA。預設配置下,使用了類似TLS或HTTPS的安全連線會信任預安裝的系統CA,而Android 6.0(API Level23)及以下版本預設會新人使用者新增的CA。
這意味著什麼呢?如果我們向User Store中新增自己的CA,那我們就可以嘗試對Android 6.0及以下版本的裝置進行中間人攻擊了。如果針對的是高於Android 6.0版本的裝置,那麼我們所新增的證書將不會被信任。為了解決這個問題,我們可以編輯應用程式的Manifest檔案,並強制它適配Android 6.0。目標API Level定義在AndroidManifest.xml檔案中的‘platformBuildVersionCode’屬性(’manifest’元素):
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.test.app" platformBuildVersionCode="25"platformBuildVersionName="7.1.1">
我們要把‘platformBuildVersionCode=25’改成23:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.test.app" platformBuildVersionCode="23"platformBuildVersionName="6.0">
重新打包之後,應用程式將會信任使用者新增的CA證書了。
當然了,如果你想要在特定平臺版本中執行的話,你也可以在APK的‘/res/xml/network_security_config.xml’檔案中定義一個<trust-anchors>。比如說,下面的程式碼就定義了一個新的受信任CA,檔案儲存在/res/raw/my_ca:
<?xm lversion="1.0" encoding="utf-8"?>
<network-security-config>
<base-config>
<trust-anchors>
<certificates src="@raw/my_ca"/>
</trust-anchors>
</base-config>
</network-security-config>
這樣一來,我們就能夠順利完成MitM了。
技術#2-用自定義CA證書重寫已打包的CA證書
如果第一種方法不起效的話,可能是因為開發人員限制了應用程式所能信任的CA證書了。還記得剛才我們使用自定義的<trust-anchors> 來提供CA證書路徑嗎?而開發人員同樣可以使用這種方法來保護自己的應用程式免受SSL攔截攻擊。
在這種場景下,為了讓我們的攔截證書可以被信任,我們就需要提取APK並用我們自定義的CA證書來重寫應用程式所提供的CA證書。需要注意的是,這種方法可能會要求進行一系列驗證。
使用APK Studio之類的工具開啟APK檔案,然後在視窗中找到應用程式所捆綁的證書。在上圖中,證書位於應用程式的assets目錄下。接下來,用我們自定義的CA覆蓋應用程式原本的CA(‘UniversalRootCA’證書),這樣就可以讓應用程式直接信任我們的證書了並實現流量攔截了。
技術#3-Frida Hook
如果安裝自定義CA也無法成功的話,說明應用程式可能使用了某種SSL繫結技術或採用了額外的SSL驗證。一般來說,為了繞過這種驗證方法,我們需要對應用程式的程式碼以及驗證介面設定鉤子。這種介面一般用於限制手機被root或越獄,但是在Frida框架【工具下載】的幫助下,我們就可以在不root裝置的情況下,對應用程式進行動態分析了。
Frida可以在作業系統中以獨立應用程式的形式執行,但是這需要對裝置進行root。為了避免root操作,我們可以直接將Frida注入到目標APK之中。Frida工具中包含了一個能夠讓應用程式在執行時載入Frida的動態庫,並允許我們對目標應用程式的程式碼和指令進行動態修改。
接下來,我們需要提取APK檔案,注入動態庫,然後編輯一些smali程式碼來讓我們的程式碼庫在應用程式啟動時最先被呼叫。完成之後,重新打包APK並進行安裝。整個過程的完整操作方法可以參考【這篇文章】。
除此之外,我們也可以使用Objection工具【專案地址】來實現我們的目標。Objection可以讓整個過程自動化完成,我們只需要在命令列中提供目標APK的路徑,Objection就可以幫我們完成所有的程式碼注入以及修改操作。
C:\>objection patchapk -s test_app.apk
No architecture specified. Determining it using `adb`...
Detected target device architecture as: armeabi-v7a
Github FridaGadget is v10.6.28, local is v10.6.13. Updating...
Downloading armeabi-v7a library toC:\.objection\android\armeabi-v7a\libfrida-gadget.so.xz...
Unpacking C:\.objection\android\armeabi-v7a\libfrida-gadget.so.xz...
Cleaning up downloaded archives...
Using Gadget version: 10.6.28
Unpacking test_app.apk
App already has android.permission.INTERNET
Reading smali from:C:\Temp\tmp8dxqks1u.apktemp\smali\com/test/app/TestMainActivity.smali
Injecting loadLibrary call at line: 10
Writing patched smali back to:C:\Temp\tmp8dxqks1u.apktemp\smali\com/test/app/TestMainActivity.smali
Creating library path: C:\Temp\tmp8dxqks1u.apktemp\lib\armeabi-v7a
Copying Frida gadget to libs path...
Rebuilding the APK with the frida-gadget loaded...
Built new APK with injected loadLibrary and frida-gadget
Signing new APK.
jar signed.
Signed the new APK
Performing zipalign
Zipaling completed
Copying final apk from C:\Users\cwass\AppData\Local\Temp\tmp8dxqks1u.apktemp.aligned.objection.apkto current directory...
Cleaning up temp files...
接下來,我們的工作目錄中應該會出現一個名叫‘test_app.objection.apk’的檔案(預設情況下,工具會在原始APK檔名的後面新增一個.objection字尾)。我們可以像安裝普通APK一樣安裝這個檔案,使用命令“adb install test_app.objection.apk”可以直接將其推送到連線裝置上。安裝完成之後執行目標App,此時App將會卡在啟動介面。現在,我們就可以連線到Frida伺服器,並開始監聽裝置流量了。Frida命令列工具的使用方法如下:
C:\>frida-ps-U
PID Name
---- ------
6383 Gadget
C:\>frida-U gadget
____
/ _ |Frida 10.3.14 - A world-class dynamic instrumentation framework
| (_||
>_ | Commands:
/_/|_| help -> Displays the help system
. . .. object? -> Display information about 'object'
. . .. exit/quit -> Exit
. . ..
. . .. More info at http://www.frida.re/docs/home/
[MotorolaMoto G (5) Plus::gadget]-> Java.available
true
Alternatively,Objection supports interaction with the listening Frida server by using the‘explore’ command:
C:\>objectionexplore
___||_ |_|___ ___| |_|_|___ ___
| . |. | | | -_| _| _| | . | |
|___|___|_||___|___|_| |_|___|_|_|
|___|(object)inject(ion)v1.2.2
RuntimeMobile Exploration
by:@leonjza from @sensepost
[tab]for command suggestions
com.test.appon (motorola: 7.0) [usb] # android hooking search classes TrustManager
android.security.net.config.RootTrustManager
android.app.trust.ITrustManager$Stub$Proxy
android.app.trust.ITrustManager
android.security.net.config.NetworkSecurityTrustManager
android.security.net.config.RootTrustManagerFactorySpi
android.app.trust.TrustManager
android.app.trust.ITrustManager$Stub
com.android.org.conscrypt.TrustManagerImpl
com.android.org.conscrypt.TrustManagerImpl$ExtendedKeyUsagePKIXCertPathChecker
com.android.org.conscrypt.TrustManagerImpl$TrustAnchorComparator
com.android.org.conscrypt.TrustManagerFactoryImpl
javax.net.ssl.TrustManagerFactory$1
javax.net.ssl.TrustManager
javax.net.ssl.TrustManagerFactory
javax.net.ssl.X509TrustManager
javax.net.ssl.TrustManagerFactorySpi
javax.net.ssl.X509ExtendedTrustManager
[Ljavax.net.ssl.TrustManager;
此時,你就可以使用內建的SSL繫結繞過函式來實施攻擊了:
com.test.appon (motorola: 7.0) [usb] # android sslpinning disable
Job:2f633f86-f252-4a57-958e-6b46ac8d69d1 - Starting
[6b46ac8d69d1][android-ssl-pinning-bypass] Custom, Empty TrustManager ready
Job:2f633f86-f252-4a57-958e-6b46ac8d69d1 – Started
技術#4-逆向自定義證書的驗證程式碼
當然了,開發人員也有可能會使用自己開發的SSL庫,而不是直接使用系統庫來處理SSL證書驗證過程。如果這樣的話,我們就需要提取出APK檔案,然後將smali程式碼轉換成Java程式碼,這樣我們才可以對負責處理證書驗證的程式碼進行分析,並想辦法實現流量攔截,這裡我們需要使用到dex2jar工具。
dex2jar工具的使用命令語句如下所示:
C:\>d2j-dex2jar.bat"C:\test_app.apk"
dex2jarC:\test_app.apk -> .\test_app-dex2jar.jar
輸出的.jar檔案可以直接在絕大多數Java逆向工具(例如JD-GUI)中開啟。
當你找到了負責處理證書驗證的程式碼之後,你就可以選擇對程式碼進行直接修改或者使用Frida來給特定函式設定鉤子了。為了避免對整個應用程式進行重構,我們可以直接對證書驗證函式設定鉤子。具體的操作方法可以參考技術#3所介紹的內容(使用Frida命令列工具或Objection介面)。
總結
本文所介紹的技術可以允許我們繞過Android開發人員所設定的常見防護措施,並攔截目標Android應用的SSL通訊流量。除此之外,本文還簡單介紹了Objection介面以及Frida工具,這些工具可以幫助我們繞過應用程式的SSL繫結以及其他防護機制。本文揭露了多種繞過給定安全控制的方法,希望這篇文章可以給Android應用程式的安全研究人員提供一些有用幫助。
資源獲取
Frida使用教程(無需root):【傳送門】
Frida框架:【下載地址】
Objection工具:【下載地址】
* 參考來源:netspi,FB小編Alpha_h4ck編譯,轉載請註明來自FreeBuf.COM