字节跳动安全合规检测技术之Android篇

做者:字节跳动终端技术——谭子敬html

业务安全合规检测经过 CI/CD 阶段卡口,针对新增代码进行分析检查、合码管控、问题溯源,针对构建产物进行发版管控,避免隐私、合规相关问题被带到线上引起安全合规风险。前端

背景

1. 业务背景

随着互联网技术的高速发展,国内外用户隐私数据相关法律法规日趋完善、行政管制也趋于常态化、用户隐私数据安全意识也在逐步提高,移动应用上线后出现隐私数据安全合规问题的风险也愈加不可控。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

2. 技术背景

以下图,业务安全检测被归入质量检测体系后,主要在 CI(Continuous Integration,持续集成)、CD(Continuous Delivery,持续交付)阶段创建检测卡口,一旦发现存在业务安全合规风险,即阻止代码合入或阻止应用发布、以此规避业务安全合规风险。函数

现状与难点

现状

咱们首先针对比较核心的需求(如:敏感API、敏感权限、敏感字符串)基于 gradle transform 和 ASM 实现了对 Android 编译中间产物的检测,即 CI 中间产物检测。

CI 中间产物检测

大体的扫描过程以下图所示:

当 feature1 分支完成开发测试、准备合入 develop 分支时,

首先,会同时触发拉出 feature1 分支的节点和待合入develop分支的节点分别进行构建打包;

而后,两个节点在各自的构建过程当中分别对编译中间产物进行分析检查、将命中规则的方法做为 issue 进行记录,构建结束便可分别获得图示中的 “初始全量问题” 和 “当前全量问题”;

接着,再对 “初始全量问题” 和 “当前全量问题” 进行 diff(差分)、便可获得 feature1 分支从建立到合入主分支之间新增的问题;

最后,对存在增量问题的 MR 进行管控、阻止该分支代码合入主分支,直到 RD 修复全部增量问题或者报备、审批经过后方可合入。

CD 产物检测

Scanner 是 Android CD阶段的产物检测工具,基于 aapt、apktool、keytool、strings 等命令行工具实现了对apk/aar/aab/so 等 Android 相关二进制产物的安全检查。大体工做流程以下图所示:

Scanner 对 Android 二进制产物中最重要的字节码的扫描,是基于 apktool 反编译获得的 smali 文件,先反编译、而后并发逐行扫描 smali 文件,检查是否存在安全合规问题。

  • smali 文件示意图

  • Dex 反编译生成 smali 时序图

难点

1. CI 业务安全检测没法覆盖源码

如何对开源代码中包含的 License 信息进行合规检查?显然 CI 中间产物检测没法知足需求,只能基于源码进行。

2. CI 业务安全检测检出问题定位成本高

因为 Android 编译中间产物对应的源码在构建时通过脱糖等一系列优化处理,源码文件中的语法糖、行号等原始信息均已没法还原,这就给检出问题的定位、排查增长了很大的工做量。

3. CD 产物检测基于敏感调用点潜藏的漏放风险

CD 阶段基于 smali 文件的扫描每每只能扫描出敏感 API 的直接调用位置,而没法覆盖全部的调用链条,这就给问题的审核带来了挑战。

以下图,以剪切板相关 API 为例,同一条敏感 API 可能既存在常规的调用场景、又存在非法的调用场景,当非法调用出如今新增间接调用场景、而该调用点又在老版本评估 “不需整改”,此时就会存在问题漏放风险。同时,调用点在问题排查时信息量有限、每每须要花费必定的精力去搜索/分析,不利于问题的定位与解决。

改进与收益

为了解决 CI 中间产物检测没法覆盖源码相关检测、检出问题定位成本高等问题,咱们又实现了一套 CI 增量源码检测。大致思路是基于 git diff 获取每一个 MR 对应的全部新增源码(包含一二方组件),而后再对这些增量源码进行各项安全检查与合码管控,即 CI 增量源码检测。

