Android安全机制.docx

上传人:b****8 文档编号:10647048 上传时间:2023-02-22 格式:DOCX 页数:14 大小:22.17KB
下载 相关 举报
Android安全机制.docx_第1页
第1页 / 共14页
Android安全机制.docx_第2页
第2页 / 共14页
Android安全机制.docx_第3页
第3页 / 共14页
Android安全机制.docx_第4页
第4页 / 共14页
Android安全机制.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

Android安全机制.docx

《Android安全机制.docx》由会员分享,可在线阅读,更多相关《Android安全机制.docx(14页珍藏版)》请在冰豆网上搜索。

Android安全机制.docx

Android安全机制

1Android安全机制概述

Android是一个权限分离的系统。

这是利用Linux已有的权限管理机制,通过为每一个Application分配不同的uid和gid,从而使得不同的Application之间的私有数据和访问(native以及java层通过这种sandbox机制,都可以)达到隔离的目的。

与此同时,Android还在此基础上进行扩展,提供了permission机制,它主要是用来对Application可以执行的某些具体操作进行权限细分和访问控制,同时提供了per-URIpermission机制,用来提供对某些特定的数据块进行ad-hoc方式的访问。

1.1uid、gid、gids

Android的权限分离的基础是建立在Linux已有的uid、gid、gids基础上的。

UID。

Android在安装一个应用程序,就会为它分配一个uid(参考PackageManagerService中的newUserLP实现)。

其中普通Android应用程序的uid是从10000开始分配(参见Process.FIRST_APPLICATION_UID),10000以下是系统进程的uid。

GID。

对于普通应用程序来说,gid等于uid。

由于每个应用程序的uid和gid都不相同,因此不管是native层还是java层都能够达到保护私有数据的作用。

GIDS。

gids是由框架在Application安装过程中生成,与Application申请的具体权限相关。

如果Application申请的相应的permission被granted,而且中有对应的gids,那么这个Application的gids中将包含这个gids。

uidgidgids的详细设置过程:

请参考ActivityManagerService中的startProcessLocked。

在通过zygote来启动一个process时,直接将uid传给给了gid。

再通过zygote来fork出新的进程(zygote.java中的forkAndSpecialize),最终在native层(dalvik_system_zygote.c)中的forkAndSpecializeCommon中通过linux系统调用来进行gid和uid和gids的设置。

1.2permission

一个权限主要包含三个方面的信息:

权限的名称;属于的权限组;保护级别。

一个权限组是指把权限按照功能分成的不同的集合。

每一个权限组包含若干具体权限,例如在COST_MONEY组中包含android.permission.SEND_SMS,android.permission.CALL_PHONE等和费用相关的权限。

每个权限通过protectionLevel来标识保护级别:

normal,dangerous,signature,signatureorsystem。

不同的保护级别代表了程序要使用此权限时的认证方式。

normal的权限只要申请了就可以使用;dangerous的权限在安装时需要用户确认才可以使用;signature和signatureorsystem的权限需要使用者的app和系统使用同一个数字证书。

Package的权限信息主要通过在AndroidManifest.xml中通过一些标签来指定。

标签,标签等标签。

如果package需要申请使用某个权限,那么需要使用标签来指定。

2Androidpermission管理机制

2.1Frameworkpermission机制

2.1.1安装入口

permission的初始化,是指permission的向系统申请,系统进行检测并授权,并建立相应的数据结构。

绝大多数的情况下permission都是从一个package中扫描所得,而这发生在package安装和升级的时候。

一般有如下几种安装入口:

npackageInstaller,package被下载安装时会触发使用。

packageInstaller会通过AppSecurityPermissions来检查dangerous的权限,并对用户给出提示。

npm命令。

nadbinstall。

最终还是调用pminstall来安装apk包。

n拷贝即安装。

PackageManagerService中使用AppDirObserver对/data/app/进行监视,如果有拷贝即触发安装。

