Android 隱私合規檢測
目前應用市場的隱私合規檢查越來越嚴格,各大手機廠商的檢測標準也不一致,經常有這個平台過審了那個平台還有問題出現,按照工信部的要求,工信部隱私合規説明。隱私合規是個不可不重視的點。
我們通常遇到的主要問題:
-
在用户同意隱私協議之前,不能有收集用户隱私數據的行為。例如:在用户同意協議之前不能去獲取 Android ID、Device ID、MAC 等隱私數據。
-
在用户同意隱私協議之後,獲取權限時必須要符合當前使用場景,例如:我們需要獲取手機讀寫,相機權限,這種需要在真正的讀寫,打開相機等頁面時才能去請求權限。
如上問題處理可分為兩種:權限 和 隱私
-
權限 需要在對應頁面即 app內獲取權限時主動設置彈窗等方式給予app相應的權限
'如電話權限,定位權限,相機權限,浮窗權限,讀寫權限等。在每個申請危險權限前,都需要彈窗説明權限解釋説明。' - 隱私 為app使用過程中與用户個人相關的個人信息
'如位置,Mac地址,設備id等。就Android端而言,多數隱私信息需要對應授權後才能獲取,但目前仍存在部分隱私信息無需授權就可以拿到的'
如何檢測
一、第三方檢測
二、靜態檢測
-
Lint 檢查項目
Lint用於檢測靜態代碼和資源,找到其中不符合預定義規則的地方。可參考網易雲隱私合規靜態檢查
-
反編譯查找對應方法
反編譯主要是為了找出第三方的一些不合規方法調用,但是比較麻煩,全局搜索很不方便
三、動態檢測(開源)
-
1、Xposed
優點 :Xposed 是比較早的做hook的框架, Xposed框架可以在不修改APK文件的情況下影響程序運行(修改系統)的框架服務,基於它可以製作出許多功能強大的模塊,且在功能不衝突的情況下同時運作。Android中一般存在兩種hook:sdk hook和ndk hook。native hook的難點在於理解ELF文件與學習ELF文件,Java層Hook則需要了解虛擬機的特性與java上的反射使用。另外還存在全局hook,即結合sdk hook和ndk hook,xposed就是一種典型的全局hook框架。
缺點:需要手機ROOT
-
2、VirtualXposed
優點 :VirtualXposed 是基於VirtualApp 和 epic 實現的,能在非ROOT環境下直接運行Xposed模塊 (目前支持5.0~10.0)。其實VirtualXposed就是一個支持Xposed的虛擬機,我們把開發好的Xposed模塊和對應需要hook的App安裝上去就能實現hook功能。
缺點:步驟相對麻煩,de.robv.android.xposed 的依賴需要翻牆。
-
3、epic
優點 :配置簡單,屬於運行時hook,説明在動態加載dex也能檢測到,也是我目前再用的,可以自定義配置hook 對應的類和方法,並找出當前調用線程堆棧,直接定位到調用的方法。
缺點:兼容問題,Android 11及以上只能支持 64位,不過這個不影響11以下的使用;只檢測java類代碼,native沒有hook 。
-
接入相對複雜,基於自定義transform , 編譯期註解+hook方案,第一個transform收集需要攔截的敏感函數,第二個transform替換敏感函數,運行期收集日誌,同時支持遊客模式。
有java.util.zip.ZipException: duplicate entry: META-INF/INDEX.LIST 衝突風險。
-
5、camille
使用
python
Frida
等工具命令,做hook 模塊,手機需要Root,功能強大但相對複雜 -
6、自定義Asm插件,做代碼插入檢測
可以在class->dex時,對相應的類、調用方法,做檢測。添加我們的攔截代碼
四、epic落地
- 我這裏使用的時 epic 檢測,直接依賴:
implementation 'me.weishu:epic:1.0.0'
implementation 'me.weishu.exposed:exposed-xposedapi:0.4.5'
主要核心是 DexposedBridge.findAndHookMethod
方法
``` //targetClass: 傳入 需要hook 的類,如:TelephonyManager.class //targetMethod:類對應的方法,如:getDeviceId DexposedBridge.findAndHookMethod(targetClass, targetMethod, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { super.beforeHookedMethod(param);
//被調用的類名
String className = param.method.getDeclaringClass().getName();
//被調用的函數名
String methodName = param.method.getName();
LogAction.log("檢測到 " + className + " 被調用: methodName=" + methodName);
//這裏可以蒐集當前的線程信息,堆棧等,將調用關係打印出來,例如:
//Thread thread = Thread.currentThread();
//StringBuilder stringBuilder = new StringBuilder();
//獲取線程信息
//String threadInfo = getThreadInfo(thread);
//stringBuilder.append(threadInfo);
// 返回表示此線程的堆棧轉儲的堆棧跟蹤元素數組。
// 如果這個線程還沒有啟動,已經啟動但還沒有被系統計劃運行,或者已經終止,這個方法將返回一個零長度的 數組。
//StackTraceElement[] stackTraceElements = thread.getStackTrace();
//String print = printToString2(stackTraceElements);
//stringBuilder.append("線程堆棧日誌:").append(print);
//LogAction.log(stringBuilder);
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
}
}); ```
例如,我這裏用了 leakcanary
做檢測時會提示的
因為我對 android.app.ApplicationPackageManager
這個類做了檢測,queryIntentActivities
方法被調用時即觸發了beforeHookedMethod
五、集成優化處理
- 我們可以自己定義一個module模塊,單獨處理合規檢測,利用
debugImplementation
的方式集成,不會影響到線上 - 可以使用
ContentProvider
做初始化入口,debugImplementation
集成進來即可,在ContentProvider onCreate
的時候去 start啟用 需要hook 的集合類。 - 可以使用企業微信提供
API Token
,在收到 隱私限制方法被調用時,觸發消息發送,方便測試和提示,不需要去看log日誌。