关键词:Sandbox(沙盒机制)Permission(权限机制)SELinux MAC机制(强制访问控制机制)ALSR(地址空间分配随机化)PIE(独立位置的可执行区域(position-independent executables))FORTIFY_SOURCE(内存溢出检查)Encrypt(加密)Certificate(证书验证,签名机制)●签名机制apk文件在发布时必须被签名(用私钥)。
签名标识应用的作者,建立应用之间的信任关系。
比如微信和qq是同一个开发者,是一个私钥,所以两者相互信任,可以相互获取信息。
使用相同私钥签名的应用,将会具备相同的UID。
关于签名的安全机制还有,如果两个应用包名相同,但是签名不同,是无法覆盖安装的。
比如你修改了qq,原先的正版没卸载,修改版是安不上去的。
在安装应用程序APK时,系统安装程序首先检查APK是否被签名,有签名才能够安装。
当应用程序升级时,需要检查新版应用的数字签名与已安装的应用程序的签名是否相同,否则,会被当作一个全新的应用程序。
通常,由同一个开发者设计的多个应用程序可采用同一私钥签名,在manifest文件中声明共享用户ID,允许它们运行在相同的进程中,这样一来,这些应用程序可以共享代码和数据资源。
Android开发者们有可能把安装包命名为相同的名字,通过不同的签名可以把它们区分开,也保证了签名不同的包不被替换掉,同时有效地防止了恶意软件替换安装的应用。
弊端:Android自签名机制允许开发人员发布未经应用市场验证的APP,从而导致应用市场鱼龙混杂。
●沙盒机制多应用模型不同应用分配不同的UID不同应用运行不同的进程系统应用的沙盒机制Dalvik虚拟机为每个应用提供一个虚拟机实例运行一个进程。
为每个应用创建一个对应于Linux底层的用户名。
应用是虚拟机实例,相互独立(沙盒的意义),当应用出现问题,可以通过消除该虚拟机实例来保证系统的安全运行。
可通过设置AndroidManifest文件中manifest标签内的ShareUserID属性。
拥有同一UserID,被认为是同一应用程序,只有两个具有相同签名的应用程序而且请求相同的shareUserID属性的时候,才会分配相同的UserID。
弊端:仍然没有办法避免某些恶意应用程序通过自签名和更改相同shareUserID 属性获得相同UserID。
●权限机制1、PermissionAndroid 应用程序安全的核心机制是权限控制。
应用程序必须在系统给予的权限中运行,不得访问未被赋予权限的其它任何内容。
程序安装时由包管理器赋予权限,运行时由应用程序框架层执行权限控制。
Android内置大约有一百多种行为或服务的权限控制,包括打电话、发短信息、访问互联网等。
应用程序在安装时必须申明其运行时需获得的权限,Android 通过检查签名和与用户的交互赋予相应权限。
权限的申请只能在安装时得到批准或拒绝,在运行过程中不得再申请任何权限。
弊端:应用程序可以自由地命名一个新的权限,无须遵循一定的命名规则和限制。
权限一经被授权给应用程序后,在应用程序的生命期间,它将不会被移除,即使声明此权限的源程序被删除。
一个系统内两个不同的权限可以共用相同的名字,以至于他们中的其中一个权限可以在未声明的前提下正常使用。
2、Android 文件(包括应用程序文件和系统文件)管理属于Linux 权限机制。
每个文件与用户ID 和用户组ID 以及三组Read / Write / eXecute(RWX)权限密切相关。
文件在创建时将被赋予不同应用程序ID,从而只能被特定的应用程序所访问,非授权的其他应用程序则是不能访问,除非它们拥有相同的ID或者该文件的访问属性设置为在全局下都是可以读写的。
另一个增强安全的设计:将镜像挂载为只读。
比较重要的可执行程序和配置文件,只有在系统初始化的时候加载。
弊端:一般来说,无论是“system”还是“root”用户都拥有整个系统中文件访问权限,而一个特定的应用程序用户则拥有本身应用程序文件访问权限。
仍然没有办法避免某些获取root权限的用户恶意访问文件系统。
3、组件封装:exported属性一个Android系统中的应用可以在其程序内将其某些组成部分的内容封装,这样可以防止其他不同的用户ID的应用程序访问他们。
这种功能实现主要是通过定义组件的“exported”属性。
如果“exported”属性设置为“假”,则组件只能被通过应用程序本身所访问,或拥有同一个user工D的其他程序通过使用sharedUserId的特征来访问。
反之,如果设置为“真”,则外部的实体可以调用或访问它。
弊端:用户设置错误导致组件被非授权访问。
●SEAndroid(MAC策略)在Linux系统中,文件的权限控制在所有者的手中。
因此,这种权限控制方式就称为自主式的,正式的英文名称为Discretionary Access Control,简称为DAC。
在理想情况下,DAC机制是没有问题的。
然而,在现实中,会产生严重的安全问题。
例如,一个用户可能会不小心将自己创建的文件的权限位错误地修改为允许其它用户访问。
如果这个用户是一个特权用户,并且它错误操作的文件是一个敏感的文件,那么就会产生严重的安全问题。
这种误操作的产生方式有三种:1. 用户执行了错误的命令2. 负责执行用户命令的程序有BUG3. 负责执行用户命令的程序受到攻击引入MAC机制:MAC的全称是Mandatory Access Control,翻译为强制访问控制。
在MAC机制中,用户、进程或者文件的权限是由管理策略决定的,而不是由它们自主决定的。
例如,我们可以设定这样的一个管理策略,不允许用户A将它创建的文件F授予用户B访问。
这样无论用户A如何修改文件F的权限位,用户B都是无法访问文件F的。
这种安全访问模型可以强有力地保护系统的安全。
SEAndroid就是一种MAC 机制。
内核中的资源在访问的过程中,一般需要获得三次检查通过:1. 一般性错误检查,例如访问的对象是否存在、访问参数是否正确等。
2. DAC检查,即基于Linux UID/GID的安全检查。
3. SELinux检查,即基于安全上下文和安全策略的安全检查。
在SEAndroid中,每一个进程和文件都会关联有一个安全上下文。
这个安全上下文由用户、角色、类型、安全级别四个部分组成,每一部分通过一个冒号来分隔。
例如,u:r:t:s0描述的就是一个SEAndroid安全上下文。
当每一个进程和文件都关联上一个安全上下文之后,系统管理员就可以基于这些安全上下文制定一个安全访问策略,用来规定什么样的进程可以访问什么样的文件。
弊端:SEAndroid安全机制并不能完全阻止我们的设备被root,但是它能保证我们的设备被root之后,一些敏感的文件仍然是不可访问,这样就可以最大程度地保护我们的设备。
内存安全相关机制:Android 1.5版本之后:1.使用ProPolice的-fstack-protector选项可以有效防止栈缓冲区溢出攻击。
ProPolice:源自IBM的stack-smashing保护程序SSP,实现类似于StackGuard的功能。
ProPolice使用编译器选项在函数调用中插入探测以检测堆栈溢出,同时对存储局部变量的位置进行重新排序,复制函数参数中的指针,使它们在数组之前。
如此,即使缓冲区溢出也不会修改指针值,防止能够控制指针的攻击者使用指针来控制程序保存数据的位置。
ProPolice嵌入gcc之中,更易于运用。
2.使用safe_iop防止整数运算溢出。
3.使用OpenBSD的dlmalloc()可以防止重复free()漏洞及防范针对堆的内存区域重组攻击。
(内存管理器,使程序不直接操作内存,分配和回收都经过内存管理器暂存)4.使用OpenBSD的calloc()防范内存分配时的整数溢出攻击。
(calloc可以在动态分配内存时对内存块进行初始化0)Android 2.3之后:1.-Wformat-security 编译选项:实现对格式描述字符串漏洞攻击的防护。
像是printf/scanf这类用到字符串的函数中,可针对非字符串格式的参数进行警告。
添加编译参数:“-Werror=format-security”,让属于format-security 的警告在编译过程中以Error的方式呈现。
2.–noexecstack编译选项:基于硬件的NX(No eXecute)机制,防范运行堆与栈中的代码。
3.使用Linux内核的内存映射mmap_min_addr()函数减少释放空指针引起的权限升级攻击(例如PPPoX socket中ops的初始化中,sendpage函数指针默认为NULL,在socket传输中,若执行到sendpage(),会对NULL指针解引用,引起内核态访问NULL指针,出现Oops。
如果用户态将0地址(通常NULL 为0)设置为可执行,那么内核代码就会顺利的执行0地址的指令。
如果0地址被恶意注入了修改当前进程ID的代码,那么当前进程就有可能从普通用户的身份变为root用户。
)。
避免低特权级用户进程在非许可的低内存空间产生映射。
这个低地址可以进行设定。
Android 4.0之后:1.地址空间分布随机化(ASLR)机制随机分配地址空间中关键区域的位置,比如代码、堆栈、库的位置。
在Ret2libc(通常用于攻击有“栈不可执行”保护措施的目标系统)攻击方式中,最为关键的一点是攻击者事先预知了特定函数。
在当一个应用程序或动态链接库,被加载时,如果其选择了被ASLR 保护,那么系统就会将其加载的基址随机设定。
这样,攻击者就无法事先预知动态库的基址,也就无法事先确定特定函数的入口地址了。
Android 4.1之后:1.PIE:position-independent executable针对代码段的地址随机化。
编译选项,用于编译共享库。
PIE是Binutils,glibc和gcc的一个功能,用于编译能像共享库一样可重分配地址的程序,这种程序必须连接到Scrt1.o。
标准的可执行程序需要固定的地址,并且只有被装载到这个地址时,程序才能正确执行。
PIE能使程序像共享库一样在主存任何位置装载,这需要将程序编译成位置无关,并链接为ELF共享对象。
2.(-Wl,-z,relro -Wl,-z,now)编译选项:只读重定位/立即绑定(Read-onlyrelocations/immediate binding)。
一般来说,.plt属性是RELRO (RELocation Read-Only),在加载到内存后会放在只读的分页中,但.got.plt 却是Read/Writeable以便支持Linker Lazy Loading,加速程序载入效率。