这些安装方式最终都会通过调用PackageManagerService中的函数来完成程序的安装。

2.1.2permission创建

第一步,从AndroidManifest.xml中提取permission信息。

主要提取如下信息:

²shareduid

指定与其它package共享同一个uid。

²permission

提取permissions标签指定属性。

它使用permissionInfo来描述一个权限的基本信息。

需要指定protectedLevel信息,并指定所属group信息。

它将被添加到这个package的permissions这个list结构中。

²permission-tree

提取permissions-tree标签属性。

permissions-tree也通过permissionInfo来描述,并被添加到package的permissions这个list结构中。

permission-tree只是一个名字空间,用来向其中动态添加一些所谓Dynamic的permission,这些permission可以动态修改。

这些permission名称要以permission-tree的名称开头。

它本身不是一种权限,没有protectedLevel和所属group。

只是保存了所属的packge和权限名(带有package前缀的)。

²permission-group

定义permission组信息,用PermissionGroup表示。

本身不代表一个权限,会添加进入package的permissionGroups这个list中。

²uses-permission

定义了package需要申请的权限名。

将权限名添加到package的requestedPermissions这个list中。

²adopt-permissions

将该标签指定的name存入package的mAdoptPermissions这个list中。

Name指定了这个package需要从name指定的package进行权限领养。

在systempackage进行升级时使用。

第二步。

获取Package中的证书,验证,并将签名信息保存在Package结构中。

1.如果该package来自systemimg(系统app),那么只需要从该Package的AndroidManifest.xml中获取签名信息,而无需验证其完整性。

但是如果这个package与其它package共享一个uid,那么这个共享uid对应的sharedUser中保存的签名与之不一致,那么签名验证失败。

2.如果是普通的package,那么需要提取证书和签名信息,并对文件的完成性进行验证。

第三步。

如果是普通的package,那么清除package的mAdoptPermissions字段信息(系统package升级才使用)。

第四步。

如果在AndroidManifest.xml中指定了shareduser,那么先查看全局list中(mSharedUsers)是否该uid对应的SharedUserSetting数据结构,若没有则新分配一个uid,创建SharedUserSetting并保存到全局全局list(mSharedUsers)中。

mUserIds保存了系统中已经分配的uid对应的SharedUserSetting结构。

每次分配时总是从第一个开始轮询,找到第一个空闲的位置i,然后加上FIRST_APPLICATION_UID即可。

第五步。

创建PackageSettings数据结构。

并将PackageSettings与SharedUserSetting进行绑定。

其中PackageSettings保存了SharedUserSetting结构;而SharedUserSetting中会使用PackageSettings中的签名信息填充自己内部的签名信息,并将PackageSettings添加到一个队列中,表示PackageSettings为其中的共享者之一。

在创建时,首先会以packageName去全局数据结构mPackages中查询是否已经有对应的PackageSettings数据结构存在。

如果已经存在PackageSettings数据结构(比如这个package已经被uninstall,但是还没有删除数据,此时package结构已经被释放)。

那么比较该package中的签名信息(从AndroidManifest中扫描得到)与PackageSettings中的签名信息是否匹配。

如果不匹配但是为systempackage,那么信任此package,并将package中的签名信息更新到已有的PackageSettings中去,同时如果这个package与其它package共享了uid,而且shareduid中保存的签名信息与当前package不符,那么签名也验证失败。

第六步。

如果mAdoptPermissions字段不为空,那么处理permission的领养(从指定的package对应的PackageSettings中,将权限的拥有者修改为当前package,一般在systemapp升级的时候才发生,在此之前需要验证当被领养的package已经被卸载,即检查package数据结构是否存在)。

第七步。

添加自定义权限。

将package中定义的permissionGroup添加到全局的列表mPermissionGroups中去;将package中定义的permissions添加到全局的列表中去(如果是permission-tree类型,那么添加到mSettings.mPermissionTrees,如果是一般的permission添加到mSettings.mPermissions中)。

