android study 8
安卓安全机制
1.权限与隔离
1.1 linux中的用户(uid),组(gid),进程(pid)
在linux中,用户分为三种,普通用户,root用户,系统用户。每个uid会对应一个用户。普通用户一般只能在home目录,临时目录,以及其他授权目录下操作,以及只能操作属于该用户的文件。一般普通用户的uid大于500。root用户的id是0,是linux中的超级用户可以修改删除任意文件。系统用户是指系统运行时必须有的用户,比如运行网站服务,就需要系统用户apache来运行httpd进程,同理需要mysql用户运行mysqld进程。系统用户编号通常是1-499。
组id则是用户id的归属,每个用户至少属于一个组。
1.2 linux进程的用户管理
每个进程拥有Real user ID即真实的用户,组(uid,gid)。Effective user ID即有效用户,有效组(euid,egid)。Saved set-user-ID保存的设置用户、组(suid、sgid)
1.真实用户/组好理解,就是进程的拥有者。
2.有效用户/有效组是什么作用呢: 方便资源访问,进程的权限实际上来自于有效用户的权限,比如su程序的权限,su 程序的所有者是 root,并且它被设置了 set-user-id 标志。这个标志意味着任何普通用户运行su程序时,有效用户就是该程序的所有者。根据有效用户的含义,任何运行 su 程序的普通用户都能访问 /etc/passwd 文件。有效用户为 root 进程称为特权进程(privileged processes)。EGID 的含义与 EUID 类似:给运行目标程序的组用户提供有效组的权限。
内核利用这些 ID 决定进程对共享资源拥有怎样的访问权,比如:消息队列、共享内存和信号量。尽管大多数的 UNIX 系统使用这些 ID 决定文件的访问权,但 Linux 使用的是独有的 filesystem ID。
3.Saved set-user-ID:这两个 ID 在 set-user-ID 与 set-group-ID 程序执行后,保存相应的 effective ID。因此,一个 set-user-ID 程序的 effective user ID 可以在 real user ID 与 saved set-user-ID 之间来回切换,从而可以恢复 / 抛弃特权。
- Filesystem user ID / Filesystem group ID:这些 ID 用于决定进程对文件与其他共享资源的访问权。进程无论何时更改 effective user/group ID,内核也同时更改 filesystem user/group ID。
1.3 android系统中的uid,gid,gids与pid
在android上,一个用户uid标志着一个应用程序,应用程序在安装时被分配uid。对于普通应用程序,gid和uid相同。gids: 个GIDS相当于一个权限的集合,一个UID可以关联GIDS,表明该UID拥有多种权限。gids在应用安装时生成。
一个进程就是host应用程序的沙箱,里面一般有一个UID和多个GIDS,每个进程只能访问UID的权限范围内的文件和GIDs所允许访问的接口,构成了Android最基本的安全基础。
Android 使用沙箱的概念来实现应用程序之间的分离和权限,以允许或拒绝一个应用程序访问设备的资源,比如说文件和目录、网络、传感器和 API。为此,Android 使用一些 Linux 实用工具,来实现应用程序被允许执行的操作。
2. Android Permission权限控制机制
2.1 权限基本信息
一个权限主要包含三个方面的信息: 权限的名称、属于的权限组、保护级别。一个权限组是指把权限按照功能分成不同的集合,每个权限组包含N个具体权限。例如CONTACTS组中,包含WRITE_CONTACTS,GET_ACCOUNTS,READ_CONTACTS等和联系人相关的权限。可以通过pm list 命令去获取相应的permission信息。也可以通过查看/data/sytem/packages.xml文件来获取。
2.2 权限等级
android权限分为normal,dangerous,signature,signatureOrSystem,system,development等,不同级别对应了不同的验证方式。normal只要申请了即可,dangerous的权限需要在安装时用户确认,signature则需要签名才赋予权限,signatureOrSystem需要签名或者系统级应用(放置在/system/app目录下)才能赋予权限,system系统级应用(放置在/system/app目录下)才能赋予权限,系统权限的描述在frameworks/base/core/res/AndroidManifest.xml当中。
android 6.0(api level 23)之后进行了一次权限大升级,其中出现了一个新的protectionLevel叫做”signature|privileged”,signatureOrSystem变成了deprecated。在这之后,系统分成了system app和priviledged app,其中/system/app目录下的应用只有system权限,而/system/priv-app/目录下的应用才有privileged app 权限。而”signature|privileged”的权限等同于android6.0之前的signatureOrSystem。大于等于此时的system权限。
Package 的权限信息主要 通过在 AndroidManifest.xml 中通过一些标签来指定。如
2.4 android提供的permission接口
android提供了一组api供app检查某个调用,主要用来检查某个调用(或者是其它 package 或者是自己)是否拥有访问某个 permission 的权限。参数中 pid 和 uid 可以指定,如果没有指定,那么 framework 会通过 Binder 来获取调用者的 uid 和 pid 信息,加以填充。返回值为 PackageManager.PERMISSION_GRANTED 或者 PackageManager.PERMISSION_DENIED
checkPermission判断流程:
1) 如果 uid 为 0 ,说明是 root 权限的进程,对权限不作控制。
2) 如果 uid 为 system server 进程的 uid ,说明是 system server ,对权限不作控制。
3) 如果是ActivityManager,对权限不做控制
4) 首先通过调用 getUserIdLP,根据uid去获取权限列表,判断是否有相应权限
5) 如果没找到,则会去PackageManagerService.mSystemPermissions 中找。这些信息是启动时,从 /system/etc/permissions/platform.xml 中读取的。这里记录了一些系统级的应用(如日历,浏览器,短信等)的 uid 对应的 permission 。
references
https://vvl.me/2018/09/linux-credentials/