Presentation is loading. Please wait.

Presentation is loading. Please wait.

The Application Sandbox in Android

Similar presentations


Presentation on theme: "The Application Sandbox in Android"— Presentation transcript:

1 The Application Sandbox in Android
杨立颖 Apr. 20st 2013

2 Android平台安全体系结构 Android 重新定位(re-purpose)了传统OS保护用户数据、保护系统资源(包括网络)、提供应用程序隔离的安全控制机制 Android提供了关键的安全特性 通过Linux内核实现OS级别上的安全健壮性 强制所有应用程序应用Sandbox机制 安全的进程间通信机制(Binder) 应用程序签名 应用程序定义和用户授予permission的细粒度机制

3 Android Platform Security Architecture
Android软件栈(software stack)中,每层都保证自身的安全性上层调用下层时会信任下层的安全性 Android Os代码作为根用户运行,所有Linux Kernel层以上代码(包括操作系统库,应用程序框架)全被限制在Sandbox中运行

4 System and Kernel Level Security
在OS级别,Android平台提供了安全Linux内核,以及确保不同进程间IPC的安全性,这种安全性确保即使是native code也被限制在sandbox中进行,即进程除非主动提供服务被其他进程通过IPC来访问,否则,该IPC也不能提供访问权限 系统能够阻止恶意程序或程序漏洞伤害其他程序、Android系统或设备本身

5 The Kernel-level Application Sandbox
Android平台利用Linux基于用户身份的鉴定来保护应用程序的资源 内核级的Sandbox机制:Android系统分配一个唯一的用户ID(UID)给每个Android应用程序,该用户运行在一个单独的进程中,这种做法不同于传统Linux OS在多个应用程序使用相同的用户权限 默认情况下,应用程序不能相互访问,应用程序都有限制地访问操作系统

6 Android和Linux中的UID含义
Linux中的UID:即User Identifier,UID就是用户的ID,表明是哪个用户运行了这个程序,主要用于权限的管理。Linux为每个用户分配唯一的UID Android中的UID:Android为单用户系统,这时UID 便被赋予了新的使命---用来识别应用程序的身份,Android为每个应用几乎都分配了不同的UID,而不同UID的Application默认是没有权限访问其他UID资源(拒绝被访问的)

7 其他系统和内核级的安全性 System Partition and Safe Mode Filesystem Permissions
Filesystem Encryption Password Protection Device Administration Memory Management Security Enhancements Rooting of Devices

8 IPC安全机制---Binder Binder:是一个基于OpenBinder实现的轻量级的具有高性能的基于远程调用的进程内和跨进程通信机制。以Linux驱动程序的形式实现 进程间同步 支持多线程通信

9 RPC-Binder

10 Binder与传统IPC Android为每个安装好的应用程序分配了自己的UID,故进程的UID是鉴别进程身份的重要标志
通过调用Binder.getCallingPid()/ Binder.getCallingUid()函数可得到与自己通信的调用者的UID/PID Android Binder基于Client-Server通信模式,传输过程只需一次拷贝,为进程添加UID/PID身份,既支持实名Binder也支持匿名Binder,传输性能稳和安全性高 传统IPC的接收方无法获得对方进程可靠的UID/PID(用户ID/进程ID),从而无法鉴别对方身份 传统IPC没有任何安全措施,完全依赖上层协议来确保 使用传统IPC只能由用户在数据包里填入UID/PID,但这样不可靠,容易被恶意程序利用 传统IPC访问接入点是开放的,无法建立私有通道 命名管道的名称、System V的键值、Socket的IP地址或文件名都是开放的,只要知道这些接入点的程序都可以和对端建立连接,无法阻止恶意程序通过猜测接收方地址获得连接

11 Java Framework IPC机制 Services:提供能够使用Binder功能的接口 Intents:是一个简单的消息传输对象
ContentProviders:一个ContentProvider是一个数据仓库,提供访问设备上的数据 一个应用程序可以通过访问其他的应用程序暴露的ContentProvider,也可以定义自己的ContentProvider来暴露自己的数据 虽然有其他IPC机制,比如网络套接字,推荐使用Android IPC框架,避免引入安全漏洞

12 Android Application Security
Android是一个权限分离的系统,是通过利用Linux内核中的权限管理机制,即为每个Application分配不同的uid和gid,使得不同的Application之间的私有数据和访问,通过Sandbox机制来达到隔离的目的 Android在Linux基础上进行扩展,提供 Application signing机制 Permission机制 per-uri permission机制

13 Android Application signing
应用程序签名确定应用程序的创建者 应用程序签名是将一个应用程序限制在Sandbox运行的第一步,从而确定该应用程序的用户ID(UID),不同的应用程序以不同的用户ID(UID)身份运行 应用程序签名可以确保一个应用程序不能访问其他应用程序(默认) 当一个应用程序(APK文件)被安装到一台Android设备中,包管理器验证包含在APK文件里的签名文件,允许开发者对两个或多个应用程序签名相同并在AndroidManifest中声明相同的SharedUserID来共享Sandbox 包名相同,签名相同,新的APK会替换旧的同包名APK 包名相同,签名不同,新的APK安装失败 包名不同,UID不同,process未指定,各个APK在不同的进程;process指定了包名,也不会和另一个用户的同名包共享进程 包名不同,UID相同,签名相同,process未指定,各个APK在不同的进程。process指定,则可以共享进程;签名不同,则APK安装失败

