黄玮
AOSP
和设备 OEM
厂商的定制修改AOSP
、GMS
和设备 OEM
厂商本章 Android 平台安全相关内容主要基于 Android 官方安全和隐私小组 2020 年 12 月更新的公开论文
P
来指代物理安全相关风险
physical
access ,可以直接通过肢体接触到目标设备proximal
access ,距离上在设备开启的 WPAN
或 WLAN
有效信号覆盖范围内可以访问到目标设备。
伪基站
技术访问到目标设备也属于此类接触类型NFC
通信虽然传输距离通常很短,但也被归属于此类威胁类型Wi-Fi 嗅探
Wi-Fi 中间人攻击
第四章 网络监听
提到的 SSL/TLS 中间人劫持攻击T.P1
的主要区别
T.P1
依赖于 距离目标设备较近 ,T.N2
可以在目标设备 通信链路中任意一个环节 下手T.P1
只影响 目标设备 ,T.N2
可以影响通信链路上 所有设备iOS
平台对 App
的管控机制:集中验证和封闭分发
JavaScript
攻击载荷
嵌入在多媒体文件中,当存在漏洞的播放器打开该恶意多媒体文件时触发漏洞。此类威胁可能导致本地或远程代码执行漏洞
平衡 用户与应用、平台之间的安全和隐私需求
谁创建、谁有权限使用
Device Owner (DO)
或者 Profile Owner (PO)
来限制用户在设备上安装和使用软件root
设备由于破坏了原有的沙盒隔离机制,因此不被认证为 Androidbooloader
解锁设备和刷入自定义固件的设备也不被认证为 Android验证启动
机制将决定恢复出厂设置会还原设备到哪个“备份”状态defense in depth
- DiD
safe by design
- SD
isolation and containment
exploit mitigation
integrity
patching/updates
enforced consent
user authentication
by-default encryption at rest and in transit
许可
(授权
)的表达方式应 易于 「三方」 无歧义 正确理解并执行
移动网络运营商配置
用户
在分享对话窗口里「选择」目标应用接受当前分享内容来源
应用的 开发者
通过 UI&UE
设计,告知 用户
当前应用内「哪些内容」 允许 被分享出去目标
应用的 开发者
自行决定是否接收、如何处理接收到的分享数据内容访问控制策略和机制
目标
应用只能访问到 来源
应用 显式 分享的数据内容
来源
应用的任何其他数据无法被越权访问到用户
通过在设置对话窗口中的「开关选项」来变更许可MNO
应用的开发者通过编程:查询平台访问控制策略后,借助 UI&UE
提供给用户可以进行许可变更的选项用户
通过 MNO 应用
发起的变更操作是合法、无违规的
平台
会使用 统一 的 系统原生 运行时权限 提示对话框 来将最终授权操作交给 用户
平台授权
保障体系确保 正确无误 的给予(开发者开发的)应用授权
Android 权限
体系,详见 DiD.1 隔离和抑制
一节的 访问控制
从 Android 11(API 级别 30)开始,在应用安装到设备上后,如果用户在使用过程中多次针对某项特定的权限点按拒绝,那么在当前应用再次请求该权限时,用户将不会看到系统权限对话框。该操作表示用户希望“不再询问”。在之前的版本中,除非用户先前已选中“不再询问”对话框或选项,否则每当应用请求权限时,用户都会看到系统权限对话框
在某些情况下,系统可能会自动拒绝权限,而无需用户执行任何操作(同样,系统也可能会自动授予权限)
如果应用以 Android 11(API 级别 30)或更高版本为目标平台并且数月未使用,系统会通过自动重置用户已授予应用的运行时敏感权限来保护用户数据
Achieving meaningful user consent is by far the most difficult and nuanced challenge in determining meaningful consent
knowledge
biometrics
biometrics
U2D
tiered authentication model
)
Primary
Authentication ,只支持 knowledge
因素Secondary
Authentication,只支持 biometrics
因素Tertiary
AuthenticationD2D
authentication多方许可
和 安全合规
多方许可
和 安全合规
出厂设置能保证恢复设备到安全状态
无需再抹除用户数据,只需删除加密用主密钥即可引入版本 | 改进措施 | 拟解决 的威胁 |
---|---|---|
6.x | 0 代码级别明文通信声明 | [T.N1][T.N2] |
7.x | 网络安全配置项增加 TLS 和明文通信设置选项 | [T.N1][T.N2] |
usesCleartextTraffic
来显式声明应用是否支持明文通信
true
。对于目标 API 级别为 28 或更高级别的应用,默认值为 false
false
,平台组件(例如 HTTP 和 FTP 堆栈、DownloadManager 和 MediaPlayer)将拒绝应用要使用明文流量的请求。但这只是一个 尽力而为
选项,并非所有组件都遵守该字段声明引入版本 | 改进措施 | 拟解决 的威胁 |
---|---|---|
9.0 | 1 DNS-over-TLS | [T.N1][T.N2] |
9.0 | 所有连接默认使用 TLS | [T.N1][T.N2] |
10 | 客户端模式, SoftAP 和 WiFi Direct 模式均默认使用 MAC 地址随机化 | [T.N1] |
10 | 新增 TLS 1.3 支持 |
[T.N1][T.N2] |
Audit-only
:应用权限保护级别为 normal
,属于 安装时权限
Runtime
:应用权限保护级别为 dangerous
,既需要在应用代码的清单文件里声明,也需要在代码里定义如何向用户申请授权许可Special Access
:用户只能通过 系统设置
去变更授权许可,应用代码里无法声明和发起申请Privileged
:只针对 系统预装
应用,通常是 OEM
通过白名单机制指定特定应用享有的系统级别特权。通常配合 签名
级别权限使用
API Level 23
之前版本,在应用清单文件被声明为 <permission android:protectionLevel=signature|privileged>
API Level 23
及之后版本,在应用清单文件被声明为 <permission android:protectionLevel=signatureOrSystem>
Signature
:应用权限保护级别为 signature
,拥有相同签名的(系统或应用)组件才能相互访问/调用,无需告知或征得用户许可即可自动授权
<permission>
<permission-group>
<path-permission>
内容提供者
组件专用的访问控制授权声明<uses-permission>
<uses-permission-sdk-23>
Android 6.0
开始引入的运行时权限申请专用<uses-feature>
Android 6.0
(API Level 23
) :新增 运行时权限
类别,用户授权不再是安装时「一锤子买卖」,实现了「精细化授权」和「按需授权」Android 10.0
(API Level 29
) :新增 上下文权限
,在原有二元化的 允许
与 拒绝
选项基础之上增加了 仅在使用中允许
Android 11
:新增 每次询问权限
Android 10.0
:禁止应用直接读取设备唯一标识(IMEI
)MIUI 12
(基于 Android 10
)的 空白通行证
ColorOS 7
(基于 Android 10
)的 保护个人信息
空信息
吗?仿真信息
是不是比 空信息
更好?引入版本 | 改进措施 | 拟解决 的威胁 |
---|---|---|
≤ 4.3 | 进程隔离0 | [T.A3] 导致的 [T.N1][T.A2][T.A5][T.A6][T.A7] |
5.x | SELinux1 | [T.A7][T.D2] |
5.x | 允许 Webview 组件代码独立更新 | [T.A3] |
UID 沙盒
是历史最悠久、最基础的应用沙盒安全技术,是实现用户进程间隔离的最基础访问控制技术,不足之处已经通过后续版本的 SELinux 规则更新逐步完善加固可审计
和 可测试
,从而可以大幅度增加安全需求兼容性测试项目数量引入版本 | 改进措施 | 拟解决 的威胁 |
---|---|---|
6.x | 允许运行时用户授权 | [T.A1] |
6.x | 基于 SELinux 的多用户支持 | [T.P4] |
6.x | 应用私有目录缺省目录权限变更 0755 -> 0700 | [T.A2] |
6.x | 针对 ioctl 增加 SELinux 规则缓解内核漏洞利用 | [T.A7][T.D2] |
6.x | 移除应用访问 debugfs 权限缓解内核漏洞利用 | [T.A7][T.D2] |
6.x | 特殊权限类别定义范围变更2 | [T.A1][T.A4] |
引入版本 | 改进措施 | 拟解决 的威胁 |
---|---|---|
7.x | 移除 /proc/ |
[T.A4] |
7.x | perf事件加固缓解内核漏洞利用 | [T.A7] |
7.x | /proc 文件系统缺省访问规则改进 | [T.A1][T.A4] |
7.x | OPA/MITM 方式更新加入的证书缺省不被信任 | [T.N2] |
8.x | /sys 文件系统缺省访问规则改进 | [T.A1][T.A4] |
8.x | 所有用户进程使用相同的 seccomp 过滤规则以缓解内核攻击面 | [T.A7][T.D2] |
8.x | 所有用户进程使用的 Webview 组件被移入独立进程 | [T.A3] |
8.x | 应用使用明文网络通信协议需用户知情同意 | [T.N1] |
引入版本 | 改进措施 | 拟解决 的威胁 |
---|---|---|
9.0 | 应用可以单独设置独立的 SELinux 沙盒 | [T.A2][T.A4] |
10 | 原则上只允许应用在可见活动窗口中启动新Activity且加入到前台“后退堆栈” | [T.A2][T.A3][T.A4][T.A7] |
10 | 外部存储上的文件访问仅限于应用拥有的文件 | [T.A1][T.A2] |
10 | 只有当前输入焦点应用或默认输入法应用才能读取剪贴板数据 | [T.A5] |
10 | /proc/net 访问控制进一步严格以缓解侧信道攻击 | [T.A1] |
11 | 不再支持传统模式下的应用访问外部存储上的其他应用文件 | [T.A1][T.A2] |
拟解决 [T.D2] 威胁
引入版本 | 改进措施 | 拟解决 的威胁 |
---|---|---|
4.4 | 强制模式的 SELinux0 被应用于 4 个 root 权限进程 | [T.A1][T.A7][T.D2] |
5.x | 用户态所有进程基于 SELinux 的 MAC |
[T.A1][T.A7] |
6.x | 所有进程基于 SELinux 的 MAC |
[T.A1][T.A7] |
7.x | 架构层面解耦 mediaserver 服务 |
[T.A1][T.A7][T.D2] |
7.x | 系统组件访问 ioctl 系统调用被限制 |
[T.A1][T.A7][T.D2] |
8.x | Treble 架构结构解耦1 |
[T.A1][T.A7][T.D2] |
强制访问控制(MAC, Mandatory Access Control)
规则:installd, netd, vold, zygoteHAL((Hardware Abstraction Layer)
组件被拆分为独立进程,减少授权,限制访问硬件驱动引入版本 | 改进措施 | 拟解决 的威胁 |
---|---|---|
10 | 多媒体软件编解码器被移入到一个受限制沙盒 | [T.A7][T.D2] |
10 | 引入 BoundSan 2 ,预防数组越界访问引起的漏洞 |
[T.A7][T.D2] |
BoundSan
) 将插桩添加到二进制文件,以插入对数组访问的边界检查。如果编译器在 编译时 无法证明访问将会是安全的,并且在运行时将会知道数组的大小,便会添加这些检查,以便对数组访问进行检查。Android 10 在蓝牙和编解码器中部署了 BoundSan
。BoundSan
由编译器提供,在整个平台的各个组件中默认启用。引入版本 | 改进措施 | 拟解决 的威胁 |
---|---|---|
10 | 引入 IntSan 3 |
[T.A7][T.D2] |
10 | 引入 Scudo 4 |
[T.A7][T.D2] |
monolithic kernel
)架构,因此无法实现内核沙盒化引入版本 | 改进措施 | 拟解决 的威胁 |
---|---|---|
5.x | 引入 PXN 0 机制 |
[T.A7][T.D2] |
6.x | 内核线程被设置为SELinux强制执行模式,限制从内核访问用户态文件 | [T.A7][T.D2] |
8.x | 引入 PAN 1 和 PAN 模拟机制 |
[T.A7][T.D2] |
PXN
, Privileged eXecute Never,内核态进程禁止执行用户态代码,预防 ret2usr
形式的漏洞利用技巧PAN
, Privileged Access Never,内核态进程访问用户态内存受到限制,仅允许通过 copy-*-user()
系列函数引入版本 | 改进措施 | 拟解决 的威胁 |
---|---|---|
9.0 | 引入 CFI 2 |
[T.A7][T.D2] |
10 | 引入 SCS 3 |
[T.A7][T.D2] |
CFI
, Control Flow Integrity,基于控制流「白名单」的函数调用限制SCS
, Shadow Call Stack,通过保护返回地址来实现调用堆栈深度回溯保护防篡改硬件(TRH, Tamper Resistant Hardware)
被用来存储重要密钥,属于 TEE 的「纵深防御」补充沙盒防御措施验证启动
(Verified Boot
)
Android Enterprise Recommended program
(设备、运营商服务以及企业移动管理服务的最低规格要求):
90 天安全更新
在设备推出后五年内,一旦有安全更新,就会在 90 天内及时安装
CTS
(Compatibility Test Suite
) 通过设计稳定和一致的 API,解决应用开发者开发应用的多版本、多设备兼容性需求VTS
(Vendor Test Suite
) Android 操作系统框架层面的稳定和一致 API 计划,解耦「设备厂商实现代码」和「Android 操作系统框架代码」HIDL
)、Android VTS
在 HAL
和它的用户之间定义一个清晰的接口
HIDL
的目标是在不重新构建 HAL
的情况下替换操作系统框架HAL
是由半导体供应商进行构建的,并且构建于设备的供应商分区中,这使得操作系统框架被放置于一个自己的分区中,无需重新编译 HAL
就能够通过 OTA
更新进行替换HAL
组件运行在自己独立沙盒且只允许所控制的硬件设备驱动访问,上层应用不允许直接访问设备驱动而是只能访问对应关联的 HAL
组件SELinux
策略不再是出厂时固化在框架代码里,改为系统启动时从不同安全分区(system
和 vendor
)加载动态组装
见课本 第五章 实验
Offline components
(2.7GB+
)Gradle 构建依赖压缩包
,并按照压缩包中的 README
进行配置
Maven
仓库镜像项目
根目录 下的 build.gradle
// google()
// jcenter()
maven {
url 'https://maven.aliyun.com/repository/google/'
}
maven {
url 'https://maven.aliyun.com/repository/jcenter/'
}
动手编写 Hello World 时间
Play 应用签名计划
自行负责保障签名密钥和密钥库的安全
在应用的预期生命周期内,应当使用同一证书为应用签名
Android package
),即带有 .apk
后缀的(zip 格式
)归档文件每个应用都是一个不同的用户
最小化授权
的应用
用户 ID
区分应用彼此属主:相同 用户 ID
的应用可以互相访问,否则被禁止互相访问四大组件
Service
BroadcastReceiver
ContentProvider
Activity
是 Android 应用中负责与用户交互的组件View
是所有UI控件、容器控件的基类
Activity
将它显示出来
setContentView()
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
Activity
地位并列Service
组件需要继承 Service
基类Service
组件被运行起来之后,拥有自己独立的生命周期
BroadcastReceiver
监听的事件源是 Android
应用中的其他组件BroadcastReceiver
子类,重写 onReceive(Context cx, Intent it)
方法即可sendBroadcast()
、sendStickyBroadcast()
或 sendOrderedBroadcast()
方法发送广播消息时,如该 BroadcastReceiver
也对该消息『感兴趣』, onReceive
方法会被自动调用
IntentFilter
实现『感兴趣』Java
代码中使用 Context.registReceiver()
方法注册 BroadcastReceiver
AndroidManifest.xml
中使用 <receiver …/>
元素完成注册BroadcastReceiver
,系统能够在常规用户流之外向应用传递事件,从而允许应用响应系统范围内的广播通知BroadcastReceiver
不会显示界面,但其可以创建状态栏通知Android
应用内不同组件之间通信的载体
Activity
或 Service
组件BroadcastReceiver
Intent
封装了当前组件需要启动或触发的目标组件信息
Intent
:明确指定需要启动或触发的组件类名Intent
:仅指定需要启动或触发的组件应满足的条件
IntentFilter
声明当前应用能处理哪些隐式 Intent
Intent intent = new Intent(this, DisplayMessageActivity.class);
EditText editText = (EditText) findViewById(R.id.edit_message);
String message = editText.getText().toString();
intent.putExtra(EXTRA_MSG, message);
// Save Data
editor.putString(getString(R.string.pref_usr_input_msg), message);
editor.commit();
startActivity(intent);
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Android OS
限制每个应用运行在自己独立的虚拟机实例中
ContentProvider
ContentProvider
需要实现以下抽象方法
insert
、delete
、update
和 query
URI
应用A
通过 ContentProvider
暴露自己的数据访问接口,应用B
通过 ContentResolver
来访问数据IntentFilter
声明