做者:字節跳動終端技術——譚子敬html
業務安全合規檢測經過 CI/CD 階段卡口,針對新增代碼進行分析檢查、合碼管控、問題溯源,針對構建產物進行發版管控,避免隱私、合規相關問題被帶到線上引起安全合規風險。前端
隨着互聯網技術的高速發展,國內外用戶隱私數據相關法律法規日趨完善、行政管制也趨於常態化、用戶隱私數據安全意識也在逐步提高,移動應用上線後出現隱私數據安全合規問題的風險也愈加不可控。git
如下簡要列舉近年來國內外隱私合規相關法律法規與通知通報:算法
2021-03-21|工信部|《關於侵害用戶權益行爲的APP通報(2021年第3批,總第12批)》安全
2020-07-24|工信部 |《關於開展縱深推動APP侵害用戶權益專項整治行動的通知》服務器
2019-12-30|工信部|《App違法違規收集使用我的信息行爲認定方法》markdown
2019-02-27|美國|《數據隱私法案》併發
2018-05-25|歐盟GDPR|《通用數據保護條例》maven
以下圖,業務安全檢測被歸入質量檢測體系後,主要在 CI(Continuous Integration,持續集成)、CD(Continuous Delivery,持續交付)階段創建檢測卡口,一旦發現存在業務安全合規風險,即阻止代碼合入或阻止應用發佈、以此規避業務安全合規風險。函數
咱們首先針對比較核心的需求(如:敏感API、敏感權限、敏感字符串)基於 gradle transform 和 ASM 實現了對 Android 編譯中間產物的檢測,即 CI 中間產物檢測。
大體的掃描過程以下圖所示:
當 feature1 分支完成開發測試、準備合入 develop 分支時,
首先,會同時觸發拉出 feature1 分支的節點和待合入develop分支的節點分別進行構建打包;
而後,兩個節點在各自的構建過程當中分別對編譯中間產物進行分析檢查、將命中規則的方法做爲 issue 進行記錄,構建結束便可分別獲得圖示中的 「初始全量問題」 和 「當前全量問題」;
接着,再對 「初始全量問題」 和 「當前全量問題」 進行 diff(差分)、便可獲得 feature1 分支從建立到合入主分支之間新增的問題;
最後,對存在增量問題的 MR 進行管控、阻止該分支代碼合入主分支,直到 RD 修復全部增量問題或者報備、審批經過後方可合入。
Scanner 是 Android CD階段的產物檢測工具,基於 aapt、apktool、keytool、strings 等命令行工具實現了對apk/aar/aab/so 等 Android 相關二進制產物的安全檢查。大體工做流程以下圖所示:
Scanner 對 Android 二進制產物中最重要的字節碼的掃描,是基於 apktool 反編譯獲得的 smali 文件,先反編譯、而後併發逐行掃描 smali 文件,檢查是否存在安全合規問題。
如何對開源代碼中包含的 License 信息進行合規檢查?顯然 CI 中間產物檢測沒法知足需求,只能基於源碼進行。
因爲 Android 編譯中間產物對應的源碼在構建時通過脫糖等一系列優化處理,源碼文件中的語法糖、行號等原始信息均已沒法還原,這就給檢出問題的定位、排查增長了很大的工做量。
CD 階段基於 smali 文件的掃描每每只能掃描出敏感 API 的直接調用位置,而沒法覆蓋全部的調用鏈條,這就給問題的審覈帶來了挑戰。
以下圖,以剪切板相關 API 爲例,同一條敏感 API 可能既存在常規的調用場景、又存在非法的調用場景,當非法調用出如今新增間接調用場景、而該調用點又在老版本評估 「不需整改」,此時就會存在問題漏放風險。同時,調用點在問題排查時信息量有限、每每須要花費必定的精力去搜索/分析,不利於問題的定位與解決。
爲了解決 CI 中間產物檢測沒法覆蓋源碼相關檢測、檢出問題定位成本高等問題,咱們又實現了一套 CI 增量源碼檢測。大致思路是基於 git diff 獲取每一個 MR 對應的全部新增源碼(包含一二方組件),而後再對這些增量源碼進行各項安全檢查與合碼管控,即 CI 增量源碼檢測。
獲取一次 MR 過程當中增量源碼的主要步驟包含如下 3個子流程:獲取源碼變動信息子流程、源碼 diff 子流程、精準獲取組件增量源碼子流程。下面結合流程圖分別對 3 個關鍵子流程作詳細說明:
源碼變動信息包含 主倉/子倉的源碼倉庫及commit信息、變動組件所在的源碼倉庫及commit信息。
以 Android 工程爲例,
首先,研發人員提交 MR 時觸發檢查,可直接得到 主倉/子倉的源碼變動信息(倉庫地址、base commit、review commit);
而後,根據主倉的源碼變動信息、分別下載主倉兩個 commit 的工程源碼;
接着,經過 gradle 命令(iOS 經過 pod 命令)分別獲取主倉兩次 commit 的組件依賴樹信息,解析組件依賴樹並對其進行 diff(差分)、便可獲得兩次提交之間的組件變動信息(新增組件和更新組件);
最後,經過組件管理模塊,根據組件變動信息中的 maven座標 和 版本號,能夠獲取組件的原始 git 倉庫以及兩個版本號各自對應的 commit 信息,即變動組件所在的源碼倉庫和 commit 信息。
組件變動存在新增組件、更新組件和刪除組件等操做,增量源碼只需關注新增組件和更新組件。
組件管理模塊負責組件的發佈、升級,會記錄組件的原始 git 倉庫、版本號與 commit 的對應關係。其沒有記錄的組件爲三方組件,三方組件無源碼、不需考慮。
基於已經得到的源碼變動信息,源碼 diff 子流程以下圖所示:
首先,下載 MR 準備合入主分支的 commit(即圖示中的 review commit)對應工程的源碼;
而後,經過 git diff 命令獲取 base commit 和 review commit 之間的代碼變動信息;
接着,遍歷代碼變動信息(對更新組件還需過濾組件目錄下的代碼變動信息)、獲取存在新增源碼或更新源碼的文件及變動的行號信息(diffs 結果中以 "+" 開頭的變動行),將全部的源碼變動文件及其變動行號信息記錄下來壓縮進 zip 包(即增量源碼包);
最後,將增量源碼包上傳到服務器、供下游的各類檢測服務使用。
新增組件與更新組件的區別在於新增組件須要對組件包含的源碼進行全量獲取,組件源碼文件中的每一行都須要進行檢查,其餘步驟與更新組件徹底一致。
一個庫工程(git 工程)中可能存在大量的組件(甚至混合 Android、iOS組件),咱們獲取到變動組件所在源碼倉庫的代碼變動可能包含其餘組件的內容,爲避免誤報、須要獲取組件在其源碼倉庫中的精準路徑
以 Android 工程爲例,
首先,經過組件管理模塊獲取組件所在源碼倉庫中的模塊名稱、將 gradle 自定義 task 注入組件源碼倉庫;
而後,執行 gradle 自定義 task 獲取源碼倉庫中全部組件的模塊名稱與對應的源碼路徑;
接着,匹配變動組件的模塊名稱、獲取變動組件的源碼路徑;
最後,在源碼 diff 子流程遍歷代碼變動信息時經過組件路徑過濾出變動組件的增量源碼信息,將變動組件的增量源碼打入增量源碼包,實現組件增量源碼的精準獲取。
原先基於編譯中間產物的檢測僅能支持 Android 工程,對於 iOS 還須要額外實現一套檢測方案。而 CI 增量源碼檢測不只覆蓋了 Android/iOS 雙端主/子倉的源碼檢測需求,並且還覆蓋了該次編譯所涉及的全部新增/變動一二方組件的增量源碼檢測,知足了 License 合規檢測以及開源項目的安全合規檢測需求。
基於源碼,咱們實現了將檢出的問題與其對應的代碼倉庫、組件目錄、源碼文件、問題所在行數進行自動精準關聯,同時還能夠按照倉庫/組件等維度將問題自動進行聚合、分發給不一樣的 Owner 跟進處理,大大提升了問題的消費效率、下降了問題的定位解決成本。
因爲在 scanner 掃描過程當中存在大量 IO 操做(反編譯生成 smali 文件、逐個掃描 smali),儘管採用了併發等手段,其掃描時間依然較長(屢次掃描同一個 86M 的包平均耗時 175.28s)。
在 smali 掃描過程當中有兩個特別耗時的環節,一個是掃描 dex/apk 生成 smali 文件、另外一個是批量掃描生成的 smali 文件進行安全合規檢查。
思考:若是前一個環節咱們能直接在內存中完成敏感信息的安全合規檢查、同時不生成 smali 文件,掃描耗時是否可能大幅下降呢?
在咱們的實驗過程當中直接基於 Dex 提取 method callgraph,使用一樣的規則、屢次掃描一樣的包(86M),平均掃描時間由原先的 175.28s 進一步下降到 32.72s,大大提高了包檢測掃描的效率。
針對前面提到的 「基於敏感調用點潛藏的漏放風險」,假設咱們可以知道函數調用關係,就能從調用點關聯到上層業務代碼,從點到鏈擴展檢測維度,根本上解決間接調用檢測遺漏的問題。
顧名思義,從調用點到 "main" 之間的鏈路。
對於 Android 應用而言,通常沒有 main 入口,須要根據Android特性,去模擬一個假的 main 入口,通常叫 DummyMain: 四大組件和 Application 生命週期函數;xml 綁定的函數,好比 onclick、databinding 等。
調用鏈的優勢
關聯上層業務代碼、助力問題的快速定位與解決;
基於 CallGraph 覆蓋全部調用場景,助力 SDK依賴梳理、API 調用梳理。
調用鏈的生成對於敏感問題的排查意義重大,業務方能夠根據生成的調用鏈按圖索驥、找到問題實際的調用鏈路,避免了間接調用形成的漏放風險。
在咱們生成調用鏈、助力問題的快速定位解決、實現了 API 調用場景的梳理後,咱們又進一步實現了 SDK 依賴梳理。所謂 SDK 依賴梳理,就是掃描出 SDK 中全部 public 未混淆 API、而後進一步掃描出這些 API 在 apk 中的全部調用鏈,經過 SDK 依賴梳理,咱們能夠垂手可得地梳理出 apk 具體在哪些業務場景下、經過哪些接口依賴了 SDK. 進而很容易地判斷出敏感 API 的調用狀況,也能夠助力 SDK/模塊 之間的解耦。
本文首先從業務安全合規檢測的業務背景和技術背景入手,介紹了 CI/CD 階段業務安全合規檢測的現狀與難點,而後介紹了咱們在 CI/CD 階段分別作出的改進:CI 增量源碼檢測、BDAnalysis 引擎,及相應的收益。
CI 增量源碼檢測覆蓋了 Android/iOS 雙端主/子倉及其所依賴一二方組件的源碼檢測、實現了檢出問題的自動精準定位與問題聚合,大大提高了檢出問題的消費效率;CD 產物檢測基於 BDAnalysis 引擎實現了調用鏈的生成、彌補了可能存在的漏放風險、同時咱們也用 dex 掃描替代 smali 掃描將 CD 產物檢測的平均耗時從 175s 下降至 32s,大大提高了檢測工具的精度與速度。
CI/CD 業務安全合規檢測還存在一些不足之處,好比效果指標建設、CI/CD 數據打通等,針對這些不足,咱們後續將逐步進行完善、持續爲各大業務 Android 端應用安全合規地運行保駕護航。
工具定位。主推 CI 增量源碼檢測、發揮其精準溯源優點;CI 中間產物檢測輔助校驗檢測結果、避免 issue 漏放。
指標建設。在現有技術指標的基礎上、完善效果指標,建設 issue 「檢出率」、「消費率」、「誤報率」、「滿意度」等指標。
數據打通。打通 CI/CD 調用鏈,升級 issueID打通方案。
工具定位。檢測工具逐步廢棄 Scanner 工具,建設功能強大的新檢測工具 BDInspect.
指標建設。針對新老檢測工具與 BDAnalysis 引擎建設相應的技術指標及自動告警機制。
引擎建設。建設 BDAnalysis 引擎,實現調用鏈與賦值鏈落地到更多業務場景。
字節跳動終端技術團隊(Client Infrastructure)是大前端基礎技術的全球化研發團隊(分別在北京、上海、杭州、深圳、廣州、新加坡和美國山景城設有研發團隊),負責整個字節跳動的大前端基礎設施建設,提高公司全產品線的性能、穩定性和工程效率;支持的產品包括但不限於抖音、今日頭條、西瓜視頻、飛書、瓜瓜龍等,在移動端、Web、Desktop等各終端都有深刻研究。
就是如今!客戶端/前端/服務端/端智能算法/測試開發 面向全球範圍招聘!一塊兒來用技術改變世界,感興趣能夠聯繫郵箱 chenxuwei.cxw@bytedance.com,郵件主題 簡歷-姓名-求職意向-指望城市-電話。