14 Android源码中四种签名文件 build/target/product/security目录中有四组默认签名供Android.mk在编译APK使用: testkey:普通APK,默认情况下使用 platform:该APK完成一些系统的核心功能。这种方式编译出来的APK所在进程的UID为system shared:该APK需要和home/contacts进程共享数据 media:该APK是media/download系统中的一环 应用程序的Android.mk中有一个LOCAL_CERTIFICATE字段,由它指定用哪个key签名,未指定的默认用testkey

15 SharedUserID与UserID 通过SharedUserID拥有同一个UserID的多个APK可以配置成运行在同一个进程中,可以互相访问任意数据;也可以配置成运行成不同的进程,可以访问其他APK的数据目录下的数据库和文件,就像访问本程序的数据一样 对于一个APK,要使用某个共享UID,必须做三步: 在Manifest节点中增加android:sharedUserId属性 在Android.mk中增加LOCAL_CERTIFICATE的定义 把APK的源码放到packages/apps/目录下,用mm进行编译 应用程序创建的任何文件都会被赋予应用的用户标识,并且正常情况下不能被其他包访问。当通过 getSharedPreferences(String,int) openFileOutput(String,int) openOrCreate Database(String,int,SQLiteDatabase.CursorFactory)创建一个新文件时,开发者可以同时或分别使用MODE_WORLD_READABLE和MODE_WORLD_RITEABLE标志允许其他包读/写此文件。当设置了这些标志后,这个文件仍然属于自己的应用程序,但它的全局读/写和读/写权限已被设置,故其他任何应用程序可以访问

16 ShaerdUserID使用例子 Android系统源码中
所有使用android.uid.system作为共享UID的APK,都会首先在manifest节点中增加android:sharedUserId="android.uid.system",然后在Android.mk中增加LOCAL_CERTIFICATE := platform。可参见Settings等 所有使用android.uid.shared作为共享UID的APK,都会在manifest节点中增加android:sharedUserId="android.uid.shared",然后在Android.mk中增加LOCAL_CERTIFICATE := shared。可参见Launcher等 所有使用android.media作为共享UID的APK,都会在manifest节点中增加android:sharedUserId="android.media",然后在Android.mk中增加LOCAL_CERTIFICATE := media。可参见Gallery等

17 多级别的安全机制 Application级别,通过user ID和group Id实现安全控制(UID和GID的指派可参考Zygote进程的启动流程) Component级别,通过permission来限制对于某一组件的访问 data级别,通过基于permission的per URI进行安全控制

18 Application Sandbox机制
UID =A Application A'Process capabilities Sandbox UID=B capabilities permission Application B'Process dataA per-URI permission dataB permission机制,它主要是用来对Application可以执行的某些具体操作进行权限细分和访问控制 per-URI permission机制,用来提供对某些特定的数据块进行ad-hoc(点对点)方式访问

19 Manifest-permission

20 Manifest.permission 一个权限的定义主要包含三个方面的信息:
权限的名称 所属的权限组(permissionGroup),一个权限组是指把权限按照功能分成的不同的集合。每一个权限组包含若干具体权限,例如在 COST_MONEY 组中包含 android.permission.SEND_SMS , android.permission.CALL_PHONE 等和收费相关的权限 保护级别(protectionLevel),不同的保护级别代表了程序要使用此权限时的认证方式: normal权限,normal 的权限只要申请了就可以使用 dangerous权限,dangerous 的权限在安装时需要用户确认才可以使用 signature ,signature的权限需要使用者的APP和声明该权限的APP使用同一个数字证书 signatureorsystem ,signatureorsystem的权限需要使用者的App和系统使用同一个数字证书 Package的权限信息主要通过在AndroidManifest.xml中通过一些标签来指定。如 <permission> 标签、<permission-group>标签、<permission-tree>标签等。如果 package需要申请使用某个权限,那么需要使用<use-permission>标签来指定

21 Android permission核查机制
系统与权限检查相关的机制的实现主要集中在PackageManagerService和ActivityManagerService中 ActivityManagerService主要负责对uid的身份检查,UID是0,SYSTEM_UID,同一个进程中的调用者则返回PERMISSION_GRANTED PackageManagerService维护了uid到自己拥有的和被授予的权限的一张表。在通过ActivityManagerService的身份检查后, PackageManagerService继续根据被核查的uid来查看这张表,判断其是否具有相应的权限 除此之外,per-URI permission机制的实现也需要一张表,它维护在ActivityManagerService中,它建立了从content URI到被授权访问这个URI的component之间的映射。但是它也需要借助PackageManagerService的机制来辅助实现