CI 增量源码检测

获取一次 MR 过程当中增量源码的主要步骤包含如下 3个子流程:获取源码变动信息子流程、源码 diff 子流程、精准获取组件增量源码子流程。下面结合流程图分别对 3 个关键子流程作详细说明:

1. 获取源码变动信息子流程

源码变动信息包含 主仓/子仓的源码仓库及commit信息、变动组件所在的源码仓库及commit信息。

以 Android 工程为例,

首先,研发人员提交 MR 时触发检查,可直接得到 主仓/子仓的源码变动信息(仓库地址、base commit、review commit);

而后,根据主仓的源码变动信息、分别下载主仓两个 commit 的工程源码;

接着,经过 gradle 命令(iOS 经过 pod 命令)分别获取主仓两次 commit 的组件依赖树信息,解析组件依赖树并对其进行 diff(差分)、便可获得两次提交之间的组件变动信息(新增组件和更新组件);

最后,经过组件管理模块,根据组件变动信息中的 maven坐标 和 版本号,能够获取组件的原始 git 仓库以及两个版本号各自对应的 commit 信息,即变动组件所在的源码仓库和 commit 信息。

组件变动存在新增组件、更新组件和删除组件等操做,增量源码只需关注新增组件和更新组件。

组件管理模块负责组件的发布、升级,会记录组件的原始 git 仓库、版本号与 commit 的对应关系。其没有记录的组件为三方组件,三方组件无源码、不需考虑。

2. 源码 diff 子流程(关键)

基于已经得到的源码变动信息,源码 diff 子流程以下图所示:

  • 主仓/子仓及更新组件主要步骤

首先,下载 MR 准备合入主分支的 commit(即图示中的 review commit)对应工程的源码;

而后,经过 git diff 命令获取 base commit 和 review commit 之间的代码变动信息;

接着,遍历代码变动信息(对更新组件还需过滤组件目录下的代码变动信息)、获取存在新增源码或更新源码的文件及变动的行号信息(diffs 结果中以 "+" 开头的变动行),将全部的源码变动文件及其变动行号信息记录下来压缩进 zip 包(即增量源码包);

最后,将增量源码包上传到服务器、供下游的各类检测服务使用。

  • 新增组件

新增组件与更新组件的区别在于新增组件须要对组件包含的源码进行全量获取,组件源码文件中的每一行都须要进行检查,其余步骤与更新组件彻底一致。

3. 精准获取组件增量源码子流程

一个库工程(git 工程)中可能存在大量的组件(甚至混合 Android、iOS组件),咱们获取到变动组件所在源码仓库的代码变动可能包含其余组件的内容,为避免误报、须要获取组件在其源码仓库中的精准路径

以 Android 工程为例,

首先,经过组件管理模块获取组件所在源码仓库中的模块名称、将 gradle 自定义 task 注入组件源码仓库;

而后,执行 gradle 自定义 task 获取源码仓库中全部组件的模块名称与对应的源码路径;

接着,匹配变动组件的模块名称、获取变动组件的源码路径;

最后,在源码 diff 子流程遍历代码变动信息时经过组件路径过滤出变动组件的增量源码信息,将变动组件的增量源码打入增量源码包,实现组件增量源码的精准获取。

4. 完整流程

收益

1. 覆盖了 Android/iOS 双端的源码检测

原先基于编译中间产物的检测仅能支持 Android 工程,对于 iOS 还须要额外实现一套检测方案。而 CI 增量源码检测不只覆盖了 Android/iOS 双端主/子仓的源码检测需求,并且还覆盖了该次编译所涉及的全部新增/变动一二方组件的增量源码检测,知足了 License 合规检测以及开源项目的安全合规检测需求。

2. 实现了检出问题的自动精准定位与问题聚合