第八步。

清除不一致的permission信息。

1.清除不一致的permission-tree信息。

如果该permission-tree的packageSettings字段为空,说明还未对该package进行过解析(若代码执行到此处时packageSettings肯定已经被创建过),将其remove掉。

如果packageSettings不为空,但是对应的package数据结构为空(说明该package已经被卸载,但数据还有保留),或者package数据结构中根本不含有这个permission-tree,那么将这个permission-tree清除。

2.清除不一致的permission信息。

如果packageSettings或者package结构为空(未解析该package或者被卸载,但数据有保留),或者package中根本没有定义该permission,那么将该permission清除。

第九步。

对每一个package进行轮询,并进行permission授权。

1.对申请的权限进行检查,并更新grantedPermissions列表

2.如果其没有设置shareduserid,那么将其gids初始化为mGlobalGids,它从permission.xml中读取。

3.遍历所有申请的权限,进行如下检查

1)如果是该权限是normal或者dangerous的。

通过检查。

2)如果权限需要签名验证。

如果签名验证通过。

还需要进行如下检查

*如果程序升级,而且是systempackage。

那么是否授予该权限要看原来的package是否被授予了该权限。

如果被授予了,那么通过检查,否则不通过。

*如果是新安装的。

那么检查通过。

4.如果3中检查通过,那么将这个permission添加到package的grantedPermissions列表中,表示这个permission申请成功(granted)。

申请成功的同时会将这个申请到的permission的gids添加到这个package的gids中去。

5.将permissionsFixed字段标准为ture,表示这个packge的permission进行过修正。

后续将禁止对非system的app的权限进行再次修正。

2.1.3Dynamicpermission的管理

PackageManagerService提供了addPermission/removePermission接口用来动态添加和删除一些权限。

但是这些权限必须是所谓的动态权限(BasePermission.TYPE_DYNAMIC)。

一个Package如果要添加Dynamicpermissions,首先必须要在manifest中申明标签,它实际上是一个权限的名字空间(例如,“com.foo.far”这个权限就是permission-tree“com.foo”的成员),本身不是一个权限。

一个Package只能为自己的permission-tree或者拥有相同的uid的package添加或者删除权限。

Package不能够通过这种接口去修改在manifest中静态申请的权限,否则抛出异常。

首先查找这个permission在全局permission列表mSettings.mPermissions中是否存在。

如果存在,而且类型为BasePermission.TYPE_DYNAMIC那么根据传入的权限信息修改全局表中的权限信息,并触发permissions.xml的持久化。

如果在全局的permission列表mSettings.mPermissions中没有找到,先找到这个permission所在permissionTree,然后添加到全局permission列表mSettings.mPermissions中去,并触发permissions.xml的持久化。

2.1.4Uripermission的管理

下面两个接口主要用于Uripermission的管理(其实现在ActivityManagerService中)。

//为指定的uid和targetPkg添加对某个contentUri的读或者写权限。

publicvoidgrantUriPermission(IApplicationThreadcaller,StringtargetPkg,Uriuri,intmode)throwsRemoteException;

//清除所有通过grantUriPermission对某个Uri授予的权限。

publicvoidrevokeUriPermission(IApplicationThreadcaller,Uriuri,intmode)throwsRemoteException;

grantUriPermission主要的实现过程分析。

grantUriPermission分析:

1.验证caller的ProcessRecord和targetPkg不为空。

否则检测不通过。

2.验证所请求的mode为Intent.FLAG_GRANT_READ_URI_PERMISSION或者为Intent.FLAG_GRANT_WRITE_URI_PERMISSION,否则不通过。

3.确保参数Uri是一个contentUri。

否则,则检测不通过。

4.通过Uri得到目标ContentProvider,如果不存在,则检测不通过。

5.从PackageManagerService中获得targetPkg对应的uid。