22 component-permission(1)
在AndroidManifest.xml文件中,在所需要的component上添加一个android:permission属性,声明需要控制的权限 Activity permissions声明在<activity>标签中。这个权限会在 Context.startActivity()和Activity.startActivityForResult()时被检查调用者是否拥有所声明的该权限。如果调用者没有这个权限,则在调用时抛出SecurityException Service permissions声明在<service>标签中。这个权限会在 Context.startService()、Context.stopService()和Context.bindService()时被检查调用者是否拥有所声明的该权限。如果调用者没有权限,则在调用时抛出 SecurityException

23 component-permission(2)
BroadcastReceiver permissions声明在<receiver>标签中。只有拥有该权限的broadcasts才可以发送给该receiver 当Context.sendBroadcast()返回时会检查这个权限,如果调用者没有这个权限,则不会发送intent给该receiver,但不会抛出SecurityException Context.registerReceiver()也可以有自己permission用于限制谁才可以向一个在程序中注册的receiver发送广播 另一种方式是,一个permission也可以提供给Context.sendBroadcast() 用以限制哪一个BroadcastReceiver才可以接收该广播

24 component-permission(3)
ContentProvider permissions声明在<provider>标签中,用于限制谁才可以访问ContentProvider提供的数据。两个属性可以用来设置权限: android:readPermission,用于限制谁可以读取provider中的数据 android:writePermission,用于限制谁才可以向provider中写入数据 一个provider拥有了读写两个权限,拥有写的权限并不能保证可以读取provider。当你第一次获取provider的时候,并且这时你对provider执行了某些操作就要进行权限检查,如果你没有任何permission,则会抛出SecurityException 使用ContentResolver.query()需要持有读权限;使用ContentResolver.insert(), ContentResolver.update(), ContentResolver.delete()需要持有写权限。在所有这些情况下,没有权限执行操作都会抛出SecurityException

25 Permissions when Sending Broadcasts
除了之前BroadcastReceiver可以声明权限来限制谁才能够给自己发送广播外,还可以在发送广播Context.sendBroadcast()的时候声明一个权限字符串,只有BroadcastReceiver所在的宿主程序中声明该权限才能够收到 接收器和广播都可以声明权限,这两种permission检查需要全部通过后才会将相应的intent发送给相关的接受者

26 Framework提供permission检查接口
如果package接受到外来访问者的操作请求,那么可以调用Android提供的接口进行permission检查: Context.checkPermission(String, int, int):如果你有另一个进程的pid,可以对该pid进程检查是否拥有相应权限 Context.checkCallingPermission()方法:内部调用checkPermission(permission,Binder.getCallingPid(),UserId.getAppId(Binder.getCallingUid())) PackageManager.checkPermission(String, String):如果你有另一个应用程序的包名,可以对该包名对应进程进行检查,来确定该包是否已经拥有了相应的权限

27 URI Permissions(1) 一个content provider可能想保护它的读写权限,而同时与它对应的直属客户端也需要将特定的URI传递给其它应用程序,以便其它应用程序对该URI进行操作。一个典型的例子就是: 邮件程序处理带有附件的邮件。进入邮件需要使用permission来保护,因为这些是敏感的用户数据。然而,如果有一个指向图片附件的URI需要传递给图片浏览器,那个图片浏览器是不会有访问附件的权利的,因为他不可能拥有所有的邮件的访问权限 标准的permission系统对于content provider来说是不够的

28 URI Permissions(2) 针对这个问题的解决方案是per-URI permission:
当启动一个activity或者给一个activity返回结果的时候,呼叫方可以设置Intent.FLAG_GRANT_READ_URI_PERMISSION和/或Intent.FLAG_GRANT_WRITE_URI_PERMISSION。这会使接收该intent的activity获取到进入该Intent指定的URI的权限,这时并不管接收该intent的activity是否有权限进入该intent对应的content provider 这种机制允许一个通常是以用户交互(如打开一个附件, 从列表中选择一个联系人)为驱动的capability-style模型来获取更细粒化的权限(fine-grained permissions)。这是一种减少不必要权限的重要方式,这种方式主要针对的就是那些和程序的行为直接相关的权限 这些URI permission的获取需要content provider(包含那些URI)的配合。强烈推荐在content provider中提供这种临时权限的能力,通过android:grantUriPermissions 或者<grant-uri-permissions> 标签来声明支持

29 URI Permissions(3) Context.grantUriPermission(String toPackage, Uri uri, int modeFlags),为某个 package 添加访问 content Uri 的读或者写权限 Context.revokeUriPermission(Uri uri, int modeFlags) Context.checkUriPermission(Uri uri, int pid, int uid, int modeFlags),检查某个 pid 和 uid 的 package 是否拥有 uri 的读写权限,返回值表示是否被 granted checkUriPermission的实现主要在ActivityManagerService中,分析如下: 如果uid为0,说明是root用户,那么不控制权限 否则,在ActivityManagerService维护的mGrantedUriPermissions这个表中查找这个uid是否含有这个权限,如果有再检查其请求的是读还是写权限

30 Thank You!


Download ppt "The Application Sandbox in Android"

Similar presentations


Ads by Google