基于源码,咱们实现了将检出的问题与其对应的代码仓库、组件目录、源码文件、问题所在行数进行自动精准关联,同时还能够按照仓库/组件等维度将问题自动进行聚合、分发给不一样的 Owner 跟进处理,大大提升了问题的消费效率、下降了问题的定位解决成本。

CD 产物检测

Android 产物检测

因为在 scanner 扫描过程当中存在大量 IO 操做(反编译生成 smali 文件、逐个扫描 smali),尽管采用了并发等手段,其扫描时间依然较长(屡次扫描同一个 86M 的包平均耗时 175.28s)。

  • smali 扫描流程

在 smali 扫描过程当中有两个特别耗时的环节,一个是扫描 dex/apk 生成 smali 文件、另外一个是批量扫描生成的 smali 文件进行安全合规检查。

思考:若是前一个环节咱们能直接在内存中完成敏感信息的安全合规检查、同时不生成 smali 文件,扫描耗时是否可能大幅下降呢?

  • dex 扫描流程

在咱们的实验过程当中直接基于 Dex 提取 method callgraph,使用一样的规则、屡次扫描一样的包(86M),平均扫描时间由原先的 175.28s 进一步下降到 32.72s,大大提高了包检测扫描的效率。

BDAnalysis引擎

针对前面提到的 “基于敏感调用点潜藏的漏放风险”,假设咱们可以知道函数调用关系,就能从调用点关联到上层业务代码,从点到链扩展检测维度,根本上解决间接调用检测遗漏的问题。

  • 调用链

顾名思义,从调用点到 "main" 之间的链路。

对于 Android 应用而言,通常没有 main 入口,须要根据Android特性,去模拟一个假的 main 入口,通常叫 DummyMain: 四大组件和 Application 生命周期函数;xml 绑定的函数,好比 onclick、databinding 等。

  • 调用链的优势

    • 关联上层业务代码、助力问题的快速定位与解决;

    • 基于 CallGraph 覆盖全部调用场景,助力 SDK依赖梳理、API 调用梳理。

收益

1. 基于 BDAnalysis 实现了调用链的生成

调用链的生成对于敏感问题的排查意义重大,业务方能够根据生成的调用链按图索骥、找到问题实际的调用链路,避免了间接调用形成的漏放风险。

2. 调用链技术被应用于 API 调用与 SDK 依赖梳理等场景

在咱们生成调用链、助力问题的快速定位解决、实现了 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 增量源码检测、发挥其精准溯源优点;CI 中间产物检测辅助校验检测结果、避免 issue 漏放。

  • 指标建设。在现有技术指标的基础上、完善效果指标,建设 issue “检出率”、“消费率”、“误报率”、“满意度”等指标。

  • 数据打通。打通 CI/CD 调用链,升级 issueID打通方案。

CD 业务安全检测

  • 工具定位。检测工具逐步废弃 Scanner 工具,建设功能强大的新检测工具 BDInspect.

  • 指标建设。针对新老检测工具与 BDAnalysis 引擎建设相应的技术指标及自动告警机制。

  • 引擎建设。建设 BDAnalysis 引擎,实现调用链与赋值链落地到更多业务场景。

关于字节终端技术团队

字节跳动终端技术团队(Client Infrastructure)是大前端基础技术的全球化研发团队(分别在北京、上海、杭州、深圳、广州、新加坡和美国山景城设有研发团队),负责整个字节跳动的大前端基础设施建设,提高公司全产品线的性能、稳定性和工程效率;支持的产品包括但不限于抖音、今日头条、西瓜视频、飞书、瓜瓜龙等,在移动端、Web、Desktop等各终端都有深刻研究。

就是如今!客户端/前端/服务端/端智能算法/测试开发 面向全球范围招聘!一块儿来用技术改变世界,感兴趣能够联系邮箱 chenxuwei.cxw@bytedance.com,邮件主题 简历-姓名-求职意向-指望城市-电话

相关文章
相关标签/搜索