6.检查targetuid所对应的package是否真正需要这个权限?

先判断要申请的是读还是写权限,然后查看对应的ContentProvider中对应的readPermissionwritePermission字段是否保存了权限名称。

如果该字段不为空,则以targetuid和该权限名去PackageManagerService中去查找该uid是否被granted了该权限。

如果已经获得了该权限,那么无需再去为这个Activity去申请这个Uri权限了,返回。

否者继续执行如下操作。

7.检查这个ContentProvider的grantUriPermissions开关变量,是否允许对其它package进行权限的grant操作。

如果禁止,那么抛出异常。

8.检查这个ContentProvider是否设置了Uri的过滤类型uriPermissionPatterns,如果设置了过滤类型,则将需要申请权限的Uri与之匹配。

匹配不同过,则抛出异常。

9.检查调用者自己是否有权限访问这个Uri。

如果没有,抛出异常。

10.从mGrantedUriPermissions中取得targetuid对应的HashMap数据结构。

用targetuid和Uri生成UriPermission并保存在mGrantedUriPermissions中。

revokeUriPermission实现分析。

找到该Uri对应的ContentProvider,然后删除mGrantedUriPermissions中与Uri对应的所有权限。

2.2permission的动态检查

这里的动态检查是指是package在程序运行过程中进行某些操作或者数据访问时才进行的check,与之对应的是应用程序安装或者升级时PackageManagerService通过扫描包中的静态权限信息相对应。

系统与权限检查相关的机制的实现主要集中在PackageManagerService和ActivityManagerService中。

ActivityManagerService主要负责的是底层的uid层次的身份检查;PackageManagerService则维护了uid到自己拥有的和被授予的权限的一张表。

在通过ActivityManagerService的身份检查后,PackageManagerService根据请求者的uid来查看这张表,判断其是否具有相应的权限。

除此之外,per-URIpermission机制的实现也需要一张表,它维护在ActivityManagerService中,它建立了从contentURI到被授权访问这个URI的component之间的映射。

但是它也需要借助PackageManagerService的机制来辅助实现。

2.2.1framework提供的接口

Androidframework中提供了一些接口用来对外来的访问(包括自己)进行权限检查。

这些接口主要通过ContextWrapper提供,具体实现在ContextImpl中。

如果package接受到外来访问者的操作请求,那么可以调用这些接口进行权限检查。

一般情况下可以把这些接口的检查接口分为两种,一种是返回错误,另一种是抛出异常。

主要包含如下几组:

npermission和uid检查API

下面这一组接口主要用来检查某个调用(或者是其它package或者是自己)是否拥有访问某个permission的权限。

参数中pid和uid可以指定,如果没有指定,那么framework会通过Binder来获取调用者的uid和pid信息,加以填充。

返回值为PackageManager.PERMISSION_GRANTED或者PackageManager.PERMISSION_DENIED。

publicintcheckPermission(Stringpermission,intpid,intuid)//检查某个uid和pid是否有permission权限

publicintcheckCallingPermission(Stringpermission)//检查调用者是否有permission权限,如果调用者是自己那么返回PackageManager.PERMISSION_DENIED

publicintcheckCallingOrSelfPermission(Stringpermission)//检查自己或者其它调用者是否有permission权限

下面这一组和上面类似,如果遇到检查不通过时,会抛出异常,打印消息。

publicvoidenforcePermission(Stringpermission,intpid,intuid,Stringmessage)

publicvoidenforceCallingPermission(Stringpermission,Stringmessage)

publicvoidenforceCallingOrSelfPermission(Stringpermission,Stringmessage)

nper-URI检查API

为某个package添加访问contentUri的读或者写权限。

publicvoidgrantUriPermission(StringtoPackage,Uriuri,intmodeFlags)

publicvoidrevokeUriPermission(Uriuri,intmodeFlags)

检查某个pid和uid的p

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 简历

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1