签名和权限的作用
Android签名
中使用到的一些加密技术有:
公/私钥, SHA1(CERT.SF,MANIFEST.MF), RSA(CERT.RSA), 消息摘要,
移动平台中的主流签名作用:
- Android平台中是使用自签名
自签名,证书的签名者和证书拥有者
是同一人.
自签名的完整性认证
自签名是没有信任模式的
,因为自签名信息是自己的,对无法知道该信息是不是安全,我们只能对其的完整性进行认证.
限制安装和运行
下面是限制应用安装和运行的流程
-
应用安装时
校验是否含签名 –> 没有,禁止安装
–> 有,提取证书进行校验–> 证书是否有效可信任–> 不是禁止安装.基于证书的公钥对签名进行校验–> 签名是否正确 –> 不正确禁止安装.
-
应用运行时
校验是否包含签名 –> 没有,禁止运行
–> 有,提取证书进行校验–> 证书是否有效可信任–> 不是禁止运行.(这一步跟安装流程相似)基于证书的公钥对签名进行校验–> 签名是否正确 –> 不正确禁止运行.(这一步跟安装流程相似)
权限的作用(细粒度的特权管理)
- 权限是一个ID或者一个字符串
- 谦虚用来细分权利(类似Capability,分散权利)
- 通常一个权限与一个类操作绑定
- 权限首先需要申请(AndroidManifest或者代码动态申请)
- 但是申请后是否被批准有平台策略决定
如:用户需要读取SDCard的权限,这时Android平台会弹出访问SDCard的窗口,如果用户accept了,那这个权限就被申请.
权限的安全性保护(通过签名)
权限的完整性保护(防篡改)
如发短信的方式,不可能没发一条短信都弹dialog来申请权限,所以这时开发只要在Manifest 中添加sendSMS permission
就可以.(通过认证并获得签名后再加policy权限)权限的授权安全策略(防Escalate)
如普通应用申请Inject Event 权限(注入)
签名作用
完整性鉴别
自签名支持完整性鉴别
Android中使用的是自签名方式
,那就是无法对签名的信任进行认证,只能通过他的完整性鉴别.不做安装和运行时的限制(不做信任模式)
Android不会在安装的时候进行Signature Permission
的验证,他仅仅是做Signature(签名) 这步骤.
Signature Permission 和ShareUID(TODO 讲得不错要做详细)
-
Signature Permission(Signature Permission Level Permission)
相当于他对一些特权的permission 他用单独的signature 方式去验证.- 示例代码块:
<permission android:name="android.permission.HARDWARE_TEST"//权限名称,要注意命名规范
android:permissionGroup="android.permission-group.HARDWARE_CONTROLS"//在显示时对权限进行归类
android:protectionLevel="signature"// 权限安全界别
android:label="@string/permlab_hardware_test"// 在对应语言系统上显示
android:description="@string/permdesc_hardware_test"
//该权限的描述与使用
/>
上面的protectionLevel="signature"
,因此他并不是给第三方应用去使用的.对于普通的app去使用该权限的话肯定是会被拒绝的.但是对于如果是系统应用的话只要要.mk
里的config写的是security="platefrom"
那么这个app里的Signature 就会使用平台的private key
进行签名.
-
ShareUID(Share Process UID)
- 示例代码块:
android:sharedUserid="xxx"
其实Android中的UID也是在manifest 中写的,如上面代码,那么Android重为什么要有UID.
UID其实是一个特权的概念,不同文件对一些权限会做一些限制,如对于uid="owner"
会用r/w/x 权限,而对于uid="other"
可能就会连read 的权限都没有.这样就可以使得Android中每一个 project他对于的资源目录下是属于一个private 的状态.
所以Android很好的引用了Linux自有的一些特性,将每个项目通过群组(UID)的方式分离出来.-
Process间Share UID的目的是共享资源
如果a,b,c三个应用他们之间的share UID是同一个,那么这几个应用间的资源是开源互相访问的.漏洞: 那么这样就会引出一个安全问题,如果360配置的时候将share UID设置成 QQ应用一样,而且框架允许的情况下,那么问题就来了,360可以很简单的就访问到了qq的数据.
Android中两个Apk Share相同的UID必须其签名所用的Private Key 一样.(为什么?)
google的解决方法就是,如果多个应用之间真的要设置成Share UID相同,那么前提条件就是这几个应用的私钥也必须是一样的,是同一个owner ,也就是说厂家是同一家.
- 示例代码块:
身份ID和升级的匹配
- Android中的自签名只是代表了身份,但是不代表身份是否可信任
- Android应用的identifier(鉴定者) 是Package Name:
- Package Name不一样,相互不影响,只允许同时存在(安装)
- Package Name一样,只能存在一个,允许做升级处理.
- 升级的安全性考虑
- 必须签名的证书一致(市场上假冒app)
- 如果不一致,则用户要么放弃新的应用,要么先卸载旧的,再安装新的.
- 正常的升级将不清除应用cache,以保证历史数据的持续性.
Android APK 之META INF
其实很应用的安装包,就是一个压缩包,把apk 后缀修改成.zip 就可以解压里面的数据.
-
APK的一个结构
- assets
- lib
- META-INF 里面有3个文件,相当于是摘要信息文件(签名信息CERT.RSA,CERT.SF,MANIFEST.MF)
- res
- AndroidManifest
- class.ex
签名流程
java -jar signapk.jar testkey.x509.pem testkey.pk8 update.apk update-signed.apk
Android中的权限
Android签名
中使用到的一些加密技术有:
签名(特权权限)
权限作用
细粒度特权管理
权限与操作关联
每一个权限都与对应的操作(功能)有关联.应用需要显式申请权限
如需要在AndroidManifest中去申请需要的权限.用户对权限可知(不可控)
用户对该项目使用到的app需要涉及什么权限,都是可以查看到的,但是在安装app时必须accept所有权限才可以安装,否则就无法安装,这就是不可控,但是在Android6.0后google出现了RuntimePermission,对部分单个权限是可控的,而且当系统root后,也可以通过一些管家对某个app 的单个权限进行分配.对特权权限单独控制
Android中对特权权限单独控制,这个方式其实就是通过签名来处理的.比如上面提到的sendSMS
发送短信的权限.
Android的不同权限类别
- Normal 默认,一般安装不会被显示出来.
- Dangerous 危险,安装时会有pop提示.
- Signature 签名,对于一些特权权限就需要通过签名来保护,对apk的私钥邀请与签名一样.
- SignatureOrSystem 签名or系统,对于申请权限的私钥跟签名一样,或者改app是系统app才可以使用该权限.
- 自定义权限注意
一般一些开发厂商或应用开发商会自定义一些权限.
注意:
对于自定义权限很简单,但是对于要设置他的protectionLevel这个问题还是比较关键的.如果level定义太严格,那以后拓展起来就比较差,如果定义太宽泛,就很容易出现安全漏洞.建议根据如下方式定义:
- 根据需求应用范围用户权限,按照上面的权限类别描述来定义需要的权限.
- 为了避免permission name 重复,命名规范也要注意.
- 如,百度地图在自定义权限时,该sdk提供一些api但是如果这些功能只给百度自己公司的app 用,那就可以定义protectionLevel=”SignatureOrSystem”.
Android运行时权限控制方式
下面是两种方式的描述
通过PM的CheckPermission
- Android独有的service(底层平台不具有)
- 所以需要在Android本身framework中控制
- 主流的service一般都基于binder IPC或者其他IPC提供服务
- Android真正的service都是在底层实现的,所以在最底层控制(service所在的server中)以避免逃逸控制
- 绕开Utility Function 直接 Invoke Remote Service
- 如:DayDream(屏保)
映射为OS的特定属性
- 非Android特有的service(底层平台已经提供,如File访问,TCPIP数据收发等)
- 多个入口访问: Android API,Java API, NDK C API, Shell,etc
- 底层控制准则,会聚扣在底层,所以在底层(OS层面)统一控制,这样可以避免逃逸控制.
- 所以复用OS的一些安全控制特性,比如GID
- 所以需要把Android空间的 Permission Mapping到OS的GID
- 如: 访问SDCard
因为Android是基于Linux OS的那么Linux它有的一些安全特性与GID ,Android就可以对他复用,因此在对于多接口的访问安全问题就可以解决了,可以先看下面代码:
读取SDCard的权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
SDCard权限的映射关系
<permission name="android.permission.WRITE_EXTERNAL_STORAGE"
<group gid="sdcard_rw"
/>
Android的permission 与UID/GID 的mapping
- 任何自定义权限只要符合上面xml 语法的都会在
system/etc/permissions
下面的xml文件,被系统读取并parse 在UID/GID中进行mapping. 如见system/etc/permissions
目录下的platform.xml . - 安全性问题
- 任何应用都可以为自己的permission 分配GID吗?那不是安全漏洞?
- 当然不行! 只有ROOT用户才允许新增或改写.